简单描述QAbstractItemModel::dataChanged() 与 QAbstractItemModel::data() 的关系

 QAbstractItemModel::data() 在两种情况下被触发: 1) QAbstractItemModel  释放dataChanged 信号时; 2)QAbstractItemModel  调用appendRow方法时。但是 dataChanged 并不能总是触发data函数。下面用一个例子 来说明。

先建立一个mainwindow类,里面含有一个ui,ui中包含qtableview。此外mainwindow还有一个model成员,是QStandardItemModel的派生类:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QKeyEvent>
#include <QMouseEvent>
#include "model.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    model             m_LstModel;

    void            vSetHrntHeader();
private:
    Ui::MainWindow *ui;

protected:
    void            mouseDoubleClickEvent(QMouseEvent *);
    void            keyPressEvent(QKeyEvent *);
};

#endif // MAINWINDOW_H

#ifndef MODEL_H
#define MODEL_H

#include <QStandardItemModel>
#include <QKeyEvent>
#include <QVariant>


class model : public QStandardItemModel
{
    Q_OBJECT
public:
    explicit model(QObject *parent = 0);
    void            update(QKeyEvent *);
    bool			m_bGreen;
    QVariant data(const QModelIndex & , int role = Qt::DisplayRole) const;
signals:

public slots:

};

#endif // MODEL_H


当用户双击mainwindow时,model::appendRow()会被调用;当用户点击按键时,会调用model的update()函数,进而释放dataChanged()信号。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qdebug.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
	ui->tableView->setFocusPolicy(Qt::NoFocus);
    vSetHrntHeader();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::vSetHrntHeader()
{
    QStringList HrntList;
    HrntList<<"hello"<<"789"<<"123";
    m_LstModel.setHorizontalHeaderLabels(HrntList);
    ui->tableView->setModel(&m_LstModel);
    ui->tableView->setFocusPolicy(Qt::NoFocus);
    ui->tableView->setAlternatingRowColors(true);

    ui->tableView->setStyleSheet("QTableView{background-color: rgb(250, 0, 0);"
                                 "alternate-background-color: rgb(141, 163, 215);"
                                "gridline-color: rgb(0,60,0);"
                                "text-align: center;}");
    ui->tableView->verticalHeader()->setVisible(false);
}

void MainWindow::mouseDoubleClickEvent(QMouseEvent *e)
{
    QStandardItem * qitem1 = new QStandardItem(QString("a"));
    QStandardItem * qitem2 = new QStandardItem(QString("b"));
    QStandardItem * qitem3 = new QStandardItem(QString("c"));
    QList<QStandardItem *> qlstTmp;
    qlstTmp<<qitem1<<qitem2<<qitem3;
    m_LstModel.appendRow(qlstTmp);
}

void MainWindow::keyPressEvent(QKeyEvent *e)
{
	if(e->key() == Qt::Key_A)
		qDebug()<<"A pressed";
    m_LstModel.update(e);
}

#include "model.h"

model::model(QObject *parent) : QStandardItemModel(parent)
{
	m_bGreen = false;
}

void model::update(QKeyEvent *e)
{
    if(e->key() == Qt::Key_A)
    {
		m_bGreen = true;
        emit dataChanged(createIndex(0,0), createIndex(0,0));
    }
    else
    {
		m_bGreen = false;
        emit dataChanged(createIndex(0,0), createIndex(0,0));
    }
}

QVariant model::data(const QModelIndex & index, int role) const
{
    if(index.column() == 0)
    {
        if(role == Qt::BackgroundRole)
        {
            return m_bGreen? QBrush(Qt::green):QBrush(Qt::blue);
        }
		else if(role == Qt::TextAlignmentRole)
		{
			return Qt::AlignCenter;
		}
		else if(role == Qt::DisplayRole)
		{
			return QString("0");
		}
		else
		{
			return QVariant();
		}
    }
    else
    {
        if(role == Qt::BackgroundRole)
        {
            return QBrush(Qt::yellow);
        }
		else if(role == Qt::TextAlignmentRole)
		{
			return Qt::AlignLeft;
		}
		else if(role == Qt::DisplayRole)
		{
			return QString("not 0");
		}
		else
		{
			return QVariant();
		}
    }
}


现在看效果。
1)启动程序后,直接按下A键界面无反应。不仅无反应,在model::data()处设置断点,断点也不会触发。这是因为model里面没有内容。虽然dataChanged已经发射出去了,但不会触发data()



2) 双击mainwindow,data()被触发,且新添加的一行显示了出来。由于步骤1)里已经把m_bGreen设为true(这也说明dataChanged确实发出去了,只是没被data()响应),所以(0,0)的背景色就是绿的:



3) 现在按下"B"键,(0,0)又变回蓝色,说明data()可以响应dataChanged()信号了。


总结一下:
1)当QAbstractItemModel还没有内容时,data() 函数不会响应dataChanged信号;
2)当QAbstractItemModel调用 appendRow方法后,会自动调用 data();
3)只有当QAbstractItemModel有内容时,data()才会响应dataChanged()。dataChanged()的前两个变量分别表示数据变化区域的左上角和右下角。事实上,一个dataChanged()会触发data()好几次,不仅会修改响应单元格的内容,也会改变其背景色等。

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以按照以下步骤使用 QAbstractItemModel 实现一个基本的 QTableView: 1. 创建一个继承自 QAbstractItemModel 的子类,实现其中的纯虚函数 rowCount()、columnCount()、data()、setData()、flags(),分别用于返回行数、列数、单元格数据、设置单元格数据和单元格标识等操作。例如: ```cpp class MyModel : public QAbstractItemModel { public: MyModel(QObject *parent = nullptr); int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; bool setData(const QModelIndex &index, const QVariant &value, int role) override; Qt::ItemFlags flags(const QModelIndex &index) const override; private: QVector<QVector<QString>> m_data; // 存储单元格数据的二维数组 }; ``` 2. 在主窗口中创建一个 QTableView 控件,然后将其设置为模式视图(setModel() 函数),并将模型数据设置为步骤1中创建的 MyModel 对象。例如: ```cpp QTableView *tableView = new QTableView(this); MyModel *model = new MyModel(this); tableView->setModel(model); ``` 3. 可以在 MyModel 中的 data() 函数中返回具体的单元格数据,例如: ```cpp QVariant MyModel::data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole) return QVariant(); if (index.row() >= m_data.size() || index.column() >= m_data.at(0).size()) return QVariant(); return m_data.at(index.row()).at(index.column()); } ``` 4. 可以在 MyModel 中的 setData() 函数中设置具体的单元格数据,例如: ```cpp bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (index.isValid() && role == Qt::EditRole) { m_data[index.row()][index.column()] = value.toString(); emit dataChanged(index, index, {role}); return true; } return false; } ``` 5. 最后,可以在 MyModel 中的 flags() 函数中设置单元格的编辑标识,例如: ```cpp Qt::ItemFlags MyModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; } ``` 通过以上步骤,就可以使用 QAbstractItemModel 实现一个基本的 QTableView 了。需要注意的是,以上代码仅为示例,实际使用时需要根据具体需求进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值