The thread How to set a precise size of QTableWidget to prevent from having scroll bars? (Qt-interest Archive, June 2007) between Lingfa Yang and Susan Macchia seems to resolve my question. I will post more details shortly, if my testing works.
Update #1: My test now generates the nice-looking window:
The complete test code for this, with Test.h unchanged, is:
#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();
}
Some notes:
-
The above thread’s inclusion of
verticalScrollBar()->width()
seems to be wrong. And, in my testing, this was always either a default value of 100, or the value 15, if the scrollbar had been displayed. -
Applying the
show(); hide();
sequence just to the QTableWidget was not sufficient to force Qt to recalculate the geometry, in this test. I needed to apply it to the whole window. -
Any suggestions for improvements would be welome. (I’ll wait a bit before accepting my own answer, in case there are better solutions.)
Update #2:
-
The Qt-interest thread may be wrong (or, at least, it disagrees with my version of Qt running my machine) regarding details on how to calculate the size: the +1 for each gridline is unnecessary, but an overall +4 is needed.
-
I’m still working through
layout()->invalidate()
vs. e.g. QT: How to preview sizes of widgets in layout BEFORE a show().
Update #3:
-
This is my final version–but I’m not very happy with it. Any improvements would be very welcome.
-
Things like
adjustSize()
andlayout()->invalidate()
andQt::WA_DontShowOnScreen
don’t seem to help. -
The blog Shrinking Qt widgets to minimum needed size is interesting, but using
setSizeConstraint()
is just as good. -
The
setSizeConstraint()
andmove()
methods are needed for subsequent changes to the table, not shown here. -
There was an odd thing in my testing, done on CentOS 5 with Qt 4.6.3 and 4.7.4. For the
hide(); show();
sequence, the window position is saved/restored. But about 25% of the time (the patterning was irregular) the restored position would be 24 pixels higher on the screen, presumably the height of the window title. And about 10% of the time the value returned bypos()
would be null. The Qt site says for X11 it needsnifty heuristics and clever code
for this, but something seems to be broken somewhere.