• 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即可,你可以在里面添加任意自定义的控件,而且可以添加任意多个,随意排列组合。

  • 相关阅读:
    解决方案solution
    Marshal类
    鼠标钩子WH_MOUSE_LL和WH_MOUSE的区别
    DllImport
    打包.py文件成.exe
    C++定义全部变量注意项
    类.cpp文件不识别类.h所定义的结构体问题
    C++判断文件是否存在
    博客专栏
    软件测试基础知识
  • 原文地址:https://www.cnblogs.com/itrena/p/5938364.html
Copyright © 2020-2023  润新知