赞
踩
目录
本博文用到了Qt的model/view framework框架,如果对Qt的“模型/视图/委托”框架不懂,本博文很难读懂。如果不懂这方面的知识,请在Qt Assistant 中输入Model/View Programming 学习了解。读者本机Qt安装目录下的Examples\Qt-XX.XX.XX\widgets\itemviews目录下有很多model/view framework的例子,可以进行自学了解,其中XX.XX.XX为Qt的版本号,如:5.14.1。
因为QColumnView、QHeaderView、QListView、QTableView、QTreeView、QListWidget 、QUndoView、QTableWidget、QTreeWidget都是从QAbstractItemView继承,故本博文所说的技术点也适用于这些类,本博文以QTableView类来讲解。
业务需求是:鼠标在QTableView的项上方移动(不是按下)时,项背景色改变。即像下面那样的效果:
logTableView.h:
- #ifndef LOG_TABLE_VIEW_H
- #define LOG_TABLE_VIEW_H
-
- #include <QTableView>
-
-
- class CLogTableView : public QTableView
- {
- Q_OBJECT
-
- public:
- explicit CLogTableView(QWidget *parent = nullptr);
-
- signals:
-
- // void mouseEnterItemSigal(const QModelIndex &);
- private:
-
- /* 注意:不能重载mouseMoveEvent函数,否则QAbstractItemView::entered信号不会触发,
- 如果非要重载mouseMoveEvent函数,则在该函数中发送自定义鼠标进入视图项的信号,如本
- 类中的mouseEnterItemSigal信号
- */
- //virtual void mouseMoveEvent(QMouseEvent *event) override;
- };
-
- #endif // LOG_TABLE_VIEW_H
logTableView.cpp:
- #include "logTableView.h"
- #include<QMouseEvent>
- CLogTableView::CLogTableView(QWidget *parent)
- : QTableView(parent)
- {
- setMouseTracking(true);
- }
-
- /* 注意:不能重载mouseMoveEvent函数,否则QAbstractItemView::entered信号不会触发,
- 如果非要重载mouseMoveEvent函数,则在该函数中发送自定义鼠标进入视图项的信号,如本类
- 中的mouseEnterItemSigal信号
- */
- //void CLogTableView::mouseMoveEvent(QMouseEvent *event)
- //{
- // auto pos = event->pos();
- // auto modelIndex = this->indexAt(pos);
- // // emit mouseEnterItemSigal(modelIndex);
- // //update();
- //}
logTableModel.h:
- #ifndef LOGTABLEMODEL_H
- #define LOGTABLEMODEL_H
-
- #include <QAbstractTableModel>
-
- class CLogTableModel : public QAbstractTableModel
- {
- Q_OBJECT
-
- public:
- explicit CLogTableModel(QObject *parent = nullptr);
-
- public:
-
- /*功能:向外层发送日志信息
- *参数1:日志具体内容
- *参数2:日志来源的模块,如:设备管理模块
- *参数3:日志级别
- */
- void addLog(const QString&qsLog, const QString&qsLogSrcModule, int nLogEvel);
-
- private:
- // Basic functionality:
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
-
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-
- virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
- private:
- QVariant doDecorationRole(int nLogEvel) const;
-
- QVariant doForegroundRole(int nLogEvel) const;
-
-
- private:
-
- QStringList m_lstLogInfo;
-
- };
-
- #endif // LOGTABLEMODEL_H
logTableModel.cpp:
- #include "logTableModel.h"
- #include<QIcon>
- #include<QBrush>
-
- CLogTableModel::CLogTableModel(QObject *parent)
- : QAbstractTableModel(parent)
- {
-
- }
-
- int CLogTableModel::rowCount(const QModelIndex &parent) const
- {
- if (parent.isValid())
- return 0;
-
- return static_cast<int>(m_lstLogInfo.size() / 3);
- }
-
- int CLogTableModel::columnCount(const QModelIndex &parent) const
- {
- if (parent.isValid())
- return 0;
-
- return 1;
- }
-
- QVariant CLogTableModel::data(const QModelIndex &index, int role) const
- {
- if (!index.isValid())
- return QVariant();
-
- auto rowIndex = index.row();
- auto rowCount = m_lstLogInfo.size() / 3;
- if((rowIndex < 0) || ( rowCount <= rowIndex))
- {
- Q_ASSERT(0);
- return QVariant();
- }
-
- // 以下这么做的目的是为了让最近产生的日志排在最顶部,最久产生的日志排在最底部
- auto logIndex = 3 * rowIndex;
- auto qsLog = m_lstLogInfo[logIndex];
- auto qsLogSrcModule = m_lstLogInfo[logIndex + 1];
- auto nLogEvel = m_lstLogInfo[logIndex + 2].toInt();
-
- auto columnIndex = index.column();
-
- switch (role)
- {
- case Qt::DisplayRole:
- {
- switch (columnIndex)
- {
- case 0:
- {
- return qsLog;
- }
- }
- }
- break;
- case Qt::DecorationRole:
- {
- return doDecorationRole(nLogEvel);
- }
- break;
- case Qt::ForegroundRole:
- {
- return doForegroundRole(nLogEvel);
- }
- break;
-
- } // end switch role
-
- return QVariant();
- }
-
- Qt::ItemFlags CLogTableModel::flags(const QModelIndex &index) const
- {
- Q_UNUSED(index);
-
- return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
- }
-
- QVariant CLogTableModel::doForegroundRole(int nLogEvel) const
- {
- switch (nLogEvel)
- {
- case 1:
- {
- return QBrush(Qt::yellow);
- }
- break;
- case 2
- case 3:
- {
- return QBrush(Qt::red);
- }
- break;
- default:
- {
-
- }
- break;
- }
-
- return QVariant();
- }
-
- QVariant CLogTableModel::doDecorationRole(int nLogEvel) const
- {
- QIcon icon;
- switch (nLogEvel)
- {
- case 0:
- {
- icon.addFile(QLatin1String(":/logWnd/image/log/normal.png"));
- return icon;
- }
- break;
- case 1:
- {
- icon.addFile(QLatin1String(":/logWnd/image/log/warn.png"));
- return icon;
- }
- break;
- case 2:
- case 3:
- {
- icon.addFile(QLatin1String(":/logWnd/image/log/error.png"));
- return icon;
- }
- break;
- default:
- {
- return icon;
- }
- break;
- }
-
- return QVariant();
- }
-
-
- void CLogTableModel::addLog(const QString&qsLog, const QString&qsLogSrcModule, int nLogEvel)
- {
- beginResetModel();
-
- if(m_lstLogInfo.size() >= 50)
- {
- m_lstLogInfo.clear();
- }
-
- auto qsLogEvel = QString::number(nLogEvel);
- m_lstLogInfo.insert(0, qsLog);
- m_lstLogInfo.insert(1, qsLogSrcModule);
- m_lstLogInfo.insert(2, qsLogEvel);
-
- endResetModel();
- }
-
logItemDelegate.h:
- #ifndef CLOGITEMDELEGATE_H
- #define CLOGITEMDELEGATE_H
-
- #include <QStyledItemDelegate>
-
- class CLogItemDelegate : public QStyledItemDelegate
- {
- Q_OBJECT
-
- public:
- explicit CLogItemDelegate(QObject *parent = nullptr);
-
- public:
- void enterItem(const QModelIndex &index);
- private:
- void paint(QPainter *painter, const QStyleOptionViewItem &option,
- const QModelIndex &index) const override;
-
- private:
-
- QModelIndex m_curIndex;
- };
-
- #endif // CLOGITEMDELEGATE_H
logItemDelegate.cpp:
- #include "logItemDelegate.h"
- #include<QPainter>
-
- CLogItemDelegate::CLogItemDelegate(QObject *parent)
- : QStyledItemDelegate(parent)
- {
- }
-
- void CLogItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
- {
- if (m_curIndex.row() == index.row())
- {
- // 可以把第2个参数换成你想要的任何颜色
- painter->fillRect(option.rect, option.palette.highlight());
- }
-
- QStyledItemDelegate::paint(painter, option, index);
- }
-
-
- void CLogItemDelegate::enterItem(const QModelIndex &index)
- {
- if(!index.isValid())
- {
- return;
- }
-
- m_curIndex = index;
- }
调用方代码如下:
- #include "logWnd.h"
- #include "ui_logWnd.h"
- #include<QPainter>
- #include "logTableModel.h"
- #include"logItemDelegate.h"
-
- CLogWnd::CLogWnd(QWidget *parent) : QWidget(parent),
- ui(new Ui::CLogWnd)
- {
- ui->setupUi(this);
- this->resize(650, 1200);
- this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Window);
-
- // 创建模型类
- m_pLogTableModel = new CLogTableModel(this);
- ui->logTv->setModel(m_pLogTableModel);
-
- // 创建委托类
- auto pLogItemDelegate = new CLogItemDelegate(this);
- ui->logTv->setItemDelegate(pLogItemDelegate);
-
- ui->logTv->horizontalHeader()->hide();
- ui->logTv->verticalHeader()->hide();
- ui->logTv->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);
-
- // 连接entered信号
- connect(ui->logTv, &CLogTableView::entered, pLogItemDelegate, &CLogItemDelegate::enterItem);
-
- // connect(ui->logTv, &QAbstractItemView::mouseEnterItemSigal, pLogItemDelegate, &CLogItemDelegate::enterItem);
-
- }
-
- void CLogWnd::addLog(const QString&qsLog, const QString&qsLogSrcModule, int nLogEvel)
- {
- m_pLogTableModel->addLog(qsLog, qsLogSrcModule, nLogEvel);
- }
-
调用:
- auto pLogWnd = new CLogWnd(this);
- pLogWnd->addLog("a", "a1", 0);
- pLogWnd->addLog("b", "b1", 2);
- pLogWnd->addLog("c", "c1", 2;
功能实现说明如下:
现实中,经常发现QAbstractItemView类的entered信号不会激发,解决方法,参见:
QAbstractItemView类如:QTreeView、QTableView、QTableWidget不发送entered信号的问题解决
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。