【发布时间】:2021-02-27 19:10:29
【问题描述】:
我使用QTableWidget 来表示一些用户可编辑的数据。编辑后,通过连接到表的itemChanged(QTableWidgetItem*) 信号来更新数据的内部表示。
我有一个菜单操作“保存”来保存数据,如果用户尝试关闭窗口,我会检查closeEvent 中是否修改了当前文档。如果用户在未保存修改时尝试关闭,系统会询问他们是否要保存。
现在的问题是,itemChanged 信号似乎只在表格失去输入焦点时发送。考虑这种情况:用户双击表格中的一个单元格,更改文本,然后立即单击保存。在发送itemChanged 信号之前触发保存操作,因此在用户输入实际同步之前。同样,如果用户关闭窗口。
我尝试在保存函数中主动从表中读取数据,而不是等待信号触发,但这也不起作用,因为相应项目在其编辑器打开时仍包含旧数据。 这显然是一个大问题,因为要么保存了错误的数据,要么根本没有保存,即数据丢失。
我该如何正确处理这个问题?
附件是一个演示问题的最小工作示例。出于演示目的,closeEvent 只是无条件地执行“保存”(仅在此处打印)。在实际应用中,它会先检查数据是否被修改,没有正确执行。
主窗口.h:
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QTableWidget>
#include <iostream>
#include <vector>
class MainWindow : public QMainWindow
{
Q_OBJECT
private:
std::vector<double> data;
QTableWidget* table;
public:
MainWindow(QWidget* parent = nullptr) : QMainWindow(parent)
{
data = {1.0, 2.0, 3.0};
table = new QTableWidget(this);
table->setRowCount(1);
table->setColumnCount(data.size());
for (size_t i = 0; i < data.size(); i++)
table->setItem(0, i, new QTableWidgetItem(QString::number(data[i])));
connect(table, SIGNAL(itemChanged(QTableWidgetItem*)),
SLOT(on_table_itemChanged(QTableWidgetItem*)));
setCentralWidget(table);
QMenuBar* menubar = new QMenuBar(this);
QMenu* file = new QMenu("File", menubar);
QAction* save = new QAction("Save", this);
file->addAction(save);
menubar->addMenu(file);
setMenuBar(menubar);
connect(save, SIGNAL(triggered()), SLOT(on_actionSave_triggered()));
setGeometry(0, 0, 400, 100);
}
private slots:
void on_actionSave_triggered()
{
std::cout << "data: " << data[0] << ", " << data[1] << ", " << data[2] << std::endl;
std::cout << "item 0: " << table->item(0, 0)->text().toDouble()
<< ", item 1: " << table->item(0, 1)->text().toDouble()
<< ", item 2: " << table->item(0, 2)->text().toDouble() << std::endl;
}
void on_table_itemChanged(QTableWidgetItem* item)
{
data[item->column()] = item->text().toDouble();
}
};
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
【问题讨论】:
-
您可以使用itemDoubleClicked 解决问题吗?每次双击单元格时保存单元格的值,而不是检查是否实际修改了数据。当然在检查重复项时
-
@MarKS 会在用户更改数据之前发生。此外,除非我做错了什么,否则我似乎无法在用户输入的数据仍在编辑时读取它(单元格的编辑器已打开)。
-
作为一种解决方法,您可以在 on_actionSave_triggered() 槽中启动一个单发计时器(0 ms 应该足够了,槽应该排队),并将数据保存在计时器槽中
-
一种选择是创建自己的项目委托类,并在函数
createEditor()中使用编辑器的textChanged()信号 -
@NgocMinhNguyen 这似乎可行,但让我想知道其他人是否遇到同样的问题,或者我从根本上使用了错误的方法。如果您将其写为包含
createEditor代码的答案,我会接受。
标签: c++ qt qt5 qtablewidget