Comment déterminer la taille correcte d’un QTableWidget?

Existe-t-il un moyen de définir la taille “correcte” d’un QTableWidget? (Je suis un débutant) Ce code de test ne comporte que 25 lignes, dans deux fichiers, avec le fichier Test.h:

#include  class Test : public QMainWindow { Q_OBJECT public: Test(); }; 

et le fichier Test.cpp:

 #include "Test.h" Test::Test() : QMainWindow() { QVBoxLayout *vbox = new QVBoxLayout; QPushButton *btn = new QPushButton("Hello World etc etc etc etc etc"); QTableWidget *tbl = new QTableWidget(2, 2); vbox->addWidget(btn); vbox->addWidget(tbl); QWidget *w = new QWidget; setCentralWidget(w); w->setLayout(vbox); resize(1, 1); } int main(int argc, char *argv[]) { QApplication app(argc, argv); Test test; test.show(); app.exec(); } 

Puis la commande:

  qmake -project && qmake && make && ./Test 

donne la fenêtre:

Fenêtre indésirable

Mais ce que nous voulons bien sûr, c’est plus:

Fenêtre recherchée

Utiliser tbl->width() semble inutile, car il donne par défaut 640 avant test.show() et la valeur non test.show() de 195 après. J’ai examiné les conseils et les stratégies de taille Qt jusqu’à ce que ma tête tourne, et j’ai essayé setResizeMode(QHeaderView::Fixed) et setStretchLastSection(false) . Peut-être que je manque quelque chose d’évident? Ceci est avec Qt 4.7.4 sur CentOS 5, si cela compte. Merci pour toute aide.

Edit : En réponse à DK, si la ligne est resize(1, 1); n’est pas présent, il y a le problème égal et opposé : la fenêtre est trop grande.

Et en réponse à Donotalo, ajoutant:

 tbl->setMaximumWidth(222); tbl->setMinimumWidth(222); tbl->setMaximumHeight(88); tbl->setMinimumHeight(88); 

donnera la taille de fenêtre souhaitée (au moins sur ma machine), mais pas de la manière souhaitée. Comment devrions-nous calculer les «constantes» 222 et 88?

Et la réponse de Ton à Qt: Comment forcer un widget caché à calculer sa mise en page? ne semble pas fonctionner ici: l’ajout de tbl->setAtsortingbute(Qt::WA_DontShowOnScreen); tbl->show(); tbl->setAtsortingbute(Qt::WA_DontShowOnScreen); tbl->show(); a laissé la valeur de tbl->width() inchangée à 640.

Le fil Comment définir une taille précise de QTableWidget pour éviter d’avoir des barres de défilement? (Archive Qt, juin 2007) entre Lingfa Yang et Susan Macchia semble résoudre ma question. Je posterai plus de détails sous peu, si mes tests fonctionnent.

Mise à jour # 1 : Mon test génère maintenant la belle fenêtre:

fenêtre de test réussie

Le code de test complet pour ceci, avec Test.h inchangé, est:

 #include "Test.h" static QSize myGetQTableWidgetSize(QTableWidget *t) { int w = t->verticalHeader()->width() + 4; // +4 seems to be needed for (int i = 0; i < t->columnCount(); i++) w += t->columnWidth(i); // seems to include gridline (on my machine) int h = t->horizontalHeader()->height() + 4; for (int i = 0; i < t->rowCount(); i++) h += t->rowHeight(i); return QSize(w, h); } static void myRedoGeometry(QWidget *w) { const bool vis = w->isVisible(); const QPoint pos = w->pos(); w->hide(); w->show(); w->setVisible(vis); if (vis && !pos.isNull()) w->move(pos); } Test::Test() : QMainWindow() { QVBoxLayout *vbox = new QVBoxLayout; QPushButton *btn = new QPushButton("Hello World etc etc etc etc etc"); QTableWidget *tbl = new QTableWidget(2, 2); vbox->addWidget(btn); vbox->addWidget(tbl); setCentralWidget(new QWidget); centralWidget()->setLayout(vbox); layout()->setSizeConstraint(QLayout::SetMinimumSize); // or SetFixedSize tbl->setVerticalHeaderItem(1, new QTableWidgetItem("two")); // change size myRedoGeometry(this); tbl->setMaximumSize(myGetQTableWidgetSize(tbl)); tbl->setMinimumSize(tbl->maximumSize()); // optional } int main(int argc, char *argv[]) { QApplication app(argc, argv); Test test; test.show(); app.exec(); } 

Quelques notes:

  • L’inclusion de verticalScrollBar()->width() dans le thread ci-dessus semble être fausse. Et, lors de mes tests, il s’agissait toujours d’une valeur par défaut de 100 ou de 15 si la barre de défilement avait été affichée.

  • Appliquer le show(); hide(); show(); hide(); La séquence juste au QTableWidget n’était pas suffisante pour forcer Qt à recalculer la géomésortinge, dans ce test. Je devais l’appliquer à la fenêtre entière.

  • Toute suggestion d’amélioration serait la bienvenue. (J’attendrai un peu avant d’accepter ma propre réponse, au cas où il y aurait de meilleures solutions.)

Mise à jour # 2 :

  • Le fil de discussion Qt-interest peut être faux (ou du moins, il n’est pas d’accord avec ma version de Qt exécutant ma machine) en ce qui concerne le calcul de la taille: le +1 pour chaque ligne de grid est inutile, mais un total de +4 est nécessaire. .

  • Je suis toujours en train de travailler avec layout()->invalidate() vs QT, par exemple : Comment prévisualiser la taille des widgets dans la disposition AVANT un show () .

Mise à jour # 3 :

  • Ceci est ma version finale – mais je n’en suis pas très heureux. Toute amélioration serait la bienvenue.

  • Des choses comme adjustSize() et layout()->invalidate() et Qt::WA_DontShowOnScreen ne semblent pas aider.

  • Réduire les widgets Qt du blog à la taille minimale requirejse est intéressant, mais utiliser setSizeConstraint() est tout aussi bon.

  • Les setSizeConstraint() et move() sont nécessaires pour les modifications ultérieures de la table, non présentées ici.

  • Il y avait une chose étrange dans mes tests, fait sur CentOS 5 avec Qt 4.6.3 et 4.7.4. Pour la hide(); show(); hide(); show(); séquence, la position de la fenêtre est enregistrée / restaurée. Mais environ 25% du temps (la configuration était irrégulière), la position restaurée serait 24 pixels plus haut sur l’écran, probablement à la hauteur du titre de la fenêtre. Et environ 10% du temps, la valeur renvoyée par pos() serait nulle . Le site Qt dit que pour X11, il a besoin d’ nifty heuristics and clever code , mais quelque chose semble cassé quelque part.

Voici ma solution (pythonique) à ce problème:

 table.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Minimum) table.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff) table.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff) table.resizeColumnsToContents() table.setFixedSize(table.horizontalHeader()->length()+table.verticalHeader()->width(), table.verticalHeader()->length()+table.horizontalHeader()->height()) 

Cela me donne une table avec une taille qui enveloppe parfaitement toutes les lignes et les colonnes.

Récemment, j’ai trouvé le même problème. J’ai testé des dizaines de fonctions trouvées par Google dans Qt Center, Qt Project, mais aucune d’entre elles ne m’a donné la taille appropriée. J’ai créé cette fonction qui, à mon avis, calcule la taille de table la plus proche. La fonction donne une taille verticale correcte mais un peu plus horizontale – on dirait qu’elle couvre toujours une barre de défilement verticale. De plus, j’ai vérifié si les dimensions de la table dépassaient la taille du bureau:

 const QRect MyApp::adjustTableSize( QTableView* tv, const QVBoxLayout* lay, const int& maxRows, const int& maxCols) { // get Desktop size using std::size_t; QDesktopWidget desktop; size_t desW = desktop.screen()->width(); size_t desH = desktop.screen()->height(); int leftM,rightM,topM,bottomM; lay->getContentsMargins(&leftM,&topM,&rightM,&bottomM); size_t extraTopHeight = topM + tv->frameWidth(); size_t extraBottomHeight = bottomM + tv->frameWidth(); size_t extraLeftWidth = leftM + tv->frameWidth(); size_t extraRightWidth = rightM + tv->frameWidth(); size_t w = tv->verticalHeader()->width() + extraLeftWidth + extraRightWidth; size_t h = tv->horizontalHeader()->height() + extraTopHeight + extraBottomHeight; for(size_t col = 0; col < maxCols; ++col) { w += tv->columnWidth(col); } for(size_t row = 0; row < maxRows; ++row ) { h += tv->rowHeight(row); } std::size_t x,y; if((w - extraLeftWidth - extraRightWidth) > desW) { x = 0; w = desW - extraLeftWidth - extraRightWidth; } else x = (desW - w)/2; if(h - extraTopHeight - extraBottomHeight - QStyle::PM_TitleBarHeight > desH) { y = extraTopHeight + QStyle::PM_TitleBarHeight; h = desH - (extraTopHeight + QStyle::PM_TitleBarHeight + extraBottomHeight); } else y = (desH - h)/2; return QRect(x,y,w,h); } 

Quelques notes de côté:

QTableView .
J’ai utilisé QTableView mais je pense que cela peut également fonctionner avec QTableWidget.

QVBoxLayout .
Je suis assez convaincu que toutes les mises en page disponibles dans Qt peuvent être utilisées dans cette fonction.

J’espère que cette fonction peut aider n’importe qui.

Je m’occupais du même problème et j’ai peaufiné les réponses précédentes pour obtenir un code de travail correct.

Tout d’abord, nous obtenons les marges de contenu de QTableWidget . Si vous souhaitez simplement ajuster sa largeur, il vous suffit de désactiver la barre de défilement horizontale:

 int w = 0, h = 0; ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); w += ui->tableWidget->contentsMargins().left() + ui->tableWidget->contentsMargins().right(); h += ui->tableWidget->contentsMargins().top() + ui->tableWidget->contentsMargins().bottom(); 

Ensuite, nous ajoutons la largeur de l’en-tête vertical à w . L’en-tête vertical est une colonne spéciale contenant des index de lignes. Elle est activée par défaut. nous ajoutons également la hauteur de l’en-tête horizontal à h . L’en-tête horizontal est une ligne spéciale contenant les titres de colonne.

 w += ui->tableWidget->verticalHeader()->width(); h += ui->tableWidget->horizontalHeader()->height(); 

Ensuite, nous ajoutons la largeur de chaque colonne à w et la hauteur de chaque ligne à h .

 for (int i=0; itableWidget->columnCount(); ++i) w += ui->tableWidget->columnWidth(i); for (int i=0; itableWidget->rowCount(); ++i) h += ui->tableWidget->rowHeight(i); 

Maintenant, si w ou h sont trop grands pour tenir sur une fenêtre, nous les réduisons pour tenir dans ui->centralWidget->contentsRect() .

 if (w > ui->centralWidget->contentsRect().width()) w = ui->centralWidget->contentsRect().width(); if (h > ui->centralWidget->contentsRect().height()) h = ui->centralWidget->contentsRect().height(); 

Malheureusement, je ne connais pas le meilleur moyen d’appliquer w et h pour définir la largeur et la hauteur de QTableWidget . Si j’utilise:

 ui->tableWidget->setMinimumWidth(w); ui->tableWidget->setMaximumWidth(w); ui->tableWidget->setMinimumHeight(h); ui->tableWidget->setMaximumHeight(h); 

L’utilisateur ne pourra alors pas redimensionner le widget. Je pense que nous devons utiliser une sorte de mise en page manuelle.

Cela peut sembler un peu hors sujet, mais si vous voulez que votre table ait une vue plus attrayante, utilisez cette commande pour redimensionner les colonnes en fonction de leurs données:

 ui->tableWidget->resizeColumnsToContents(); 

Pour obtenir la largeur du tableau, additionnez la largeur des en-têtes verticaux et horizontaux et deux fois la largeur du cadre. La même chose vaut pour la hauteur:

 w = verticalHeader()->width() + horizontalHeader()->length() + frameWidth()*2 h = horizontalHeader()->height() + verticalHeader()->length() + frameWidth()*2 

Il existe plusieurs façons de les définir en fonction de votre situation. Le mieux serait probablement de remplacer sizeHint () pour renvoyer vos valeurs. De cette façon, la table rest redimensionnable, mais en l’absence d’autres exigences, elle sera de votre taille.

La clé pour que cela fonctionne consiste à utiliser la méthode length() aux bons endroits au lieu de simplement width() ou height() . Je ne suis pas tout à fait sûr de savoir pourquoi mais ici, c’est la bonne chose à faire 😉

Je ne peux pas commenter le post de Joseph Qunesey / Celdor, je l’écris donc ici: Pour récupérer la vraie valeur de QStyle::PM_TitleBarHeight , vous devriez le faire comme suit:

 QStyle *style; if(tv->style()) { style = tv->style(); } else { style = QApplication::style(); } int titleBarHeight = style->pixelMesortingc(QStyle::PM_TitleBarHeight)); 

C’est parce que l’énum n’a pas de valeurs exactes assignées. Je pense que votre incompréhension de son fonctionnement était due à une documentation Qt trompeuse qui donne à penser que l’énumération représente directement les valeurs, ce qui n’est bien sûr pas le cas (car cela dépend du style).

apparemment, il y a – un bug peut-être? – dans la fonction horizontalHeader () -> width (); cette solution a fonctionné pour moi:

  //given a QtableWidget* called x int previous_width= x->horizontalHeader()->width();//get the width //the width is relating to all the columns including the vertical headers int previous_length=x->horizontalHeader()->length();//and the length // the length is relating to all the columns excluding the size of the vertical headers int vertical_headers_width=(previous_width-previous_length); x->resizeColumnsToContents();//now we resize x->resizeRowsToContents(); //if we call again x->horizontalHeader()->width(); // we get a number that looks to me not correct (maybe is my ignorance here) x->setFixedWidth(x->horizontalHeader()->length()+vertical_headers_width); //by adding to the length of the data columns the old width_of_verticla_headers_column we get the correct size;