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-12-04 20:29:47

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

Qt之模型/视图(自定义进度条)

简述 在之前的章节中分享过关于QHeaderView表头排序.添加复选框等内容,相信大家模型/视图.自定义风格有了一定的了解,下面我们来分享一个更常用的内容-自定义进度条. 实现方式: 从QAbstractTableModel中设置对应的进度数据,因为我们需要显示进度条,而不是直接显示进度文本,所以原始的数据不需要直接显示在界面上,所以不需要使用Qt::DisplayRole,可以使用Qt::UserRole来代替. 委托QStyledItemDelegate中根据进度索引所对应的数据来获取进度

ios-如何iOS标签栏点击自定义按钮弹出模态视图

问题描述 如何iOS标签栏点击自定义按钮弹出模态视图 我自定义了一个UITabBar类:TabBar 在TabBar.m里面写代码设定这个按钮的参数 在TabBarViewController.m类里面放入这个按钮 TabBar * tabBar=[[TabBar alloc]init]; [self setValue:tabBar forKey:@"tabBar"]; 然后我在TabBar.m里面为这个按钮addTarget 但是addTarget事件里面无法写PresentView

Qt之图形视图框架

简述 图形视图(Graphics View)提供了一个平台,用于大量自定义2D图元的管理与交互,并提供了一个视图部件(view widget)来显示可以缩放和旋转的图元. 框架包括一个事件传播架构,支持场景(Scene)中的图元(Item)进行精确的双精度交互功能.图元可以处理键盘事件.鼠标按下.移动.释放和双击事件,同时也能跟踪鼠标移动. 图形视图使用一个BSP(Binary Space Partitioning - 二叉空间分割)树,以提供对图形元素的快速查找,正因为如此,它可以使超大的场景

使用Buttons库通过Sass和Compass库实现自定义按钮

文章简介:本文从实用的角度出发,主要介绍了如何在实际项目中使用Buttons库,并且简章介绍了通过Sass和Compass库来实现自定义按钮.希望这篇文章对大家制作属于自己的按钮库有所帮助. 前几天在互联网上看到alexwolfe制作的Button库,觉得很有意思,特意花了些时间学习了一下这个库的源码与使用.今天花了点时间将期整理与大家分享. Button库并不是简单的一个CSS制作的Button库,在这里alexwolfe大师采用了SASS和Compass进行开发和维护的.或许有些同学看到这两

xcode-点击自定义按钮时触发事件

问题描述 点击自定义按钮时触发事件 创建了一个TableView,然后创建了自定义的单元,其中放了一个Button.现在我想要实现,点击索引的时候获取tableview的索引内容,但是点击了对应索引的按钮之后,没有给出索引列表. 我的tableview类名是SubMenuViewController,然后单元类名是SubMenuCell, SubMenuViewController代码如下: - (UITableViewCell *)tableView:(UITableView *)tableV

WPF自定义控件与样式(2)-自定义按钮FButton

原文:WPF自定义控件与样式(2)-自定义按钮FButton 一.前言.效果图 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接.  还是先看看效果图吧:       定义Button按钮名称叫FButton,主要是集成了字体图标(参考上一篇:WPF自定义控件与样式1-矢量字体图标(iconfont)).其实在WPF里,要实现本文FButton的需求,完全可以不用自定义控件,使用样

uibutotn-在自定义按钮中设置文本

问题描述 在自定义按钮中设置文本 在自定义按钮使用自定义图片.然后我想设置标题时弄不上. 代码: - (void)viewDidLoad { UIImage *backButtonImage = [UIImage imageNamed:@"button.png"]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [backButton setImage:backButtonImage forSt

vc60-如何用vc6.0画自定义按钮

问题描述 如何用vc6.0画自定义按钮 想要自制按钮,就是按下之后会亮的那种,用vc怎么画,或者说哪里有资源吗 解决方案 参考:http://blog.csdn.net/lightboat09/article/details/6069710http://download.csdn.net/detail/nexuiz2/3445593 解决方案二: setwindowlong子类化按钮,在wndproc里拦截WM_PAINT消息,使用GDI/GDI+或其他的绘图,返回0阻止系统重画 解决方案三:

javascript-关于wysihtml5()自定义按钮点击事件

问题描述 关于wysihtml5()自定义按钮点击事件 当我点击图片中"插入图片"按钮时,弹出windows窗体, 相关代码如下: JS===> $("#compose-textarea").wysihtml5(); HTML====> <div class="form-group"> <textarea id="compose-textarea" name="addNoticeDeta