Qt之模型/視圖(自定義進度條)


簡述

在之前的章節中分享過關於QHeaderView表頭排序、添加復選框等內容,相信大家模型/視圖、自定義風格有了一定的了解,下面我們來分享一個更常用的內容-自定義進度條。

實現方式:

  1. 從QAbstractTableModel中設置對應的進度數據,因為我們需要顯示進度條,而不是直接顯示進度文本,所以原始的數據不需要直接顯示在界面上,所以不需要使用Qt::DisplayRole,可以使用Qt::UserRole來代替。

  2. 委托QStyledItemDelegate中根據進度索引所對應的數據來獲取進度,然后為QStyleOptionProgressBar設置進度值、顯示文本等信息。

  3. 設置樣式,這里需要QStyle在繪制的時候設置drawControl的最后一個參數,是一個QWidget *,這里我們使用QProgressBar即可。

效果

這里寫圖片描述

數據結構

下面定義了文件名、大小、狀態、進度所對應的列,以及一個保存數據的結構體。

#define FILE_DOWNLOAD_FILE_NAME_COLUMN 0
#define FILE_DOWNLOAD_SIZE_COLUMN 1
#define FILE_DOWNLOAD_STATUS_COLUMN 2
#define FILE_DOWNLOAD_PROGRESS_COLUMN 3

// 下載記錄
struct FileDownloadRecord
{
    QString strFileName;         //文件名稱
    qint64 nSize;                //大小
    int nStatus;                 //狀態
    int nProgress;               //進度
};

QStyledItemDelegate

這里只有繪制部分的代碼,model對應的代碼這里不再列出,可以參考其它對應的文章。

源碼

void ProgressBarDelegate::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_DOWNLOAD_PROGRESS_COLUMN)
    {
        int nProgress = index.model()->data(index, Qt::UserRole).toInt();
        int nLeft = 8;
        int nTop = 8;
        int nWidth = option.rect.width() - 2 * nLeft;
        int nHeight = option.rect.height() - 2 * nTop;

        // 設置進度條的風格
        QStyleOptionProgressBar progressBarOption;
        progressBarOption.initFrom(option.widget);
        // 設置進度條顯示的區域
        progressBarOption.rect = QRect(option.rect.left() + nLeft, option.rect.top() + nTop,  nWidth, nHeight);
        // 設置最小值
        progressBarOption.minimum = 0;
        // 設置最大值
        progressBarOption.maximum = 100;
        // 設置對齊方式
        progressBarOption.textAlignment = Qt::AlignCenter;
        // 設置進度
        progressBarOption.progress = nProgress;
        // 設置文本(百分比)
        progressBarOption.text = QString("%1%").arg(nProgress);
        // 設置文本可見
        progressBarOption.textVisible = true;

        QProgressBar progressBar;

        //繪制進度條
        QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter, &progressBar);
    }
}

QThread

為了模擬真實性,所以起了一個線程,每隔1秒刷新一次。

FileDownloadThread::FileDownloadThread(QObject *parent)
    : QThread(parent)
{
    qRegisterMetaType<QList<FileDownloadRecord>>("QList<FileDownloadRecord>");
}

FileDownloadThread::~FileDownloadThread()
{
    requestInterruption();
    wait();
}

void FileDownloadThread::run()
{
    while (!isInterruptionRequested())
    {
        QTime time;
        time= QTime::currentTime();
        qsrand(time.msec()+time.second()*1000);

        QList<FileDownloadRecord> list;
        for (int i = 0; i < 5; ++i)
        {
            FileDownloadRecord record;
            record.strFileName = QString("/root/user/file%1.log").arg(i + 1);
            record.nSize = 1024 / ((i + 2) *(i + 2)) ;
            record.nStatus = i;
            record.nProgress = qrand() % 100 + 1;

            list.append(record);
        }

        emit transfer(list);
        msleep(1000);
    }
}

樣式

QProgressBar{ border: none; text-align: center; background: rgb(210, 225, 240); }
QProgressBar::chunk { background: rgb(0, 160, 230); }

衍伸

這里為了美觀,我設置進度條距離左、上、右、下的距離均為8px,而且單元格里面只顯示了一個進度條。

這里只需要控制好單元格繪制區域位置rect即可,你可以在里面添加任意自定義的控件,而且可以添加任意多個,隨意排列組合。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM