参考:
C++ GUI Programming with Qt 4, Second Edition
本地环境:
win10专业版,64位,Qt5.12
上一篇:
qt5-入门-自定义委托-简单例子_qt 委托-CSDN博客
https://blog.csdn.net/pxy7896/article/details/137234839
本篇重点在于接收信号。Model做了一点点改动。
效果
每个item都是可以编辑的字符串。
编辑之后,输出编辑的位置以及改动后的值(前两个数字是row index和column index,第三个是更改后的值)。
实现
自定义model
class CustomTableModel : public QAbstractTableModel
{Q_OBJECT
public:explicit CustomTableModel(QObject* parent = nullptr): QAbstractTableModel(parent){// 初始化数据//m_data << 1 << 2 << 3 << 4 << 5;}void setData(QStringList other) {this->m_data = other;}QStringList getData() {return this->m_data;}QVariant headerData(int section, Qt::Orientation orientation, int role) const override{if (role == Qt::DisplayRole){// 这个相当于将行名和列名设置为“”,实际仍然占据空间// 如果要完全隐藏需要用setVisible(false),参见最后1节return QVariant();/*if (orientation == Qt::Horizontal){return QVariant(); // 返回空的QVariant,不显示列名}else{return QVariant(); // 返回空的QVariant,不显示行名}*/}return QAbstractTableModel::headerData(section, orientation, role);}int rowCount(const QModelIndex& parent = QModelIndex()) const override{return m_data.size();}int columnCount(const QModelIndex& parent = QModelIndex()) const override{return 1;}QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override{if (!index.isValid())return QVariant();if (role == Qt::DisplayRole) {return m_data.at(index.row());}return QVariant();}Qt::ItemFlags flags(const QModelIndex& index) const override{if (!index.isValid())return Qt::NoItemFlags;return Qt::ItemIsEditable | QAbstractTableModel::flags(index);}bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override{if (index.isValid() && role == Qt::EditRole) {m_data.replace(index.row(), value.toString());// 这里发出信号了emit dataChanged(index, index);return true;}return false;}private:QStringList m_data;
};
自定义delegate
class EditableListItemDelegate : public QStyledItemDelegate
{
public:EditableListItemDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override{return QStyledItemDelegate::sizeHint(option, index);}void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override{QStyledItemDelegate::paint(painter, option, index);}// 创建编辑器QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override{QLineEdit *editor = new QLineEdit(parent);return editor;}// 设置编辑器内容void setEditorData(QWidget *editor, const QModelIndex &index) const override{QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);lineEdit->setText(index.model()->data(index).toString());}// 获取并设置更新后的文本到Modelvoid setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override{QLineEdit *lineEdit = qobject_cast<QLineEdit*>(editor);model->setData(index, lineEdit->text(), Qt::EditRole);}void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override{editor->setGeometry(option.rect);}
};
使用
注意:这里的隐藏是指完全隐藏,并非只隐藏内容。
QTableView* tableView = new QTableView;
// 隐藏列名列
tableView->horizontalHeader()->setVisible(false);
// 隐藏行号列
tableView->verticalHeader()->setVisible(false); // 设置代理
EditableListItemDelegate* delegate = new EditableListItemDelegate;
tableView->setItemDelegate(delegate);// 设置数据
CustomTableModel* model = new CustomTableModel;
model->setData({"1", "2"});
tableView->setModel(model);// 信号接收
QObject::connect(model, &CustomTableModel::dataChanged, [](const QModelIndex &topLeft, const QModelIndex &bottomRight) {qDebug() << "Data changed in model:" << topLeft.row() << topLeft.column() << "-" << bottomRight.data().toString() << endl;
});tableView->show();
done.