参考:
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());
}
// 获取并设置更新后的文本到Model
void 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.