Qt学习:项视图类之自定义委托

QT学习笔记-Qt Model/View 目录前言一、Qt模型视图结构简介二、Qt模型概念Model indexes行列父项**数据项角色**三、Qt视图概念使用已有视图使用模型操作被选项四、Qt委托使用已有委托一个简单的自定义委托五、创建模型设计模型 前言 因工作需要,要实现一个小型的数据管理系统。本着想捡起来QT技能的想法,学习下QT模型视图的操作。 一、Qt模型视图结构简介 模型/视图结构,仍然分离了数据与呈现给用户的方式,但提供了基于相同原理的简单框架。这种分离使得它可以在几个不同的视图中显示相同的数据,并且实现新类型的视图,而无需改变 阅读详情
    我们用好几节内容介绍了Qt的MVC架构中的模型和视图类,至今,我们依然没有提到我们提到的代理的功能,下面我们再回顾一下Qt的项视图类架构。
    我们知道,在经典的 MVC 模型中,view用于向用户展示 model 的数据。但是,Qt提供的不是 MVC 三层架构,而是一个 model/view 设计。这种设计并没有包含一个完整而独立的组件用于管理用户的交互。一般来说,view仅仅是用作对model数据的展示和对用户输入的处理,而不应该去做其他的工作。在这种结构中,为了获得对用户输入控制的灵活性,这种交互工作交给了delegate,也就是“委托”,去完成。简单来说,就像它们的名字一样,view 将用户输入委托给 delegate 处理,而自己不去处理这种输入。这些组件提供一种输入能力,并且能够在某些 view 中提供这种交互情形下的渲染,比如在 table 中通过双击单元格即可编辑内容等。对这种控制委托的标准接口被定义在 QAbstractItemDelegate 类中。
    就是说Qt用委托的方式完成了用户和模型之间的交互。其实本质上还是基于经典的MVC架构思想。
    delegate 可以用于渲染内容,这是通过 paint() 和 sizeHint() 函数来完成的。但是,对于一些简单的基于组件的delegate,可以通过继承 QItemDelegate 或者 QStyledItemDelegate 来实现。这样就可以避免要完全重写 QAbstractItemDelegate 中所需要的所有函数。对于一些相对比较通用的函数,在这两个类中已经有了一个默认的实现。 

 

    Qt提供的标准组件使用 QItemDelegate 提供编辑功能的支持。这种默认的实现被用在 QListView,QTableView 和 QTreeView 之中。view 实用的delegate可以通过 itemDelegate() 函数获得setItemDelegate()函数则可以为一个标准组件设置自定义的delegate。
    Qt 4.4版本之后提供了两个可以被继承的delegate类:QItemDelegate 和 QStyledItemDelegate。默认的delegate是 QStyledItemDelegate。这两个类可以被相互替代,用于给view 组件提供绘制和编辑的功能。它们之间的主要区别在于,QStyledItemDelegate 使用当前的风格(style)去绘制组件。所以,在自定义delegate或者需要使用 Qt style sheets 时,建议使用 QStyledItemDelegate 作为父类。使用这两个类的代码通常是一样的,除了需要使用style进行绘制的部份。如果你希望为view item自定义绘制函数,最好实现一个自定义的style。这个你可以通过QStyle类来实现。
    如果delegate没有支持为你的数据类型进行绘制,或者你希望自己绘制item,那么就可以继承 QStyledItemDelegate 类,并且重写 paint() 或者还需要重写 sizeHint() 函数。paint() 函数会被每一个item独立调用,而sizeHint()函数则可以定义每一个item 的大小。在重写 paint() 函数的时候,通常需要用 if 语句找到你需要进行渲染的数据类型并进行绘制,其他的数据类型需要调用父类的实现进行绘制。 

 

        
    一个自定义的delegate也可以直接提供一个编辑器,而不是使用内置的编辑器工厂(editor item factory)。如果你需要这种功能,那么需要实现一下几个函数:
createEditor():                 返回修改数据的组件;
setEditorData():                为editor提供编辑的原始数据;
updateEditorGeometry():         保证editor显示在 item view 的合适位置以及大小;
setModelData():                 根据editor 的数据更新model的数据。

            下面我们使用一个音轨编辑器的例子来说明这些函数的用法,实现一个自定义的委托,这个例子来自于:(C++ GUI Programming with Qt4, 2nd Edition) 
 首先我们自定义了一个数据类型,用于存储音轨的标题(QString)和持续时间(int):

 

class Track
{
public:
    Track(const QString &title = "", int duration = 0);

    QString title;
    int duration;
}; 



    关于这个类的实现这里就不提了,接下来我们创建整个界面的布局,这里也只给出构造函数:

TrackEditor::TrackEditor(QList<Track> *tracks, QWidget *parent)
    : QDialog(parent)
{
    this->tracks = tracks;

    tableWidget = new QTableWidget(tracks->count(), 2);
    tableWidget->setItemDelegate(new TrackDelegate(1));
    tableWidget->setHorizontalHeaderLabels(
            QStringList() << tr("Track") << tr("Duration"));

    for (int row = 0; row < tracks->count(); ++row) {
        Track track = tracks->at(row);

        QTableWidgetItem *item0 = new QTableWidgetItem(track.title);
        tableWidget->setItem(row, 0, item0);

        QTableWidgetItem *item1
             = new QTableWidgetItem(QString::number(track.duration));
        item1->setTextAlignment(Qt::AlignRight);
        tableWidget->setItem(row, 1, item1);
    }

    tableWidget->resizeColumnToContents(0);

    buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
                                     | QDialogButtonBox::Cancel);
    QPushButton *addTrackButton = buttonBox->addButton(tr("&Add Track"),
            QDialogButtonBox::ActionRole);

    connect(addTrackButton, SIGNAL(clicked()), this, SLOT(addTrack()));
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(tableWidget);
    mainLayout->addWidget(buttonBox);
    setLayout(mainLayout);

    setWindowTitle(tr("Track Editor"));
} 



    其中tableWidget->setItemDelegate(new TrackDelegate(1));告诉编译器我们使用TrackDelegate这个对象作为我们的委托,这里
TrackDelegate就是我们自定义的委托。效果图如下:

    我们可以通过双击来对音轨的持续时间进行编辑,下面我们着重讨论这个自定义委托类的实现过程,像上面提到的那样,我们得重新实现 void paint()、QWidget *createEditor()、void setEditorData()、void setModelData()四个函数。下面是这个类的定义部分

#ifndef TRACKDELEGATE_H
#define TRACKDELEGATE_H

#include <QItemDelegate>

class TrackDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    TrackDelegate(int durationColumn, QObject *parent = 0);

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const;
    QWidget *createEditor(QWidget *parent,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const;

private slots:
    void commitAndCloseEditor();

private:
    int durationColumn;
};

#endif


 

    我们用 durationColumn来存储我们需要设置委托的列。

TrackDelegate::TrackDelegate(int durationColumn, QObject *parent)
    : QItemDelegate(parent)
{
    this->durationColumn = durationColumn;
}

    构造函数接收一个列数告诉这个委托,那一列需要被编辑。

void TrackDelegate::paint(QPainter *painter,
                          const QStyleOptionViewItem &option,
                          const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        int secs = index.model()->data(index, Qt::DisplayRole).toInt();
        QString text = QString("%1:%2")
                       .arg(secs / 60, 2, 10, QChar('0'))
                       .arg(secs % 60, 2, 10, QChar('0'));

        QStyleOptionViewItem myOption = option;
        myOption.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;

        drawDisplay(painter, myOption, myOption.rect, text);
        drawFocus(painter, myOption, myOption.rect);
    } else{
        QItemDelegate::paint(painter, option, index);
    }
}

 

    paint()函数用于控制某一列的显示格式,因为用户传进去的值是秒数,所以我们得重绘这个显示,用“分钟:秒”、右对齐的格式显示这些数据。

QWidget *TrackDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &option,
        const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        QTimeEdit *timeEdit = new QTimeEdit(parent);
        timeEdit->setDisplayFormat("mm:ss");
        connect(timeEdit, SIGNAL(editingFinished()),
                this, SLOT(commitAndCloseEditor()));
        return timeEdit;
    } else {
        return QItemDelegate::createEditor(parent, option, index);
    }
} 

 

    当我们双击一个单元格时 createEditor()函数被调用并在当前单元格创建一个QTimeEdit用于编辑,但要注意我们双击出来的数据并不在这会儿就写入单元格,即当我们把焦点聚焦在另一个单元格时,我们在这个时间编辑器编辑的时间会失效,单元格显示我们原来写入的时间,所以我们连接一个槽,当编辑完后焦点转移就会触发这个槽,这个槽是这样实现的:

void TrackDelegate::commitAndCloseEditor()
{
    QTimeEdit *editor = qobject_cast<QTimeEdit *>(sender());
    emit commitData(editor);
    emit closeEditor(editor);
}

    这个槽发射commitData()信号通知视图用被编辑的数据替换已经存在的数据,并发射closeEditor()信号通知视图已经不再需要这个编辑器了,这时模型就会删除它。

void TrackDelegate::setEditorData(QWidget *editor,
                                  const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        int secs = index.model()->data(index, Qt::DisplayRole).toInt();
        QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor);
        timeEdit->setTime(QTime(0, secs / 60, secs % 60));
    } else {
        QItemDelegate::setEditorData(editor, index);
    }
}

    当用户初始化编辑的时候是调用createEditor()创建一个编辑器的,这我们上边也提到过, 然后这个项的当前数据调用setEditorData()这个函数来初始化编辑器(原来是拿00:00来初始化的)。

void TrackDelegate::setModelData(QWidget *editor,
                                 QAbstractItemModel *model,
                                 const QModelIndex &index) const
{
    if (index.column() == durationColumn) {
        QTimeEdit *timeEdit = qobject_cast<QTimeEdit *>(editor);
        QTime time = timeEdit->time();
        int secs = (time.minute() * 60) + time.second();
        model->setData(index, secs);
    } else {
        QItemDelegate::setModelData(editor, model, index);
    }
}

    如果用户完成了编辑,就从QTimeEdit中提取出分钟数和秒数,并且设置数据为相应的秒数,paint函数就会把这个秒数以当前的格式写进对应的单元格中。

    至此我们简单扼学完了Qt的MVC框架,但这只是入门之说,仍需努力,努力,再努力。

 

 

 

 

 


 

 

Qt-QTableView委托视图学习1——样式委托类实现 Qt委托绘制 阅读详情

相关推荐

Qt6模型/视图架构解析:从数据分离到自定义委托实战

模型/视图(Model/View)是GUI开发中实现数据与界面分离的核心架构模式。其原理在于通过抽象的数据模型(Model)统一管理数据源,视图(View)负责可视化呈现,委托(Delegate)控制具体绘制与编辑行为,三者通过标准接口与信号槽机制松耦合协作。这种架构的技术价值在于极大提升了代码的可维护性和复用性——业务逻辑只需与模型交互,无需关心界面细节,同一数据模型可适配多种视图组件(如列表、表格、树形)。在桌面应用开发中,它尤其适用于需要动态展示复杂数据(如文件管理器、数据监控面板)的场景。本文以Qt

weixin_30292843的博客 510

QT自定义委托类代理类

QT自定义委托类,委托QSpinBox来提供编辑功能。

Txwtech 1627

【QT开发】列表视图QListView类详解及实战应用

QListView是Qt提供的一个功能强大且灵活的列表视图类,通过本篇文章的学习,你应该对QListView有了全面的理解,能够在自己的项目中正确使用它。QListView在用户界面中帮助你更好地展示和管理二维列表数据,实现交互式和响应式的数据展示,有助于创建用户友好和高效的文件列表、项目列表、数据列表等应用场景。

科技改变人类,技术成就未来 3731

Qt模型视图框架:自定义委托

这里实现一个委托使用 QSpinBox 来提供编辑功能,主要用于显示整数的模型。 从 QStyledItemDelegate 子类化委托而不是 QAbstractItemDelegate,因为QStyledItemDelegate 已经实现了 paint() 函数。 class SpinBoxDelegate : public QStyledItemDelegate { Q_OBJECT public: SpinBoxDelegate(QObject *parent = .

友善啊,朋友的博客 1001

QT高级(1)QTableView自定义委托集合,一个类实现若干委托

*一个类实现11种常用委托,使用灵活,可以直接将代码加入到自己的项目中,零耦合。*** 2. ***复选框控件:可以居中,可以在点击的时候发送信号,在外部轻松获得数据。*** 3. ***图标控件:可以指定某一种条件(、=灯),指定某一行为判断行,当某个行的值符合条件时,会先一种图标,不符合时显示另一种图标*** 4. ***密码框控件:可以显示明文和密码文,密码样式可以自己指定,同时当数值改变时,会发送信号*** 5. ***数值控件/日期时间控件/进度条控件:在前面4篇文章中已经有教程了*** 6

m晴朗的博客 3881

QT中级(3)QTableView自定义委托(三)实现QCheckBox委托并且将QCheckBox居中

我们需要在mainwindow.cpp中的init()调用delegate类实现委托。我们将QTableView的第一列设置为委托:更新mainwindow.cpp中的init()函数。

m晴朗的博客 3546

QT:在QTableView中使用各种自定义委托

原文地址::https://blog.youkuaiyun.com/lhchen922/article/details/38367719 相关文章 1、QT:在QTableView中使用各种自定义委托----https://blog.youkuaiyun.com/zgrjkflmkyc/article/details/48086851 2、QTableView使用自定义委托(QItemDelegate)----https://www.cnblogs.com/doubleeleven/p/3948803.html 3、QTa

xqhrs232的专栏 1594

QT中级(2)QTableView自定义委托(二)实现QProgressBar委托

我们在之前写的[《QT(7)-初识委托》](https://blog.youkuaiyun.com/qq_40666149/article/details/128674837)文章末尾提到,***“使用一个类继承QStyledItemDelegate实现常用的控件委托,在使用时可以直接调用接口,灵活实现各种委托”***。我们接下来几篇文章将先详细讲解各个控件的委托,最后整理成一个类,并分享源码。如果大家感兴趣,可以点个关注,后面我们一起学习! ***讲解比较详细,大家可以跟着一步一步做,自己就可以实现了。*** # 2 需要用到的部分知识 [《QT(3)-QTableView》](https://blog.youkuaiyun.com/qq_40666149/article/details/128215699) [《QT(4)-QAbstractItemView》](https://blog.youkuaiyun.com/qq_40666149/article/details/128235025) [《QT(6)-QStandardItemModel》](https://blog.youkuaiyun.com/qq_4066614

十三 Qt自定义信号

Qt中自定信号 自定义槽函数。

zhlei_12345的博客 5602

QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托

使用一个类继承QStyledItemDelegate实现常用的控件委托,在使用时可以直接调用接口,灵活实现各种委托 配套文章:https://blog.youkuaiyun.com/qq_40666149/article/details/128877549

【算力网络】算力知识

尽管算力这个词在近年来很“火”,但其背后的含义,却很少有人真正了解

qq_42809645的博客 1万+

Qt学习笔记(六)项视图类

[原博客地址]https://blog.youkuaiyun.com/skc361/article/details/12754193 许多应用程序允许用户搜索、查看和编辑属于某个数据集中的一些个别项。这些数据可能保存在文件中、数据库中或者网络服务器上。处理像这样的数据集的标准方式是使用Qt的项视图类(item view cla...

JMaliex 930

同花顺Supermind量化交易 风险控制建模--海龟交易法则

A.市场与标的海龟交易法则应用于流动性高的市场中,选择交易量较大的标的进行交易。本文以沪深300指数ETF为标的,构建海龟交易法则。B、仓位:仓位是海龟交易系统最核心的部分,通过ATR真实波幅指标来管理仓位。第一步:计算True Range,简称TR。TR = Max ( H−L , H−P , P−L ) ,其中H为当日日内最高价,L为当日日内最低价,P为前一日收盘价。第二步:计算ATRATR = mean ( TR , 20 ) , 即计算过去20天的TR的平均值,ATR是TR的移动平均值。

qq_22808537的博客 1497

26.QT-模型视图之自定义委托

 在上一章学习25.QT-模型视图后,本章接着学习视图委托 视图委托(Delegate)简介 由于模型负责组织数据,而视图负责显示数据,所以当用户想修改显示的数据时,就要通过视图中的委托来完成 视图委托类似于传统的MVC设计模式里的Controller(控制器)角色 Model(模型) - 负责数据组织 View(视图) - 负责数据显示 Controller(控制器) - 负...

抵抗时间扭曲,坚持做一件有意义的事 533

C#读取CAD文件(dwg/dxf)并处理

项目要求识别CAD图纸(图纸内容与现实事物比例是1:1)中的内容,并提取出一些关键信息。这里的CAD图纸是指CAD文件,包含多种格式,dwg/dxf/dwf/stl/pdf等等。识别其中内容,主要指文件中的图元信息(也叫实体Entity),指线段、圆弧、矩形等图形元素。得到图元基础信息(比如长度、坐标、粗细)后,进一步做处理(如得到交点、得到线段间间隔、圆弧与线段切点等)。听起来有点难,因为作为软件工程师,对CAD相关事物并不了解,它是未知的;

三千幻想乡 1万+

MySQL 分库分表及其平滑扩容方案

MyCAT不仅仅可以用作读写分离,以及分表分库、容灾管理,而且可以用于多租户应用开发、云平台基础设施,让你的架构具备很强的适应性和灵活性。分表对于一张多行(记录)多列(字段)的二维数据表,又分两种情形(1)垂直分表竖向切分,不同分表存储不同的字段,可以把不常用或者大容量、或者不同业务的字段拆分出去;扩容前每个节点的数据,有一半要迁移至一个新增节点中,对应关系比较简单。此时,四个节点的数据都已完整,只是有冗余(多存了和自己配对的节点的那部分数据),择机清除即可(过后随时进行,不影响业务)。...

m0_71777195的博客 1929

QT的模型&视图框架--看书笔记

QT的模型&视图框架--看书笔记

Jane_Yih的博客 1316

STM32F103C8T6键盘DIY全攻略:从电路设计到固件烧录(附避坑指南)

本文详细介绍了基于STM32F103C8T6微控制器的DIY键盘制作全流程,涵盖硬件电路设计、按键矩阵实现、USB HID通信及固件烧录等关键步骤。特别针对常见问题提供避坑指南,帮助开发者高效完成从电路设计到功能实现的完整过程,打造个性化瀚文键盘。

soda5的博客 770

Qt5 学习8 之 model/view、QStringListModel、模型、视图和委托

model/view 有时,我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应用程序的界面中。早期的 Qt 要实现这个功能,需要定义一个组件,在这个组件中保存一个数据对象,比如一个列表。我们对这个列表进行查找、插入等的操作,或者把修改的地方写回,然后刷新组件进行显示。这个思路很简单,也很清晰,但是对于大型程序,这种设计就显得苍白无力。比如,在一个大型系统中,你的数据可能...

qq_40729688的博客 1719

Android汽车服务篇(一) CarService

本文主要说明了CarService这一系统服务的启动流程,以及一些关键成员的创建和初始化流程.同时简单介绍了一下客户端是如何获取和使用CarService对象, 如上文介绍的, CarService对象只是获取各个Manager的媒介,它本身并不承担管理传感器.空调等具体的任务.如果要获取车辆的相关信息,如车速, 车内空调温度,诊断信息, 或对车辆进行相关的控制,如升高和降低空调温度,控制座椅和车窗, 调节音量等,就要通过具体的Manager中的API和对应的服务来实现了.

u012514113的专栏 8148

Open3D点云数据处理(五):点云、mesh可视化(draw_geometries方法)

本文介绍了Open3D中的draw_geometries可视化方法,可以用于可视化点云和mesh。详细讲述了该方法的各个参数的作用,给出了代码示例。

孙悟空 3139

Qt使用自定义委托(QItemDelegate/QStyledItemDelegate)

文章来源:http://blog.youkuaiyun.com/zhgn2/article/details/14613519 QxOrm QxOrmis a new open source ORM (Object Relational Mapping) C++ library designed to provide : *Persistence(based onQt

$firecat利白的代码足迹$ 8862

19、多项式基算术:原理与运算详解

本文深入探讨了有限域 $GF(2^m)$ 中的多项式基算术,详细介绍了加法、减法、乘法和平方运算的原理与实现方法。重点分析了多项式基表示形式、模约简技术以及乘法优化策略,如高基数乘法、并行与顺序乘法器设计,并提到了Karatsuba-Ofman算法在减少乘法次数方面的优势。此外,文章还讨论了多项式基算术在密码学、编码理论等领域的应用前景,并展望了未来在高效算法设计与硬件加速方面的研究方向。

yellow的专栏 150

QT 视图(View)/委托(Delegate)/ 模型(Model)/项(Item) 之间的关系

引言 在学习Qt 中此部分的使用是界面自定义出美观的重要部分,熟练的使用,可以制作出很好的效果,在此梳理一下他们的关系。 Model/View(模型/视图) **视图(View)**是显示和编辑数据的界面组件 **模型(Model)**是视图与原始数据之间的接口。 在QT中提供了以下几种预定义模型: ...

Osean_li的博客 2949

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Qt视图和委托

Qt视图和委托

m0_60259116的博客 287

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

QT模型/视图

QT模型/视图

hw5230的博客 1075

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

上一篇: Qt学习:项视图类之自定义模型
下一篇: 第十一学 linux内核——进程管理——进程是什么
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值