【Qt 学习之路】QCombobox应用QStyledItemDelegate

目录

1、简述

2、效果

3、源代码

3.1、代理类

3.2、应用类

4、QStyledItemDelegate

4.1、简述QStyledItemDelegate

4.2、数据类型

4.3、成员函数


1、简述

QComboBox是个很基础的控件,也是继承自QWidget

2、效果

效果是这样的:

3、源代码

3.1、代理类

我们先建立代理类,继承自QStyledItemDelegate:

1、头文件:

#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H

#include <QStyledItemDelegate>
class ItemDelegate : public QStyledItemDelegate
{
  Q_OBJECT
signals:
    void deleteItem(const QModelIndex &index);
public:
    ItemDelegate(QObject * parent=0);
    virtual ~ItemDelegate(){}
    void paint(QPainter * painter,const QStyleOptionViewItem & option,const QModelIndex & index) const;
    bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
};

#endif // ITEMDELEGATE_H

2、源文件:

#include "ItemDelegate.h"
#include <QPainter>
#include <QMouseEvent>
#include <QStyledItemDelegate>
#include <QToolTip>
#include <QApplication>
ItemDelegate::ItemDelegate(QObject * parent)
    : QStyledItemDelegate(parent)
{
}

void ItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyleOptionViewItem  viewOption(option);
    if (viewOption.state & QStyle::State_HasFocus)
    {
        viewOption.state = viewOption.state ^ QStyle::State_HasFocus;
    }
    QStyledItemDelegate::paint(painter, viewOption, index);
    int height = (viewOption.rect.height() - 9) / 2;
    QPixmap pixmap = QPixmap(":/delete");
    QRect decorationRect = QRect(viewOption.rect.left() + viewOption.rect.width() - 30, viewOption.rect.top() + height, 9, 9);
    painter->drawPixmap(decorationRect, pixmap);
}

bool ItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index)
{
    int height = (option.rect.height() - 9) / 2;
    QRect decorationRect = QRect(option.rect.left() + option.rect.width() - 30, option.rect.top() + height, 9, 9);
    QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
    if (event->type() == QEvent::MouseButtonPress && decorationRect.contains(mouseEvent->pos()))
    {
        emit deleteItem(index);
    }
    if (event->type() == QEvent::MouseMove && decorationRect.contains(mouseEvent->pos()))
    {
        QCursor cursor(Qt::PointingHandCursor);
        QApplication::setOverrideCursor(cursor);
        QString strText = QStringLiteral("删除账号信息");
        QToolTip::showText(mouseEvent->globalPos(), strText);
    }
    else
    {
        QCursor cursor(Qt::ArrowCursor);
        QApplication::setOverrideCursor(cursor);
    }
    return QStyledItemDelegate::editorEvent(event, model, option, index);
}

3.2、应用类

在我们的程序中应用这个代理:

1、头文件:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
private slots:
    void deleteItem(const QModelIndex &index);
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

2、源文件:

#include "widget.h"
#include "ui_Widget.h"
#include "ItemDelegate.h"
#include <QMessageBox>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    ItemDelegate *pDelegate = new ItemDelegate(this);
    ui->comboBox->addItem(QPixmap(":/shasha.png"), QStringLiteral("沙师弟"));
    ui->comboBox->addItem(QPixmap(":/jiejie.png"), QStringLiteral("二师兄"));
    ui->comboBox->addItem(QPixmap(":/kongkong.png"), QStringLiteral("猴哥"));
    ui->comboBox->addItem(QPixmap(":/tangtang.png"), QStringLiteral("师傅"));
    ui->comboBox->setItemDelegate(pDelegate);
    connect(pDelegate, SIGNAL(deleteItem(QModelIndex)), this, SLOT(deleteItem(QModelIndex)));
}
Widget::~Widget()
{
    delete ui;
}
void Widget::deleteItem(const QModelIndex &index)
{
    if (QMessageBox::question(this, QStringLiteral("提示"), QStringLiteral("确认要删除所选账号吗?"),
                     QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes)
    {
        ui->comboBox->removeItem(index.row());
    }
}

4、QStyledItemDelegate

4.1、简述QStyledItemDelegate

当在 Qt 项目视图中显示来自模型的数据时,单个项目由委托绘制。此外,当一个项目被编辑时,它提供了一个编辑器小部件,小部件在编辑时放置在项目视图的顶部。 QStyledItemDelegate 是所有 Qt 项目视图的默认委托,并在创建它们时安装在它们上。

模型中项目的数据被分配了一个 ItemDataRole。项目可以为每个角色存储一个 QVariant。 QStyledItemDelegate 实现了用户期望的最常见数据类型的显示和编辑,包括布尔值、整数和字符串。

4.2、数据类型

数据将根据它们在模型中的角色而不同地绘制。下面是委托可以为每个角色处理的角色和数据类型:

  • Qt::BackgroundRole:QBrush
  • Qt::CheckStateRole:Qt::CheckState
  • Qt::DecorationRole:QIcon、QPixmap、QImage、QColor
  • Qt::DisplayRole:QString 和带有字符串表示的类型
  • Qt::EditRole:详见 QItemEditorFactory
  • Qt::FontRole:QFont
  • Qt::SizeHintRole:QSize
  • Qt::TextAlignmentRole:Qt::Alignment
  • Qt::ForegroundRole:QBrush

子类化 QStyledItemDelegate

如果委托不支持绘制所需的数据类型,或者想自定义项目的绘制,则需要子类化 QStyledItemDelegate,并重新实现paint() 和sizeHint()。为每个项目单独调用paint() 函数,使用sizeHint(),可以为每个项目指定提示。

自定义委托可以在不使用编辑器项目工厂的情况下提供编辑器。在这种情况下,必须重新实现以下虚函数:

  • createEditor():返回用于更改模型数据的小部件,并且可以重新实现以自定义编辑行为。
  • setEditorData():为小部件提供要操作的数据。
  • updateEditorGeometry():确保编辑器相对于项目视图正确显示。
  • setModelData():将更新的数据返回给模型。
  • QStyledItemDelegate 与 QItemDelegate

这两个类的区别在于 QStyledItemDelegate 实现了paint()函数。除非需要自定义项目显示,否则建议在实现自定义委托或使用 Qt 样式表时使用 QStyledItemDelegate 作为基类。

4.3、成员函数

1、QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index)

重新实现: QAbstractItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const。

返回用于编辑由 index 指定的项目以进行编辑的小部件。父小部件和样式选项用于控制编辑器小部件的显示方式。(设置qss/Style要在父小部件上设置)

2、QString displayText(const QVariant &value, const QLocale &locale)

此函数返回委托将用于在语言环境中显示模型的 Qt::DisplayRole 的字符串。 value 是模型提供的 Qt::DisplayRole 的值。

默认实现使用 QLocale::toString 将值转换为 QString。

对于空模型索引,即模型返回无效 QVariant 的索引,不会调用此函数。

3、bool eventFilter(QObject *editor, QEvent *event)

如果editor是一个有效的 QWidget 并且event被处理,则返回 true,否则返回false。

默认处理以下按键事件:

  • Tab
  • Backtab
  • Enter
  • Return
  • Esc

如果编辑器的类型是 QTextEdit 或 QPlainTextEdit,则不处理 Enter 和 Return 键。

在 Tab、Backtab、Enter、Return 键按下事件的情况下,编辑器的数据提交到模型并关闭编辑器。

  • 如果事件是按 Tab 键,则视图将在视图中的下一项上打开编辑器。
  • 如果事件是 Backtab 键,则视图将打开视图中前一项的编辑器。
  • 如果事件是 Esc 键按下事件,则编辑器将关闭而不提交其数据。

4、void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index)

使用索引索引的值初始化选项。

当子类需要 QStyleOptionViewItem,但又不想自己设置所有信息时,此方法很有用。

5、void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)

重新实现:QAbstractItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const。

在子类中重新实现paint()时。使用 initStyleOption() 以与 QStyledItemDelegate 相同的方式设置选项。

尽可能在绘画时使用option。特别是它的 rect 变量来决定在哪里绘制和它的状态来确定它是启用还是选择。

绘制后,应该确保绘制器返回到调用此函数时提供的状态(在绘画之前调用 QPainter::save() 和之后调用 QPainter::restore())。

6、void setEditorData(QWidget *editor, const QModelIndex &index)

重新实现:QAbstractItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const。

从模型索引指定的数据模型项设置编辑器要显示和编辑的数据。

默认实现将数据存储在编辑器小部件的用户属性中。

7、void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index)

重新实现:QAbstractItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const。

从编辑器小部件获取数据并将其存储在项目索引处的指定模型中。

默认实现从编辑器小部件的用户属性获取要存储在数据模型中的值。

8、QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index)

重新实现:QAbstractItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const。

返回委托显示由索引指定的项目所需的大小,同时考虑选项提供的样式信息。

9、void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index)

重新实现:QAbstractItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const。

根据option更新由 index 指定的项目的编辑器。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

沙振宇

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值