[Qt] 点击QTableWidget item项后键盘输入导致崩溃

复现场景

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;
}

在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值