QTableWidget "Shrink to Fit"



  • I have a QTableWidget displayed in a dialog as one widget among several. This table will always have exactly three columns and five rows. It works fine, but I'm not happy with the appearance. The table is laid out in such a way that it consumes more space than is strictly necessary to show only the 5 rows and 3 columns -- the widget's frame is larger than the actual table, so there's white space along the right edge and bottom to make up the difference. No doubt there is some way to construct the widget so that it must take a specific number of pixels in each direction, but I'm hoping there's some switch I don't know about to tell the table "make yourself as large as necessary, but no larger." Is there?

    Second question: how can one get rid of the frame that appear around most widgets? For instance, on Windows, the QTableWidget appears in a "shadow box" (as though you are looking at it through a rectangular hole in a piece of cardboard). Likewise, the row and column headings appear in such a way that they look like buttons. How can they appear simply as text -- more like a QLabel?

    I'm new to Qt as of about 10 days ago, and liking it a lot.

    Randall



  • Hi! And welcome to DevNet.
    For your first question you can create function which resize the qtablewidget:
    @void MainWindow::adjustTableSize()
    {
    ui->tableWidget->resizeColumnsToContent();
    ui->tableWidget->resizeRowsToContent();

    QRect rect = ui->tableWidget->geometry();
    int tableWidth = 2 + ui->tableWidget->verticalHeader()->width();
    for(int i = 0; i < ui->tableWidget->columnCount(); i++){
        tableWidth += ui->tableWidget->columnWidth(i);
    }
    rect.setWidth(tableWidth);
    int tableHeight = 2 + ui->tableWidget->horizontalHeader()->height();
    for(int i = 0; i < ui->tableWidget->rowCount(); i++){
        tableHeight += ui->tableWidget->rowHeight(i);
    }
    rect.setHeight(tableHeight);
    
    ui->tableWidget->setGeometry(rect);
    

    }@
    and about your second question. You can use qss for that. Start point for you:
    @QHeaderView::section {
    color: black;
    border: 1px solid #6c6c6c;
    }@
    set this qss with:
    @ui->tableWidget->setStyleSheet ( const QString & styleSheet )@



  • QTableWidget is-a QFrame (ultimately) so you can call setFrameStyle() and other QFrame functions to adjust the frame.



  • qxoz, when I apply the setGeometry() method, it has no effect. Even if I use explicit values, like
    @tableWidget->setGeometry(0,0,100,100);@

    there is still no effect. I've tried variations on that theme, involving making changes to the QRect obtained from tableWidget->geometry(). Again, no effect on the widget's appearance whatsoever.

    Does the code in your example work for you? It might not since it won't compile -- there is no resizeColumnsToContent() method; it's called resizeColumnsToContents().

    Here's a stripped-down version of the code involved. This is the constructor for a class that extends QDialog:

    @
    TestDialog::TestDialog(QWidget *parent) : QDialog(parent)
    {
    // Set up the spreadsheet for input.
    testSheet = new QTableWidget();
    testSheet->setRowCount(5);
    testSheet->setColumnCount(3);

    testSheet->setColumnWidth(0,70);
    testSheet->setColumnWidth(1,70);
    testSheet->setColumnWidth(2,70);

    for (int i = 0; i < 5; i++)
    testSheet->setRowHeight(i,25);

    testSheet->setAlternatingRowColors(true);
    testSheet->setCornerButtonEnabled(false);

    // Thank you, ChrisW67
    testSheet->setFrameStyle(QFrame::NoFrame);

    QTableWidgetItem *item = new QTableWidgetItem(QString("1.987493"));
    testSheet->setItem(0,0,item);

    // This has no effect. The appearance is the same whether I
    // comment this out or not.
    QRect tableRect = testSheet->geometry();
    tableRect.setWidth(300);
    tableRect.setHeight(300);
    testSheet->setGeometry(tableRect);

    // I thought that adding stretch in the layout might help...it does not.
    sheetLayout = new QHBoxLayout();
    sheetLayout->addStretch();
    sheetLayout->addWidget(testSheet);
    sheetLayout->addStretch();

    // Blah, blah...add some buttons...code omitted.

    // Bring everything together.
    topLayout = new QVBoxLayout();
    topLayout->addLayout(sheetLayout);
    topLayout->addStretch();
    topLayout->addLayout(buttonLayout);

    // All done.
    this->setLayout(topLayout);

    setWindowTitle(tr("QTableWidget Problem"));
    }@



  • I have a solution. qxoz is basically correct, after making two changes.

    Here is the TestDialog constructor again, but this time it works as desired.
    @
    TestDialog::TestDialog(QWidget *parent) : QDialog(parent)
    {
    // Set up the spreadsheet for input.
    testSheet = new QTableWidget();
    testSheet->setRowCount(5);
    testSheet->setColumnCount(3);

      testSheet->setColumnWidth(0,70);
      testSheet->setColumnWidth(1,70);
      testSheet->setColumnWidth(2,70);
     
      for (int i = 0; i < 5; i++)
        testSheet->setRowHeight(i,25);
     
      testSheet->setAlternatingRowColors(true);
      testSheet->setCornerButtonEnabled(false);
     
      // Thank you, ChrisW67
      testSheet->setFrameStyle(QFrame::NoFrame);
     
      QTableWidgetItem *item = new QTableWidgetItem(QString("1.987493"));
      testSheet->setItem(0,0,item);
    
      // I added this to make the widget recalculate its dimensions
      // before trying to adjust them.
      sheet->hide();
      sheet->show();
     
      // This is from qxoz, with some small changes. I don't seem to need
      // the '+2' in his version. It makes the widget too large.
      int tableWidth = sheet->verticalHeader()->width();
      for (int i = 0; i < sheet->columnCount(); i++)
        tableWidth += sheet->columnWidth(i);
    
      int tableHeight = sheet->horizontalHeader()->height();
      for (int i = 0; i < sheet->rowCount(); i++)
        tableHeight += sheet->rowHeight(i);
    
      // I still don't see why qxoz's suggestion to use setGeometry() does
      // not work, but this does work.
      sheet->setMaximumHeight(tableHeight);
      sheet->setMinimumHeight(tableHeight);
      sheet->setMaximumWidth(tableWidth);
      sheet->setMinimumWidth(tableWidth);
     
      // I thought that adding stretch in the layout might help...it does not.
      sheetLayout = new QHBoxLayout();
      sheetLayout->addStretch();
      sheetLayout->addWidget(testSheet);
      sheetLayout->addStretch();
     
      // Blah, blah...add some buttons...code omitted.
     
      // Bring everything together.
      topLayout = new QVBoxLayout();
      topLayout->addLayout(sheetLayout);
      topLayout->addStretch();
      topLayout->addLayout(buttonLayout);
     
      // All done.
      this->setLayout(topLayout);
     
      setWindowTitle(tr("QTableWidget Problem"));
    }
    

    @

    The above gets the output I want, even if the code to do it is sort of a hack. There really ought to be a way of telling the widget to do this itself.

    Concerning my other question about changing the appearance of the table's headers, it turns out that you have to sub-class QHeaderView and reimplement the paintSection() method. You can't do it by changing the delegate for the header because, even though the framework to do that seems to be there in the relevant classes, the documentation of QHeaderView says that "calling a header's setItemDelegate() function will have no effect."

    Thanks for the help.



  • [quote author="RSFJ" date="1367519882"]
    @// I still don't see why qxoz's suggestion to use setGeometry() does
    // not work, but this does work.
    sheet->setMaximumHeight(tableHeight);
    sheet->setMinimumHeight(tableHeight);
    sheet->setMaximumWidth(tableWidth);
    sheet->setMinimumWidth(tableWidth);@
    [/quote]
    Thats because layout change the geometry when you add tableWidget to it. You can setGeometry after settings layouts but every changes of form size will broke your geometry settings. I tryed play with sizepolicy of widget but there are no useful effect. So i think settings minimum and maximums is only solution for this case.



  • About your second question. Probably i don't understand you correctly can you explain your goal and why qss not enough for you?



  • Yes, I see now. Your suggestion is much cleaner than sub-classing QHeaderView (which isn't that hard). If you say
    @QString style = "::section{"
    "padding-right: 3px;"
    "border: 0px; }";

    sheet->horizontalHeader()->setStyleSheet(style);
    @

    then you get headers without any sort of border. I'm new to Qt, but I'm getting the hang of it.

    Thanks



  • thanks for the post, it really helps. 5 years now and Qt still remain unaware of this issue, QTableWidget is a really badly designed class indeed.



  • Since Qt 5.2 (Dec 2013) you can use tableWidget->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); to achieve this


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.