FAQ Qt
FAQ QtConsultez toutes les FAQ
Nombre d'auteurs : 26, nombre de questions : 298, dernière mise à jour : 15 juin 2021
- Comment créer une QDialog sans bouton dans la barre de titre ?
- Pourquoi le texte n'est-il pas anti aliasé ?
- Comment activer la multisélection dans un QCalendarWidget ?
- Comment intégrer un fichier ui de Qt Designer dans un projet
- Comment avoir une barre à outils sur la droite de l'aire du dock supérieur ?
- Comment puis-je ajouter une deuxième boite à outils sur une ligne différente ?
- Comment puis-je redimensionner un QDockWidget depuis le code ?
- Comment enlever les icônes des barres de titres fenêtres MDI-enfant ?
- Comment puis-je dessiner un menu sur la droite de la barre de menus ?
- Comment faire pour qu'un texte long soit élidé ?
- Comment Qt sélectionne-t-il une police pour l'application ?
Vous pouvez créer une QDialog sans boutons dans la barre des titres en spécifiant une combinaison de paramètres fournie par votre gestionnaire de fenêtres.
L'exemple ci-dessous montre une façon de le faire. Si vous voyez toujours les boutons de la barre des titres, c'est que votre gestionnaire de fenêtres ne supporte pas cette manipulation et que cela n'est donc pas possible avec Qt.
#include
<QtGui>
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
QDialog
box(0
, Qt
::
WindowTitleHint);
box.show();
return
app.exec();
}
L'anti aliasing de texte de Qt se base sur la gestion des polices du système hôte. Si une police n'est pas anti aliasée, cela peut venir du fait que c'est une police bitmap ou que le système hôte ne le supporte pas. Par exemple, avec X11, xft est nécessaire pour dessiner des polices anti aliasées.
Il est possible d'indiquer un style à QFont en utilisant QFont::StyleStrategy, afin d'indiquer de ne pas utiliser des polices bitmap. Selon les polices disponibles sur le système et les familles de polices, cela peut ne pas fonctionner.
Sur Windows 2000, les polices, selon la taille, ne sont pas anti aliasées, afin de rendre le texte lisible.
Il n'y a pas de fonction pour activer la multisélection dans un QCalendarWidget. Néanmoins, vous pouvez utiliser un filtre d'événements sur la vue du QTableView utilisé par le QCalendarWidget afin de vérifier si la touche 'Shift' est appuyé. Si c'est le cas, il faut sélectionner le QModelIndexes approprié. L'exemple ci-dessous montre la façon de faire. Veuillez prendre en compte que l'exemple demande quelques personnalisation pour l'intégrer dans votre code. Par exemple il ne marche que sont on sélectionne les dates en avant et non en arrière.
#include
<QtGui>
class
CalendarWidget : public
QCalendarWidget
{
Q_OBJECT
public
:
CalendarWidget(QWidget
*
parent =
0
) : QCalendarWidget
(parent)
{
view =
qFindChild
<
QTableView
*>
(this
);
view->
viewport()->
installEventFilter(this
);
}
bool
eventFilter(QObject
*
obj, QEvent
*
event)
{
if
(obj->
parent() &&
obj->
parent() ==
view) {
if
(event->
type() ==
QEvent
::
MouseButtonPress ||
event->
type() ==
QEvent
::
MouseButtonRelease) {
QMouseEvent
*
me =
static_cast
<
QMouseEvent
*>
(event);
QPoint
pos =
me->
pos();
if
(event->
type() ==
QEvent
::
MouseButtonPress &&
!
(me->
modifiers() &
Qt
::
ShiftModifier)) {
QModelIndex
idx =
view->
indexAt(pos);
if
(idx.row() !=
0
&&
idx.column() !=
0
)
startIndex =
idx;
}
else
if
(event->
type() ==
QEvent
::
MouseButtonRelease &&
me->
modifiers() &
Qt
::
ShiftModifier) {
QModelIndex
idx =
view->
indexAt(pos);
if
(idx.row() !=
0
&&
idx.column() !=
0
)
endIndex =
idx;
else
return
false
;
if
(!
startIndex.isValid())
startIndex =
view->
selectionModel()->
selectedIndexes().first();
endIndex =
view->
indexAt(pos);
int
rowStart =
startIndex.row();
int
rowEnd =
endIndex.row();
int
colStart =
startIndex.column();
int
colEnd =
endIndex.column();
QItemSelection
sel;
for
(int
i =
rowStart; i <=
rowEnd; i++
) {
if
(i ==
rowStart &&
i !=
rowEnd) {
for
(int
j =
colStart;
j <
view->
model()->
columnCount(); j++
)
view->
selectionModel()->
select(
view->
model()->
index(i, j),
QItemSelectionModel
::
Select);
}
else
if
(i ==
rowEnd) {
int
start =
(i ==
rowStart) ? colStart : 1
;
for
(int
j =
start; j <
colEnd; j++
)
view->
selectionModel()->
select(
view->
model()->
index(i, j),
QItemSelectionModel
::
Select);
}
else
{
for
(int
j =
1
; j <
view->
model()->
columnCount(); j++
)
view->
selectionModel()->
select(
view->
model()->
index(i, j),
QItemSelectionModel
::
Select);
}
}
view->
selectionModel()->
select(endIndex,
QItemSelectionModel
::
Select);
return
true
;
}
}
return
false
;
}
else
{
return
QCalendarWidget
::
eventFilter(obj, event);
}
}
private
:
QTableView
*
view;
QPersistentModelIndex
startIndex;
QPersistentModelIndex
endIndex;
}
;
#include
"main.moc"
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
CalendarWidget calendar;
calendar.show();
return
app.exec();
}
Qt Designer permet de placer des composants graphiques (widget) et de changer leurs propriétés. Son avantage est de montrer directement le rendu. Chaque composant est en fait un objet utilisable dans le code. Le fichier .ui créé avec Qt Designer définit les attributs des objets tels qu'ils ont été configurés graphiquement. Il faut ensuite intégrer ces objets dans le projet pour les utiliser/modifier et les afficher. Il y a pour cela plusieurs manières de faire décrites dans la documentation.
- créer une fenêtre, boîte de dialogue, widget dans Qt Designer ;
- enregistrer un fichier .ui à partir de l'interface créée ;
- transformer ce fichier .ui en source C++ avec la commande uic ;
- inclure le source généré dans le code du projet et instancier la classe Ui::nomObjetPrincipal selon une des techniques de la documentation citée ci-dessus.
qmake permet d'automatiser une partie des étapes. En ajoutant le fichier .ui dans le fichier .pro FORMS += exemple.ui, l'appel de qmake automatisera l'étape 3.
Si on utilise Qt Creator, créer un form ajoute automatiquement le fichier .ui au fichier projet (étape 3). En créant le form avec une classe, le code instanciant la classe Ui::nomObjetPrincipal sera inclus dans une classe générée automatiquement (étape 4).
Il n'y a aucune fonction pour effectuer ceci, mais vous pouvez toujours jouer avec les polices de taille pour y arriver. Voici un exemple :
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
QMainWindow
box;
QToolBar
*
toolBar =
new
QToolBar
(&
box);
QToolBar
*
toolBar2 =
new
QToolBar
(&
box);
toolBar->
setSizePolicy(QSizePolicy
::
Maximum, QSizePolicy
::
Maximum);
box.addToolBar(toolBar);
box.addToolBar(toolBar2);
QAction
*
action =
toolBar->
addAction("one"
);
QAction
*
action2 =
toolBar2->
addAction("right"
);
box.show();
return
app.exec();
}
Vous pouvez appeler insertToolBarBreak() ou addToolBarBreak() dans la QMainWindow lorsque vous ajoutez les boites à outils. Cela va provoquer l'ajout d'une nouvelle ligne dans l'aire des boites à outils ce qui fera que les prochaines boites à outils seront sur la nouvelle ligne.
#include
<QtGui>
#include
<QToolBar>
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
QMainWindow
box;
QToolBar
*
pToolBar1 =
new
QToolBar
(QString
("ToolBar1"
));
QToolBar
*
pToolBar2 =
new
QToolBar
(QString
("ToolBar2"
));
QToolBar
*
pToolBar3 =
new
QToolBar
(QString
("ToolBar3"
));
QToolBar
*
pToolBar4 =
new
QToolBar
(QString
("ToolBar4"
));
QToolBar
*
pToolBar5 =
new
QToolBar
(QString
("ToolBar5"
));
box.addToolBar(pToolBar1);
box.addToolBar(pToolBar2);
box.addToolBarBreak();
box.addToolBar(pToolBar3);
box.addToolBar(pToolBar4);
box.addToolBar(pToolBar5);
box.insertToolBarBreak(pToolBar5);
box.show();
return
app.exec();
}
Lien : QMainWindow
Lorsque vous ajoutez le QDockWidget à la fenêtre principale, celui-ci devient partie intégrante du layout de la fenêtre et les tailles que vous lui donnerez seront donc ignorées. Vous pouvez toujours réimplémenter sizeHint() pour le widget contenu dans le QDockWidget afin de lui donner une taille recommandée (preferred size) ou alors vous pouvez appeler setFixedSize() pour lui donner une taille fixe. Notez que depuis que QDockWidget agit comme une surcouche pour ses widgets enfants, vos indices de tailles (size hint), les tailles minimales et maximales ainsi que les polices de redimensionnement doivent être réimplémentées dans le widget enfant. QDockWidget les respectera, en ajustant ses propres contraintes avec le cadre et le titre. Les contraintes de taille ne doivent pas être définies dans le QDockWidget, car elles varient si l'objet est arrimé ; un QDockWidget arrimé n'a pas de cadre et une barre de titre plus petite.
#include
<QtGui>
class
Label : public
QLabel
{
public
:
Label(QWidget
*
parent) : QLabel
(parent)
{
setAutoFillBackground(true
);
setSizePolicy(QSizePolicy
::
Expanding, QSizePolicy
::
Expanding);
QPalette
pal =
palette();
pal.setBrush(QPalette
::
Window, Qt
::
red);
setText("The label"
);
setPalette(pal);
}
QSize
sizeHint() const
{
return
QSize
(400
, 500
);
}
}
;
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
QMainWindow
box;
box.setCentralWidget(new
QLabel
("Widget central"
, &
box));
QDockWidget
*
dock =
new
QDockWidget
(&
box);
dock->
setWidget(new
Label(dock));
box.addDockWidget(Qt
::
TopDockWidgetArea, dock );
box.show();
return
app.exec();
}
Vous pouvez facilement cacher les icônes en appelant setWindowIcon() avec un QPixmap transparent:
QPixmap
pix(16
,16
);
pix.fill(Qt
::
transparent);
child->
setWindowIcon(QIcon
(pix));
Vous pouvez insérer un séparateur avant l'action du menu.
Le séparateur sera dessiné selon le style utilisé. Il ne va pas l'être avec le style Windows(XP). Donc vous pouvez soit appeler menuBar()->setStyle(new QMotifStyle()), soit surcharger le style et réimplémenter l'indice de style (styleHint) afin de retourner l'indice SH_DrawMenuBarSeparator.
#include
<QtGui>
class
Style : public
QWindowsStyle
{
public
:
Style()
{}
int
styleHint(StyleHint hint, const
QStyleOption
*
option =
0
, const
QWidget
*
widget =
0
, QStyleHintReturn
*
returnData =
0
) const
{
if
(hint ==
QStyle
::
SH_DrawMenuBarSeparator)
return
1
;
return
QWindowsStyle
::
styleHint(hint, option, widget, returnData);
}
}
;
class
MainWindow : public
QMainWindow
{
public
:
MainWindow()
{
QMenu
*
menu =
new
QMenu
("File"
, this
);
menu->
addAction("An action"
);
QMenu
*
menu2 =
new
QMenu
("Help"
, this
);
menu2->
addAction("Another action"
);
menuBar()->
addMenu(menu);
menuBar()->
addMenu(menu2);
// menuBar()->setStyle(new QMotifStyle()); // As an alternative to styleHint(), set the Motif style
menuBar()->
setStyle(new
Style());
menuBar()->
insertSeparator(menu2->
menuAction());
}
}
;
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
MainWindow box;
box.show();
return
app.exec();
}
Lien : QMenu::insertSeparator()
Lien : QStyle::styleHint()
Pour qu'un long texte soit élidé, on peut utiliser QFontMetrics::elidedText() et lui passer la largeur pour laquelle vous voulez le texte élidé.
#include
<QtGui/QApplication>
#include
<QMainWindow>
#include
<QLabel>
int
main(int
argc, char
**
argv)
{
QApplication
app(argc, argv);
QMainWindow
win;
QFontMetrics
*
pFM =
new
QFontMetrics
(QFont
());
QLabel
*
pLabel =
new
QLabel
(pFM->
elidedText(QString
("Un tres long texte qui va etre charcute !"
),Qt
::
ElideLeft,55
),&
win);
win.setCentralWidget(pLabel);
win.show();
return
app.exec();
}
Si vous n'avez pas spécifié de police pour votre application, Qt utilise la police par défaut sur votre machine. Celle-ci dépend de votre système d'exploitation et donc différente selon les machines. Sur Windows, c'est la police de Windows par défaut, avec X11 c'est celle présente dans qtrc. Si la police par défaut ne peut être chargée, alors Qt utilise une police prédéfinie. Si vous voulez avoir la même police dans tous les cas, vous devriez prédéfinir une police pour votre application (cela peut devenir important, notamment lorsque les polices ont de grandes différences de taille). Celle-ci doit être, bien entendu, présente sur la machine cible.
Lien : QFont