1. 问题
使用Qt进行研发时,遇到一个问题,当在系统默认输入法中文(英文输入法或者搜狗就不会触发闪退)的情况下,选中QTableWidget
控件(QTableWidgetItem有焦点,但是不双击), 进行输入,会导致软件错误退出。
这个Bug在Qt的Bug记录里也存在:QTableWidgetItem cause stack overflow
2. 问题复现
输入以下代码,按照问题操作步骤,可复现问题。
cpp
ui->tableWidget->setCellWidget(0, 1, new QLineEdit);

3. 解决方案1 设置输入方式,紧急解决方案
cpp
ui->tableWidget->setInputMethodHints(Qt::ImhHiddenText);
4. 解决方案2 每个设置Item的地方使用setCellWidget
,非最优解
cpp
for (int i = 0; i < ui->tableWidget->rowCount(); ++i)
{
for (int j = 0; j < ui->tableWidget->columnCount(); ++j)
{
ui->tableWidget->setCellWidget(i, j, new QLineEdit);
}
}
5. 解决方案3 使用代理,首选建议
示例代码
.h
cpp
// 自定义代理类,继承自 QStyledItemDelegate
class SpinBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SpinBoxDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
// 创建编辑器,当用户开始编辑单元格时调用
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override
{
QSpinBox *editor = new QSpinBox(parent);
editor->setMinimum(0);
editor->setMaximum(100);
return editor;
}
// 设置编辑器的数据,将模型中的数据设置到编辑器中
void setEditorData(QWidget *editor, const QModelIndex &index) const override
{
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
// 将编辑器中的数据保存到模型中
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override
{
QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
// 更新编辑器的几何形状,确保编辑器显示在正确位置
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const override
{
editor->setGeometry(option.rect);
QStyledItemDelegate::updateEditorGeometry(editor, option, index);
}
};
调用:
cpp
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 创建一个表格视图
QTableView tableView;
// 创建一个标准的表格数据模型
QStandardItemModel model(4, 2);
model.setHeaderData(0, Qt::Horizontal, "Integer");
model.setHeaderData(1, Qt::Horizontal, "Square");
// 为表格设置数据模型
tableView.setModel(&model);
// 创建一个自定义代理实例
SpinBoxDelegate delegate;
// 将代理应用到第一列
tableView.setItemDelegateForColumn(0, &delegate);
// 填充表格数据
for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 2; ++column) {
QModelIndex index = model.index(row, column);
if (column == 0) {
model.setData(index, row);
} else {
int value = row * row;
model.setData(index, value);
}
}
}
tableView.show();
return app.exec();
}
