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

同系列文章

QT中级(1)QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托
QT中级(2)QTableView自定义委托(二)实现QProgressBar委托
QT中级(3)QTableView自定义委托(三)实现QCheckBox委托并且将QCheckBox居中
QT中级(4)QTableView自定义委托(四)实现QDateTimeEdit、QDateEdit控件
QT高级(1)QTableView自定义委托集合,一个类实现若干委托

1 写在前面的话

我们在之前写的《QT(7)-初识委托》文章末尾提到,"使用一个类继承QStyledItemDelegate实现常用的控件委托,在使用时可以直接调用接口,灵活实现各种委托"。我们接下来几篇文章将先详细讲解各个控件的委托,最后整理成一个类,并分享源码。如果大家感兴趣,可以点个关注,后面我们一起学习!

讲解比较详细,大家可以跟着一步一步做,自己就可以实现了。

2 需要用到的部分知识

《QT(3)-QTableView》
《QT(4)-QAbstractItemView》
《QT(6)-QStandardItemModel》
《QT(7)-初识委托》

3 同系列文章

QT中级(1)QTableView自定义委托(一)实现QSpinBox、QDoubleSpinBox委托

4 实现QProgressBar委托

进度条一般都是要一直显示在QTableView上,所以要实现QProgressBar委托,就要重新实现paint函数。

4.1 第一步

文件结构如下:

在设计师界面拖拽一个tableview到MainWindow中,并对其进行初始化。
需要主要的是 void initTable(...);这个函数是我在经常使用QTableView时通用的设置,不仅可以在这个项目使用,也可以在其他项目中使用

代码如下:
mainwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class QStandardItemModel;
class QTableView;

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void init();
    //设置表格
    void initTable(QTableView *tableView,int rowHeight = 25,bool Editable=false,bool isSorting = false,bool verticalHeadVisible=false,
            bool isLastTensile = true,bool isShowGrid = true);

private:
    Ui::MainWindow *ui;
    QStandardItemModel *model;
};
#endif // MAINWINDOW_H

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QStandardItemModel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->initTable(ui->tableView,27,true);
    this->init();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::init()
{
    QStringList columnNames;
    columnNames<<"QSpinBox"<<"QComboBox"<<"QCheckBox"<<"QProgressBar"<<"···";

    model = new QStandardItemModel;
    model->setRowCount(10);
    model->setHorizontalHeaderLabels(columnNames);
    ui->tableView->setModel(model);

}

void MainWindow::initTable(QTableView *tableView,int rowHeight,bool Editable,bool isSorting,bool verticalHeadVisible,bool isLastTensile,bool isShowGrid)
{
    /*设置样式*/
    tableView->setProperty("model",true);
    /*设置默认行高*/
    tableView->verticalHeader()->setDefaultSectionSize(rowHeight);
    /*设置交替行颜色--允许交替行颜色*/
    tableView->setAlternatingRowColors(true);
    /*设置水平/垂直滚动模式--一次滚动一个项目*/
    tableView->setHorizontalScrollMode(QAbstractItemView::ScrollPerItem);
    tableView->setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
    /*设置选择行为--每次选择只有一整行*/
    tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    /*设置拖放行为--不允许拖放*/
    tableView->setDragDropMode(QAbstractItemView::NoDragDrop);
    /*设置选择模式--只能选择一个项目*/
    tableView->setSelectionMode(QAbstractItemView::SingleSelection);
    /*设置Tab导航键--允许使用Tab键导航,shift+tab反向导航*/
    tableView->setTabKeyNavigation(true);
    /*设置是否自动换行--取消自动换行*/
    tableView->setWordWrap(false);
    /*设置文本省略模式--省略号不会出现在文本中*/
    tableView->setTextElideMode(Qt::ElideNone);
    /*设置左上角全选按钮--禁用*/
    tableView->setCornerButtonEnabled(false);
    /*设置是否支持表头排序--应该和表头是否可以单击保持一致*/
    tableView->setSortingEnabled(isSorting);
    /*设置是否显示网格线*/
    tableView->setShowGrid(isShowGrid);
    /*设置垂直表头是否可见*/
    tableView->verticalHeader()->setVisible(verticalHeadVisible);
    /*设置选中一行表头是否加粗--不加粗*/
    tableView->horizontalHeader()->setHighlightSections(false);
    /*设置最后一行是否拉伸填充*/
    tableView->horizontalHeader()->setStretchLastSection(isLastTensile);
    /*设置行标题最小宽度尺寸*/
    tableView->horizontalHeader()->setMinimumSectionSize(0);
    /*设置行标题最小高度*/
    tableView->horizontalHeader()->setFixedHeight(rowHeight);

    /*设置表头是否可以单击--不可单击*/
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
    tableView->horizontalHeader()->setSectionsClickable(isSorting);
#else
    tableView->horizontalHeader()->setClickable(false);
#endif

    /*是否可编辑*/
    if(Editable)
    {
        tableView->setEditTriggers(QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed);
    }
    else
    {
        tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    }
}

4.2 第二步

  1. 我们首先创建一个类Delegate继承QStyledItemDelegate,同时定义paint函数
cpp 复制代码
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;

这四个函数的作用以及意义,详见:《QT(7)-初识委托》这里不在赘述。

  1. 创建一些 QSpinBox相关参数,并创建相应参数的外部设置接口
cpp 复制代码
    /*QProgressBar设置相关参数函数*/
    void setPgBarRange(const int min,const int max);
    void setPgBarTextVisible(bool isTextVisible);
    void setPgBarAlignment(Qt::Alignment pgbarAlignment);
    void setInvertedAppearance(bool invertedAppearance);

    /*QProgressBar相关参数*/
    int pgbarMax;
    int pgbarMin;
    Qt::Alignment pgbarAlignment;
    bool isTextVisible;
    bool invertedAppearance;
    QProgressBar *pgBar;

这里我定义了很多参数,实际应用的时候有些参数并用不到,大家根据需求定义。

  1. 创建给这些参数初始化的函init()
cpp 复制代码
void Delegate::init()
{
    pgBar = new QProgressBar;
    pgbarMax = 100;
    pgbarMin = 0;
    pgbarAlignment = Qt::AlignCenter;
    isTextVisible = true;
    invertedAppearance = false;
}

4.3 第三步

下面我们逐个实现paint函数

cpp 复制代码
void Delegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{

    if(index.column() == 3)
    {
        //获得视图中的值
        int value = index.model()->data(index,Qt::DisplayRole).toInt();
        //创建包含QProgressBar样式信息类
        QStyleOptionProgressBar soPgbar;
        //使用我们创建的pgBar初始化soPgbar
        soPgbar.initFrom(pgBar);
        //设置最大值和最小值
        soPgbar.maximum = pgbarMax;
        soPgbar.minimum = pgbarMin;
        //设置进度条值
        soPgbar.progress = value;
        //设置状态
        soPgbar.state |= QStyle::State_Enabled;
        soPgbar.state |= QStyle::State_Horizontal;
        //设置位置和大小
        soPgbar.rect = option.rect;
        //设置文本
        soPgbar.text = QString("%1%").arg(value);
        //设置文本是否可见
        soPgbar.textVisible = isTextVisible;
        //设置文本居中
        soPgbar.textAlignment = pgbarAlignment;
        //设置进度条的进度方向
        soPgbar.invertedAppearance = invertedAppearance;
        //绘制
        QApplication::style()->drawControl(QStyle::CE_ProgressBar,&soPgbar,painter,pgBar);
    }//if
    else
    {
        QStyledItemDelegate::paint(painter,option,index);
    }
}

4.4 最后一步

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

更新mainwindow.cpp中的init()函数

cpp 复制代码
void MainWindow::init()
{
    QStringList columnNames;
    columnNames<<"QSpinBox"<<"QComboBox"<<"QCheckBox"<<"QProgressBar"<<"···";

    model = new QStandardItemModel;
    model->setRowCount(10);
    model->setHorizontalHeaderLabels(columnNames);
    ui->tableView->setModel(model);

    Delegate *pgbarDelegate = new Delegate;
    ui->tableView->setItemDelegateForColumn(3,pgbarDelegate);
}

4.5 运行效果

5 源码

源码

都看到这里了,赏个关注吧!