
Joseph Quinsey
Gibt es beliebig Möglichkeit, die “richtige” Größe eines QTableWidget festzulegen? (Ich bin ein Neuling) Dieser Testcode ist nur 25 Zeilen lang, in zwei Dateien, mit der Datei Test.h:
#include <QtGui>
class Test : public QMainWindow {
Q_OBJECT
public:
Test();
};
und die Datei 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();
}
Dann der Befehl:
qmake -project && qmake && make && ./Test
gibt das Fenster:

Aber was wir wollen, ist natürlich eher:

Verwenden von tbl->width()
scheint nutzlos zu sein, da es einen Standardwert von gibt 640
Vor test.show()
, und der unerwünschte Wert von 195
nach. Ich habe mir die Qt-Size-Hinweise und -Richtlinien angesehen, bis sich mein Kopf drehte, und ich habe es versucht setResizeMode(QHeaderView::Fixed)
und setStretchLastSection(false)
. Vielleicht übersehe ich etwas Offensichtliches? Dies ist mit Qt 4.7.4 auf CentOS 5, falls dies von Bedeutung ist. Vielen Dank für jede Hilfe.
Bearbeiten: Als Antwort auf DK, wenn die Linie resize(1, 1);
ist nicht vorhanden, da ist die gleich und Gegenteil Problem: Das Fenster ist zu groß.
Und als Antwort auf Donotalo fügte er hinzu:
tbl->setMaximumWidth(222);
tbl->setMinimumWidth(222);
tbl->setMaximumHeight(88);
tbl->setMinimumHeight(88);
ergibt die gewünschte Fenstergröße (zumindest auf meinem Computer), aber nicht auf die gewünschte Weise. Wie sollen wir die ‘Konstanten’ berechnen? 222
und 88?
Und Tons Antwort auf Qt: Wie kann man ein verstecktes Widget zwingen, sein Layout zu berechnen? scheint hier nicht zu funktionieren: das Hinzufügen von tbl->setAttribute(Qt::WA_DontShowOnScreen); tbl->show();
ließ den Wert von tbl->width()
unverändert bei 640.

Joseph Quinsey
Der Faden Wie stelle ich eine genaue Größe von QTableWidget ein, um zu verhindern, dass Bildlaufleisten verwendet werden? (Qt-Interest-Archiv, Juni 2007) zwischen Lingfa Yang und Susan Macchia scheint meine Frage zu lösen. Ich werde in Kürze mehr Details posten, wenn meine Tests funktionieren.
Update #1: Mein Test generiert jetzt das hübsche Fenster:

Der vollständige Testcode dafür, mit unverändertem Test.h, lautet:
#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();
}
Einige Notizen:
-
Die Aufnahme von . im obigen Thread verticalScrollBar()->width()
scheint falsch zu sein. Und in meinen Tests war dies immer entweder ein Standardwert von 100 oder der Wert 15, wenn die Bildlaufleiste angezeigt wurde.
-
Anwenden der show(); hide();
Sequenz nur zum QTableWidget reichte in diesem Test nicht aus, um Qt zu zwingen, die Geometrie neu zu berechnen. Ich musste es auf das gesamte Fenster anwenden.
-
Verbesserungsvorschläge wären willkommen. (Ich werde etwas warten, bevor ich meine eigene Antwort akzeptiere, falls es bessere Lösungen gibt.)
Update #2:
-
Der Qt-Interest-Thread kann falsch sein (oder zumindest nicht übereinstimmen) mein Version von Qt läuft mein Maschine) bezüglich Details zur Berechnung der Größe: Das +1 für jede Rasterlinie ist nicht erforderlich, aber insgesamt ist +4 erforderlich.
-
ich arbeite noch durch layout()->invalidate()
vs. zB QT: Vorschau der Größe von Widgets im Layout VOR eine Show().
Update #3:
-
Dies ist meine letzte Version – aber ich bin nicht sehr glücklich damit. Irgendwelche Verbesserungen wären sehr willkommen.
-
Dinge wie adjustSize()
und layout()->invalidate()
und Qt::WA_DontShowOnScreen
scheinen nicht zu helfen.
-
Der Blog Qt-Widgets auf die erforderliche Mindestgröße verkleinern ist interessant, aber mit setSizeConstraint()
ist genauso gut.
-
Der setSizeConstraint()
und move()
Methoden werden für spätere Änderungen an der Tabelle benötigt, die hier nicht gezeigt werden.
-
Bei meinen Tests auf CentOS 5 mit Qt 4.6.3 und 4.7.4 gab es etwas Seltsames. Für die hide(); show();
Sequenz wird die Fensterposition gespeichert/wiederhergestellt. Aber in etwa 25 % der Fälle (die Musterung war unregelmäßig) war die wiederhergestellte Position 24 Pixel höher auf dem Bildschirm, vermutlich die Höhe des Fenstertitels. Und in etwa 10 % der Fälle wird der Wert von . zurückgegeben pos()
wäre Null. Der Qt-Site sagt für X11 braucht es nifty heuristics and clever code
dafür, aber irgendwo scheint etwas kaputt zu sein.

Benutzer6419667
Hier ist meine (pythonische) Lösung für dieses Problem:
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())
Dies gibt mir eine Tabelle mit einer Größe, die alle Zeilen und Spalten perfekt umschließt.
Ich hatte das gleiche Problem und habe frühere Antworten optimiert, um einen korrekten Arbeitscode zu erhalten.
Zuerst erhalten wir Inhaltsränder von QTableWidget
. Wenn Sie nur die Breite anpassen möchten, müssen Sie nur die horizontale Bildlaufleiste deaktivieren.:
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();
Dann hängen wir die Breite der vertikalen Kopfzeile an an w
. Die vertikale Kopfzeile ist eine spezielle Spalte, die Zeilenindizes enthält und standardmäßig aktiviert ist. Wir fügen auch die Höhe des horizontalen Headers an . an h
. Die horizontale Kopfzeile ist eine spezielle Zeile, die Spaltentitel enthält.
w += ui->tableWidget->verticalHeader()->width();
h += ui->tableWidget->horizontalHeader()->height();
Dann hängen wir die Breite jeder Spalte an w
, und Höhe jeder Reihe zu h
.
for (int i=0; i<ui->tableWidget->columnCount(); ++i)
w += ui->tableWidget->columnWidth(i);
for (int i=0; i<ui->tableWidget->rowCount(); ++i)
h += ui->tableWidget->rowHeight(i);
Nun, wenn w
oder h
sind zu groß, um auf das Fenster zu passen, wir verkleinern sie, damit sie hineinpassen 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();
Eine bessere Bewerbung kenne ich leider nicht w
und h
um Breite und Höhe von . einzustellen QTableWidget
. Wenn ich verwende:
ui->tableWidget->setMinimumWidth(w);
ui->tableWidget->setMaximumWidth(w);
ui->tableWidget->setMinimumHeight(h);
ui->tableWidget->setMaximumHeight(h);
Dann kann der Benutzer die Größe des Widgets überhaupt nicht ändern. Ich denke, wir müssen eine Art manuelles Layout verwenden.
Es mag etwas abseits vom Thema erscheinen, aber wenn Sie möchten, dass Ihre Tabelle eine ansprechendere Ansicht hat, verwenden Sie diesen Befehl, um die Spaltengröße an ihre Daten anzupassen:
ui->tableWidget->resizeColumnsToContents();

Celdor
Vor kurzem habe ich das gleiche Problem gefunden. Ich habe Dutzende von Funktionen getestet, die Google in Qt Center, Qt Project gefunden hat, aber keine davon hat mir die richtige Größe gegeben. Ich habe diese Funktion erstellt, von der ich glaube, dass sie die nächste Tabellengröße berechnet. Die Funktion bietet eine richtige vertikale, aber etwas größere horizontale Größe – es sieht so aus, als ob sie immer noch eine vertikale Bildlaufleiste abdeckt. Außerdem habe ich überprüft, ob die Tischabmessungen eine Desktop-Größe überschreiten:
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);
}
Ein paar Randnotizen:
QTableView.
Ich habe QTableView verwendet, aber ich denke, es kann auch mit QTableWidget funktionieren.
QVBoxLayout.
Ich bin mir ziemlich sicher, dass stattdessen jedes der in Qt verfügbaren Layouts in dieser Funktion verwendet werden kann.
Hoffe, diese Funktion kann jedem helfen.

Zbyněk Winkler
Um die Breite der Tabelle zu erhalten, addieren Sie die Breite der vertikalen und horizontalen Kopfzeilen und das Doppelte der Rahmenbreite. Das gleiche gilt für die Höhe:
w = verticalHeader()->width() + horizontalHeader()->length() + frameWidth()*2
h = horizontalHeader()->height() + verticalHeader()->length() + frameWidth()*2
Es gibt mehrere Möglichkeiten, sie je nach Ihren Umständen einzustellen. Am besten wäre es wahrscheinlich, sizeHint() zu überschreiben, um Ihre Werte zurückzugeben. Auf diese Weise bleibt der Tisch in der Größe veränderbar, aber ohne andere Anforderungen wird Ihre Größe sein.
Der Schlüssel, um dies zum Laufen zu bringen, ist die Verwendung der length()
Methode an den richtigen Stellen statt nur width()
oder height()
. Ich weiß nicht genau warum, aber hier tut es das Richtige 😉

Toby Speight
Ich kann den Beitrag von Joseph Qunesey / Celdor nicht kommentieren, also schreibe ich ihn hier rein: Um den wahren Wert von . abzurufen QStyle::PM_TitleBarHeight
, sollten Sie wie folgt vorgehen:
QStyle *style;
if(tv->style())
{
style = tv->style();
}
else
{
style = QApplication::style();
}
int titleBarHeight = style->pixelMetric(QStyle::PM_TitleBarHeight));
Dies liegt daran, dass der Aufzählung keine genauen Werte zugewiesen sind. Ich denke, Ihr Missverständnis darüber, wie es funktioniert, lag an der irreführenden Qt Dokumentation wobei es so aussieht, als ob die Aufzählung die Werte direkt repräsentiert, während dies natürlich nicht der Fall ist (da es stilabhängig ist).

Rabe
Dies ist keine Antwort auf die im Titel genannte Frage, aber ich denke, eine saubere Antwort auf das zugrunde liegende Problem.
Um ein anzuzeigen QTableWidget
in voller Größe, ohne Scrollbars, müssen Sie es einstellen sizeAdjustPolicy
zu QAbstractScrollArea::AdjustToContents
(Ich nehme an QAbstractScrollArea::AdjustToContentsOnFirstShow
würde auch funktionieren).
Außerdem möchten Sie möglicherweise die Bildlaufleisten für dieses Widget deaktivieren (wobei die Bildlaufleisten-Richtlinien für vertikale und horizontale Bildlaufleisten festgelegt werden), da sonst um das Widget herum zusätzlicher Platz für die Anzeige von Bildlaufleisten bereitgestellt wird.
Referenzen:
.
2667900cookie-checkWie bestimme ich die richtige Größe eines QTableWidget?yes
Ich habe das Gefühl, es ist einfach so
resize(1, 1);
.– DK
7. Januar ’12 bei 1:53
Vielleicht möchten Sie es versuchen
QWidget::setMinimumSize()
auf Ihre Wunschgröße.– Donotalo
7. Januar ’12 bei 3:22
Verwandte: Wie ändere ich die Größe von QTableView, damit der Bereich nicht mehr gescrollt wird?
– Joseph Quinsey
24. November ’18 um 17:20