c++qtqt4qtableview

QTableView issue with resizeEvent()


I have an object that inherits QTableView and overrides the resizeEvent() method to set the widths of the table columns to a percantage of the available space if the table as a whole is resized.

Code is as follows:

void DDUTableView::resizeEvent(QResizeEvent* ev)
{
    int num_columns = NUM_ELEMENTS(COLUMN_WIDTHS);

    if (num_columns > 0) {
        int width = ev->size().width();
        int used_width = 0;

        // Set our widths to be a percentage of the available width
        for (int i = 0; i < num_columns - 1; i++) {
            int column_width = (width * COLUMN_WIDTHS[i]) / 100;
            this->setColumnWidth(i, column_width);
            used_width += column_width;
        }
    
        // Set our last column to the remaining width
        this->setColumnWidth(num_columns - 1, width - used_width);
    }

    // Call our base resizeEvent to handle the vertical resizing which 
    // we don't bother with here
    QTableView::resizeEvent(ev);
}

This all works fine until the user manually resizes one of the columns and stretches it beyond the viewport (bringing up the horizontal scrollbar). This then triggers my resizeEvent() call which resets the column widths to the percentage defaults.

I can overcome this issue by connecting to the sectionResized() signal on the table header and setting a timer running. If the resizeEvent() is called whilst the timer is active then I don't recalculate the table widths.

Code below:

connect(horizontalHeader(), SIGNAL(sectionResized(int, int, int)), this, SLOT(slotSectionResized(int, int, int)));

void DDUTableView::slotSectionResized(int /*logicalIndex*/, int /*oldSize*/, int /*newSize*/)
{
    timer_->start(500);
}


void DDUTableView::resizeEvent(QResizeEvent* ev)
{

if (timer_->isActive()) {
    return;
}
// etc

This works, but is messy.

Can I prevent the resizeEvent() from being called if the user manually adjusts the column headers beyond the scope of the viewport? Alternatively, if not, is it possible to identify in the resizeEvent() whether this particular situation has occurred without having to set timers and the like?


Solution

  • Checking if the scrollbar is visible worked for my scenario.

    void DDUTableView::resizeEvent(QResizeEvent* ev)
    {
        if (!horizontalScrollBar()->isVisible()) {
    
            int num_columns = NUM_ELEMENTS(COLUMN_WIDTHS);
    
            if (num_columns > 0) {
                int width = ev->size().width();
                int used_width = 0;
    
                // Set our widths to be a percentage of the available width
                for (int i = 0; i < num_columns - 1; i++) {
                    int column_width = (width * COLUMN_WIDTHS[i]) / 100;
                    this->setColumnWidth(i, column_width);
                    used_width += column_width;
                }
    
                // Set our last column to the remaining width
                this->setColumnWidth(num_columns - 1, width - used_width);
            }
        }
        // Call our base resizeEvent to handle the vertical resizing which 
        // we don't bother with here
        QTableView::resizeEvent(ev);
    

    }