Qt之模型/视图(自定义按钮)

简述

衍伸前面的章节,我们对QTableView实现了数据显示、自定义排序、显示复选框、进度条等功能的实现,本节主要针对自定义按钮进行讲解,这节过后,也希望大家对自定义有更深入的了解,在以后的功能开发过程中,相信无论遇到什么样式形式,我们都可以很好地实现。

  • 简述
  • 效果
  • QStyledItemDelegate
    • 源码
  • 衍伸

效果

QStyledItemDelegate

源码

.h

包含显示按钮需要用到的智能指针,按钮的宽度、高度、按钮之间的间距、鼠标的坐标等。

class TableViewDelegate: public QStyledItemDelegate
{
    Q_OBJECT

public:
    explicit TableViewDelegate(QWidget *parent = 0);
    ~TableViewDelegate();
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);

signals:
    void open(const QModelIndex &index);
    void deleteData(const QModelIndex &index);

private:
    QPoint m_mousePoint;  // 鼠标位置
    QScopedPointer<QPushButton> m_pOpenButton;
    QScopedPointer<QPushButton> m_pDeleteButton;
    QStringList m_list;
    int m_nSpacing;  // 按钮之间的间距
    int m_nWidth;  // 按钮宽度
    int m_nHeight;  // 按钮高度
    int m_nType;  // 按钮状态-1:划过 2:按下
};

.cpp

主要设置按钮样式,实现鼠标划过、按下,响应鼠标事件等操作。

TableViewDelegate::TableViewDelegate(QWidget *parent)
    : QStyledItemDelegate(parent),
      m_pOpenButton(new QPushButton()),
      m_pDeleteButton(new QPushButton()),
      m_nSpacing(5),
      m_nWidth(25),
      m_nHeight(20)
{
    // 设置按钮正常、划过、按下样式
    m_pOpenButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url(:/Images/open);}                                  QPushButton:hover {image:url(:/Images/openHover);}                                  QPushButton:pressed {image:url(:/Images/openPressed);}");

                                 m_pDeleteButton->setStyleSheet("QPushButton {border: none; background-color: transparent; image:url(:/Images/delete);}                                                                 QPushButton:hover {image:url(:/Images/deleteHover);}                                                                 QPushButton:pressed {image:url(:/Images/deletePressed);}");
                                                                m_list << QStringLiteral("打开") << QStringLiteral("删除");
}

TableViewDelegate::~TableViewDelegate()
{

}

// 绘制按钮
void TableViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem viewOption(option);
    initStyleOption(&viewOption, index);
    if (option.state.testFlag(QStyle::State_HasFocus))
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;

    QStyledItemDelegate::paint(painter, viewOption, index);

    if (index.column() == FILE_OPERATE_COLUMN)
    {
        // 计算按钮显示区域
        int nCount = m_list.count();
        int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2;
        int nTop = (option.rect.height() - m_nHeight) / 2;

        for (int i = 0; i < nCount; ++i)
        {
            // 绘制按钮
            QStyleOptionButton button;
            button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i,
                                option.rect.top() + nTop,  m_nWidth, m_nHeight);
            button.state |= QStyle::State_Enabled;
            //button.iconSize = QSize(16, 16);
            //button.icon = QIcon(QString(":/Images/%1").arg(m_list.at(i)));

            if (button.rect.contains(m_mousePoint))
            {
                if (m_nType == 0)
                {
                    button.state |= QStyle::State_MouseOver;
                    //button.icon = QIcon(QString(":/Images/%1Hover").arg(m_list.at(i)));
                }
                else if (m_nType == 1)
                {
                    button.state |= QStyle::State_Sunken;
                    //button.icon = QIcon(QString(":/Images/%1Pressed").arg(m_list.at(i)));
                }
            }

            QWidget *pWidget = (i == 0) ? m_pOpenButton.data() : m_pDeleteButton.data();
            QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter, pWidget);
        }
    }
}

// 响应按钮事件 - 划过、按下
bool TableViewDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
    if (index.column() != FILE_OPERATE_COLUMN)
        return false;

    m_nType = -1;
    bool bRepaint = false;
    QMouseEvent *pEvent = static_cast<QMouseEvent *> (event);
    m_mousePoint = pEvent->pos();

    int nCount = m_list.count();
    int nHalf = (option.rect.width() - m_nWidth * nCount - m_nSpacing * (nCount - 1)) / 2;
    int nTop = (option.rect.height() - m_nHeight) / 2;

    // 还原鼠标样式
    QApplication::restoreOverrideCursor();

    for (int i = 0; i < nCount; ++i)
    {
        QStyleOptionButton button;
        button.rect = QRect(option.rect.left() + nHalf + m_nWidth * i + m_nSpacing * i,
                            option.rect.top() + nTop,  m_nWidth, m_nHeight);

        // 鼠标位于按钮之上
        if (!button.rect.contains(m_mousePoint))
            continue;

        bRepaint = true;
        switch (event->type())
        {
        // 鼠标滑过
        case QEvent::MouseMove:
        {
            // 设置鼠标样式为手型
            QApplication::setOverrideCursor(Qt::PointingHandCursor);

            m_nType = 0;
            QToolTip::showText(pEvent->globalPos(), m_list.at(i));
            break;
        }
        // 鼠标按下
        case QEvent::MouseButtonPress:
        {
            m_nType = 1;
            break;
        }
        // 鼠标释放
        case QEvent::MouseButtonRelease:
        {
            if (i == 0)
            {
                emit open(index);
            }
            else
            {
                emit deleteData(index);
            }
            break;
        }
        default:
            break;
        }
    }

    return bRepaint;
}

衍伸

通过上面的实现,我们可以自定义按钮的样式、文本、显示区域、等,我们也可以通过QStyleOptionButton的icon和iconSize来设置按钮的图标与图标大小,通过响应按钮来实现我们自己的事件。

时间: 2024-07-28 17:59:15

Qt之模型/视图(自定义按钮)的相关文章

Qt之模型/视图(自定义风格)

Qt之模型/视图(自定义风格) 关于自定义风格是针对视图与委托而言的,使用事件与QSS都可以进行处理,今天关于美化的细节讲解一下. 先看下图: 先撇开界面的美观性(萝卜青菜,各有所爱),就现有的这些风格,使用QSS + Qt二维绘图已经绰绰有余了.当然,如何让界面更美观,这个没有什么捷径,我只能说一句:无他,唯手熟尔!基本功搞扎实了,实现起来就会游刃有余...void DetailProgressBar::paint(QPainter *painter, const QStyleOptionVi

Qt之模型/视图(委托)

# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' from PyQt4.Qt import * from PyQt4.QtGui import * from PyQt4.QtCore import * import sys,os #视图和委托 """ 视图.在 model/view 架构中,视图是数据从模型到最终用户的途径.数据通过视图向用户进行显示. 此时,这种显示方式不必须同模型的存储结构相

Qt之模型/视图(委托)

概念 不同于模型 - 视图 - 控制器模式,模型/视图设计不包括用于管理与用户交互的一个完全独立的组件.一般情况,视图负责将模型数据呈现给用户以及处理用户输入.为了输入更加具有灵活性,则由委托来执行交互.这些组件提供输入功能,且在一些视图中还负责渲染个别项目.控制委托的标准接口在QAbstractItemDelegate类中定义. 委托能够通过实现的paint()和sizeHint()函数来展示它们的内容.然而,简单基础部件的委托可以继承QItemDelegate而不是QAbstractItem

Qt之模型/视图(实时更新数据)

上两节简单介绍了Qt中对于模型/视图的编程,大部分助手里说的很清楚了,现在就开始实战部分吧! 在实际应用中,视图展示的数据往往并非一成不变的,那么如何实时更新成了一个很重要的问题!功能:(1)添加委托(进度条)(2)显示文件名称.大小.进度.速度.剩余时间.状态等.(3)可进行添加.更新.删除.清空等操作.(4)实时更新数据先看一个效果图:委托(进度条):ProgressBarDelegate::ProgressBarDelegate(QObject *parent): QItemDelegat

qt model/view 架构自定义模型之QStringListModel

# -*- coding: utf-8 -*- # python:2.x #QStringListModel #QStringListModel 是最简单的模型类,具备向视图提供字符串数据的能力. #QStringListModel 是一个可编辑的模型,可以为组件提供一系列字符串作为数据. #看作是封装了 QStringList 的模型.QStringList 是一种很常用的数据类型,实际上 #是一个字符串列表(也就是 QList<QString>).既然是列表,它也就是线性的数据结构, #因

QT——模型/视图(model/view)

数据项中引入模型/视图架构,可以方便的将数据与表现层分开. ------------------------------------- 模型Model:一般来说,Model里面并不真正存储数据(数据少的话也可以直接存储在Model里),只是负责从诸如磁盘文件,数据库,网络通讯等获得源数据,并提供给View,View对数据进行修改,然后再通过Model更新源数据. Model 另一个重要工作时为源数据添加索引(ModelIndex).列表形式采用row/colum编号,树形式为建立父子间的层次关系

Qt模型/视图、委托

MVC视图和控制器对象相结合,其结果是模型/视图结构,仍然分离了数据与呈现给用户的方式,使得它可以在几个不同的视图中显示相同的数据,并实现新类型的视图而无需改变底层的数据结构.为了灵活的处理数据输入,则引入委托的概念.在此框架中引入委托的有点事:允许项目数据显示和自定义编辑. 模型与数据源进行通信,在这个体系结构中为其它组件提供了一个接口.通信的性质依赖于数据源的类型以及模型的实现方式. 视图从模型中得到模型索引,这些都是引用到数据项.通过为模型提供模型索引,视图可以从数据远中检索数据项. 在标

38.Qt模型/视图结构

1 模型/视图类 InterView框架提供了一些可以直接使用的模型类和视图类,如QStandardModel类,QDirModel类,QStringListModel类,以及QColumnView类,QHeaderView类,QListView类,QTableView类和QTreeView类 简单目录浏览器: 1 #include "mainwindow.h" 2 #include <QApplication> 3 4 #include <QAbstractItem

QT 模型/视图 编程 委托篇

委托类 概述 与模型-视图-控制器模式不同,模型/视图设计不包括用于管理与用户交互的完全独立的组件.通常,视图负责向用户表示模型数据,并处理用户输入.为了在获取输入的方式上允许一定的灵活性,交互由委托执行.这些组件提供输入功能,并负责在某些视图中呈现各个项.控制委托的标准接口在QAbstractItemDelegate类中定义. 委托应该能够通过实现paint()和sizeHint()函数来呈现它们自己的内容.然而,简单的基于widget的委托可以子类化QItemDelegate而不是QAbst