删除最后一行时,QTableWidget 的单元格小部件无法正确显示
QTableWidget's cell widget not displaying correctly when last row deleted
我有一个 QTableWidget,它以 QPushButtons 作为单元格小部件。我使用这些按钮作为从 table 中删除一行的方法。我遇到了一个问题,QPushButtons 可能会意外地从它们的单元格中移动。下图显示了正在发生的事情。
这发生在以下特定情况下:用户 1) 在 table 的最后一行中选择了一个单元格,2) 该单元格包含一个删除按钮,以及 3) 垂直滚动条是移动到最后一行部分可见。
下面是一个会产生此问题的非常小的示例。用户需要使用滚动条向上滚动一个tick,然后按下最后一个删除按钮。
mainwindow.h:
#pragma once
#include <QMainWindow>
class QSignalMapper;
class QTableWidget;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void DeletePressed(int row);
private:
QSignalMapper* signalMapper_;
QTableWidget* table_;
};
mainwindow.cpp:
#include "mainwindow.h"
#include <QGridLayout>
#include <QSignalMapper>
#include <QTableWidget>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
signalMapper_(new QSignalMapper(this)),
table_(new QTableWidget())
{
setCentralWidget( new QWidget );
this->setFixedSize(200,300);
QGridLayout *layout = new QGridLayout(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()
{
}
void MainWindow::DeletePressed(int row)
{
table_->clearSelection(); // <- added clear selection before remove row
table_->removeRow(row);
}
main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main( int argc, char* argv[] )
{
QApplication app(argc, argv);
MainWindow wnd;
wnd.show();
return app.exec();
}
我认为问题源于 QTableWidget 在进行新选择时试图保持所选单元格可见。我已经尝试了 here 发布的两个答案,但都没有解决我的问题。
如果有人能告诉我如何解决这个问题,我将不胜感激。
尝试ui->tableWidget->clearSelection();
我很久以前遇到过类似的问题QtreeWidget
,我通过调用受保护的方法解决了它updateGeometries()
。
如果你没有专门化QTableView
,你不能简单地调用这个函数(因为它是受保护的),所以这里有一个简单的技巧:
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();
}
希望这能解决您的问题。
仅当滚动条为 added.to 时才会发生这种情况解决此问题您需要设置 vrticalscrollbarpolicy 以关闭滚动条,然后删除该行并根据需要通过 setverticalbarpolicy 添加滚动条。
它会解决你的问题。
我也是这样做的。
我有一个 QTableWidget,它以 QPushButtons 作为单元格小部件。我使用这些按钮作为从 table 中删除一行的方法。我遇到了一个问题,QPushButtons 可能会意外地从它们的单元格中移动。下图显示了正在发生的事情。
这发生在以下特定情况下:用户 1) 在 table 的最后一行中选择了一个单元格,2) 该单元格包含一个删除按钮,以及 3) 垂直滚动条是移动到最后一行部分可见。
下面是一个会产生此问题的非常小的示例。用户需要使用滚动条向上滚动一个tick,然后按下最后一个删除按钮。
mainwindow.h:
#pragma once
#include <QMainWindow>
class QSignalMapper;
class QTableWidget;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void DeletePressed(int row);
private:
QSignalMapper* signalMapper_;
QTableWidget* table_;
};
mainwindow.cpp:
#include "mainwindow.h"
#include <QGridLayout>
#include <QSignalMapper>
#include <QTableWidget>
#include <QPushButton>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
signalMapper_(new QSignalMapper(this)),
table_(new QTableWidget())
{
setCentralWidget( new QWidget );
this->setFixedSize(200,300);
QGridLayout *layout = new QGridLayout(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()
{
}
void MainWindow::DeletePressed(int row)
{
table_->clearSelection(); // <- added clear selection before remove row
table_->removeRow(row);
}
main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main( int argc, char* argv[] )
{
QApplication app(argc, argv);
MainWindow wnd;
wnd.show();
return app.exec();
}
我认为问题源于 QTableWidget 在进行新选择时试图保持所选单元格可见。我已经尝试了 here 发布的两个答案,但都没有解决我的问题。
如果有人能告诉我如何解决这个问题,我将不胜感激。
尝试ui->tableWidget->clearSelection();
我很久以前遇到过类似的问题QtreeWidget
,我通过调用受保护的方法解决了它updateGeometries()
。
如果你没有专门化QTableView
,你不能简单地调用这个函数(因为它是受保护的),所以这里有一个简单的技巧:
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();
}
希望这能解决您的问题。
仅当滚动条为 added.to 时才会发生这种情况解决此问题您需要设置 vrticalscrollbarpolicy 以关闭滚动条,然后删除该行并根据需要通过 setverticalbarpolicy 添加滚动条。 它会解决你的问题。 我也是这样做的。