复现场景
Qt版本 5.9.8
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->tableWidget->setRowCount(1);
ui->tableWidget->setColumnCount(2);
QLineEdit *lineEdit = new QLineEdit(this);
ui->tableWidget->setCellWidget(0, 1, lineEdit);
}
Widget::~Widget()
{
delete ui;
}
选中第一个item,在中文输入法下随便点击一个字母键,程序崩溃,在debug模式下显示的是函数调用栈溢出。如图
解决方案
这个bug实际上也有人提交到了Qt官方收集bug的地方 QTableWidgetItem cause stack overflow。但是好像没有引起关注 🤣。所有推荐 将原本使用 setCellWidget 的地方使用代理来实现效果 或者 QtableWidget的每一个项都使用 setCellWidget。
使用代理来解决问题
为了能够一直显示控件,而不是用户双击后才显示控件。我们使用
void QAbstractItemView::openPersistentEditor(const QModelIndex &index)
MyStyledItemDelegate.cpp
#include "MyStyledItemDelegate.h"
MyStyledItemDelegate::MyStyledItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
}
QWidget *MyStyledItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == 1){
QLineEdit *lineEdit = new QLineEdit(parent);
return lineEdit;
}
return QStyledItemDelegate::createEditor(parent, option, index);
}
void MyStyledItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if(index.column() == 1){
editor->setGeometry(option.rect);
return;
}
QStyledItemDelegate::updateEditorGeometry(editor, option, index);
}
void MyStyledItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *lineEdit = nullptr;
if(index.column() == 1){
lineEdit = dynamic_cast<QLineEdit*>(editor);
model->setData(index, lineEdit->text(), Qt::DisplayRole);
return;
}
QStyledItemDelegate::setModelData(editor, model, index);
}
void MyStyledItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
QLineEdit *lineEdit = nullptr;
if(index.column() == 1){
lineEdit = dynamic_cast<QLineEdit*>(editor);
lineEdit->setText(index.data(Qt::DisplayRole).toString());
return;
}
QStyledItemDelegate::setEditorData(editor, index);
}
MyStyledItemDelegate.h
#ifndef MYSTYLEDITEMDELEGATE_H
#define MYSTYLEDITEMDELEGATE_H
#include <QObject>
#include <QStyledItemDelegate>
#include <QLineEdit>
#include <QComboBox>
class MyStyledItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit MyStyledItemDelegate(QObject *parent = nullptr);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
void setEditorData(QWidget *editor, const QModelIndex &index) const;
};
#endif // MYSTYLEDITEMDELEGATE_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
ui->tableWidget->setRowCount(1);
ui->tableWidget->setColumnCount(2);
QTableWidgetItem *item0_0 = new QTableWidgetItem("nihao");
QTableWidgetItem *item0_1 = new QTableWidgetItem("hello");
ui->tableWidget->setItem(0, 0, item0_0);
ui->tableWidget->setItem(0, 1, item0_1);
ui->tableWidget->openPersistentEditor(ui->tableWidget->item(0, 1));
}
Widget::~Widget()
{
delete ui;
}