Qt代理的实现(按钮篇,含源码+注释)

文章目录

  • 一、按钮代理代理
  • 二、QT代理的自我理解
  • 三、QT代理的使用方法
  • 四、按钮代理实现方法
    • paint函数主要工作
    • editorEvent函数主要工作
  • 五、简单的按钮代理实现(源码)
    • CButtonDelegate代理类
        • CButtonDelegate.h
        • CButtonDelegate.cpp
    • CMainWindow调用类
      • CMainWindow.h
      • CMainWindow.cpp
  • 总结
  • 相关文章

一、按钮代理代理

下图为按钮代理使用示例图,源码在本文第五节(源码含详细注释)
Qt代理的实现(按钮篇,含源码+注释)_第1张图片
提示:不会使用Qt设计师设计界面的小伙伴点击这里

二、QT代理的自我理解

QT代理在是QT为了在View中插入控件(至少有其中一作用是这样的),如当QTableView实现翻页功能时能利索的翻页,且使用该控件操作所在行而存在的。

三、QT代理的使用方法

  1. 在使用类中实例化代理对象
  2. 使用代理对象的父对象的setItemDelegateForRow/setItemDelegateForColumn设置代理的行/列
  3. 使用connect关联相应的信号和槽

四、按钮代理实现方法

按钮代理不同于其他控件代理,按钮代理只需要实现点击操作即可,因此我在按钮代理中只实现了paint函数和editorEvent函数

paint函数主要工作

  1. 创建QStyleOptionButton的对象,并使用该对象设置的text、state、rect分别设置按钮显示文本、按钮状态、按钮绘画区域。
  2. 更改按钮状态,当鼠标的pos()值包含在按钮的rect中时需要改变状态(在我写的代码中是有一个标记按钮状态的变量,当事件函数识别到鼠标包含在按钮的rect中时则更新状态)。
  3. 绘制按钮,可以先创建一个QPushButton对象调用style()->drawControl绘制按钮,其参数为指定控件样式、按钮所绘画的参数(在我这里是QStyleOptionButton对象的指针)、绘画者、指定风格。

editorEvent函数主要工作

  1. 获取鼠标位置,判断其是否包含在按钮中,方便后面设置状态变量
  2. 识别鼠标事件当鼠标事件不同时更新不同的状态变量
  3. 当鼠标单机时发送所需信号到主函数
    不过可别忘记设置在调用代理的控件的setMouseTracking属性,否则悬浮效果是不会实现的哦

五、简单的按钮代理实现(源码)

CButtonDelegate代理类

CButtonDelegate.h

#include 
#include 

class CButtonDelegate : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit CButtonDelegate(QStyledItemDelegate *parent = nullptr);
    //设置按钮样式和文本
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;

    //相应item的编辑事件
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);

signals:
    void clicked(int row);  //发出点击信号,并传出当前行
};

CButtonDelegate.cpp

#include "CButtonDelegate.h"
#include 
#include 

CButtonDelegate::CButtonDelegate(QStyledItemDelegate *parent) : QStyledItemDelegate(parent)
{}

void CButtonDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    Q_UNUSED(index);
    QStyleOptionButton btnStyle;
    btnStyle.text = "我是按钮";             //设置按钮文本
    btnStyle.rect = option.rect;            //设置按钮区域为当前item的rect
    btnStyle.state = QStyle::State_Enabled; //设置按钮状态
    
    QPushButton btn;
    btn.style()->drawControl(QStyle::CE_PushButton, &btnStyle, painter,&btn);   //将按钮绘制出来
}

bool CButtonDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    Q_UNUSED(model);
    QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
    if(option.rect.contains(mouseEvent->pos()))
    {
        //此次将会发送两次信号(按下触发和释放触发),若只需要一次信号则添加判断即可
        //判断按下:event->type() == QEvent::MouseButtonPress
        //判断释放:event->type() == QEvent::MouseButtonRelease
        emit clicked(index.row());
    }
}

CMainWindow调用类

CMainWindow.h

#include 
#include 
#include "CButtonDelegate.h"

namespace Ui {
class CMainWindow;
}
class CMainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit CMainWindow(QWidget *parent = 0);
    ~CMainWindow();
    
private slots:
    void on_itemClick(int row); //代理按钮被点击所调用的槽函数
    
private:
    Ui::CMainWindow *ui;
    QStandardItemModel  *m_model;       //tableview中的项目模型
    CButtonDelegate     *m_delegate;    //按钮代理指针
};

#endif // CMAINWINDOW_H

CMainWindow.cpp

#include "CMainWindow.h"
#include "ui_CMainWindow.h"
#include 

CMainWindow::CMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::CMainWindow)
{
    ui->setupUi(this);

    //new出模型对象,并设置到view上
    m_model = new QStandardItemModel;
    m_model->setHorizontalHeaderLabels(
                QStringList() << "普通列" << "普通列" << "代理列");   //添加列标题

    ui->tableView->setModel(m_model);

    //new出代理对象,并设置到相应列
    m_delegate = new CButtonDelegate;
    connect(m_delegate, &CButtonDelegate::clicked, this, &CMainWindow::on_itemClick);   //连接槽函数
    ui->tableView->setItemDelegateForColumn(2, m_delegate);

    //for循环建立假数据
    for(int index = 0; index != 5; ++index)
    {
        m_model->setItem(index, 0, new QStandardItem(QString("第%1行,第0列").arg(index)));
        m_model->setItem(index, 1, new QStandardItem(QString("第%1行,第1列").arg(index)));
    }
}

CMainWindow::~CMainWindow()
{
	delete m_delegate;
	delete m_model;
    delete ui;
}

void CMainWindow::on_itemClick(int row)
{
    qDebug() << QString("点击了第%1行").arg(row);
}

总结

本文按钮代理代码并未设置悬浮、按下、释放的效果,其实是可以设置的,设置按钮的QSS或者按钮状态应该都是可以的

相关文章

Qt代理的实现(常规控件篇,含源码+注释)
Qt之QTableView的简单使用(含源码+注释)
Qt之QTableView设置多列表头复选框(自定义QHeaderView)、单元格复选框(含源码+注释)
Qt之QSortFilterProxyModel的简单使用(QTableView搜索功能,含源码+注释)
Qt之QTreeView的简单使用(含源码+注释)
Qt之QListView的简单使用(含源码+注释)

友情提示——哪里看不懂可私哦,让我们一起互相进步吧
(创作不易,请留下一个免费的赞叭 谢谢 ^o^/)

注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。
注:如有侵权,请联系作者删除

你可能感兴趣的:(Qt,qt,开发语言,ui,c++)