Stanton Stanton - 1 month ago 15
C++ Question

QTableWidget's cell widget not displaying correctly when last row deleted

I have a QTableWidget that has QPushButtons as cell widgets. I use these push buttons as a means to delete a row from the table. I'm having a problem where the QPushButtons can be accidentally shifted from being centered in their cell. The image below shows what is happening.

enter image description here

This occurs in the specific case where the user has 1) made selected a cell in the last row of the table, 2) that cell contains a delete button, and 3) the vertical scroll bar is moved such that the last row is partially visible.

Below is a very minimal example that will create this problem. The user needs to use the scrollbar and scroll up by one tick, then press the last delete button.

Edited to include clear selection before call to removeRow:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
signalMapper_(new QSignalMapper(this)),
table_(new QTableWidget())
{
ui->setupUi(this);
this->setFixedSize(200,300);

QGridLayout *layout = new QGridLayout(ui->centralWidget);
layout->addWidget(table_);

table_->setRowCount(0);
table_->setColumnCount(1);

// if you comment out the following line then the problem is not present
table_->setSelectionMode(QAbstractItemView::SingleSelection);

for (int i = 0; i < 20; i++) {
table_->insertRow(i);
QPushButton *button = new QPushButton("Delete");
connect(button, SIGNAL(clicked(bool)), signalMapper_, SLOT(map()));
signalMapper_->setMapping(button, i);
table_->setCellWidget(i, 0, button);
}
connect(signalMapper_, SIGNAL(mapped(int)), this, SLOT(DeletePressed(int)));

table_->setCurrentCell(19,0);
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::DeletePressed(int row)
{
table_->clearSelection(); // <- added clear selection before remove row
table_->removeRow(row);
}


I think the problem stems from the QTableWidget trying to keep the selected cell visible when a new selection is made. I have tried both of the answers posted here but neither solved my problem.

If anyone could tell me how to solve this problem I would appreciate the help.

Answer

I had a similar problem a long time ago with a QtreeWidget and I solved it by callig protected method updateGeometries().

If you did not specialize QTableView, you can't simply call this function (as it is protected), so here's a trick to simply do it:

class MyQTableView : public QTableView
{
public:
    inline void publicUpdateGeometries() { updateGeometries(); }
};

void MainWindow::DeletePressed(int row)
{
    table_->clearSelection(); // <- added clear selection before remove row
    table_->removeRow(row);

    // call the protected method QTableView::updateGeometries()
    ((MyQTableView*) table_)->publicUpdateGeometries();
}

Hope this will solve your problem.

Comments