QT中級(2)QTableView自定義委託(二)實現QProgressBar委託

2023-11-01 18:00:52

同系列文章

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

#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

#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函數
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;

這四個函數的作用以及意義,詳見:《QT(7)-初識委託》這裡不在贅述。

  1. 建立一些 QSpinBox相關引數,並建立相應引數的外部設定介面
    /*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()
void Delegate::init()
{
    pgBar = new QProgressBar;
    pgbarMax = 100;
    pgbarMin = 0;
    pgbarAlignment = Qt::AlignCenter;
    isTextVisible = true;
    invertedAppearance = false;
}

4.3 第三步

下面我們逐個實現paint函數

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()函數

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 原始碼

原始碼

都看到這裡了,賞個關注吧!