前段时间,我接触了,如何在一个QTableView中加入一个控件,类似于QCheckBox QProgressBar,QLineEdit等。
最近在项目中实际运用,才发现,在Qt中自定义委托,如果插入一个进度条。因为它很特殊,只能通过Paint进行绘画,而不是CreateEidtor()函数实现。
所以我就遇到问题:前期在表格里画好一列进度条时,后期如何及时更新进度条状态。如下图Qt中的例子
解决方法:今天才发现,实际Qt的MVC已经实现了自动更新,是我在Model中返回到QTableView的值写成%小数。于是在Delegate中获取界面上的int值总是0,以为没成功。。。。
稍微修改一下Model中的返回值就可以了,在界面中需要修改数据地方,只要调用Model中的setData()方法,里面调用 emit DataChanged()信号,就可以通知View和Delegate一起更新了。
源代码如下:
1、界面代码:QTableView、Model、Delegate初始化
/** *函数介绍:初始化重建作业队列 *输入参数:无 *返回值: 无 */ void MainWindow::initReconJob() { //数据源 ReconJob job1; job1.setReconJobId(1); job1.setReconJobState(2); job1.setPatientId(1); job1.setPatientName("test"); job1.setScanId(1); job1.setReconType(1); job1.setReconMode(1); job1.setSeriesDescrip("CT头部 "); job1.setSubTaskNum(15); job1.setFinishedSubTaskNum(0); job1.setRemainTime(95); job1.setPriority(1); job1.setRawDataFileName("rawData1.raw"); ReconJob job2; job2.setReconJobId(2); job2.setReconJobState(1); job2.setPatientId(1); job2.setPatientName("test"); job2.setScanId(1); job2.setReconType(1); job2.setReconMode(1); job2.setSeriesDescrip("CT头部 "); job2.setSubTaskNum(15); job2.setFinishedSubTaskNum(0); job2.setRemainTime(89); job2.setPriority(0); job2.setRawDataFileName("rawData2.raw"); ReconJob job3; job3.setReconJobId(3); job3.setReconJobState(1); job3.setPatientId(1); job3.setPatientName("test"); job3.setScanId(1); job3.setReconType(1); job3.setReconMode(1); job3.setSeriesDescrip("CT头部 "); job3.setSubTaskNum(15); job3.setFinishedSubTaskNum(0); job3.setRemainTime(89); job3.setPriority(0); job3.setRawDataFileName("rawData3.raw"); reconQueue.append(job1); reconQueue.append(job2); reconQueue.append(job3); for(int i = 4; i < 12; i++) { ReconJob job4; job4.setReconJobId(i); job4.setReconJobState(1); job4.setPatientId(1); job4.setPatientName("test"); job4.setScanId(1); job4.setReconType(1); job4.setReconMode(1); job4.setSeriesDescrip("CT头部 "); job4.setSubTaskNum(15); job4.setFinishedSubTaskNum(0); job4.setRemainTime(89); job4.setPriority(0); job4.setRawDataFileName("rawData.raw"); reconQueue.append(job4); } //自定义表模型 reconqueueModel = new MoReconQueue(); reconqueueModel->setReconQueue(reconQueue); //设置视图模型 ui.tableView->setModel(reconqueueModel); //设置行交替颜色 ui.tableView->setAlternatingRowColors(true); //只能单选一个项 ui.tableView->setSelectionMode(QAbstractItemView::SingleSelection); //选择行为为行 ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows); //内容窗口自适应 //ui.tableView->resizeColumnsToContents(); //隐藏第8列 总任务数 ui.tableView->setColumnHidden(8,true); //自定义表委托 delReconQueue = new DelReconQueue(); //设置视图委托 ui.tableView->setItemDelegate(delReconQueue); //自定义表模型 delReconQueue = new DelReconQueue(); //设置视图委托 ui.tableView->setItemDelegate(delReconQueue); //是否可以编辑在模型 MoReconQueue中flags()函数设置 //编辑事件 可以调用委托处理编辑数据 //ui.tableView->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked); //最后一列全部填充View //ui.tableView->horizontalHeader()->setStretchLastSection(true); } /** *函数介绍:更新首个重建作业状态 *输入参数:无 *返回值: 无 */ void MainWindow::updateReconJobState(QListjob) { QVariant finishedTaskNum = job.at(9); reconqueueModel->setData(reconqueueModel->index(0,9),finishedTaskNum); qDebug() <<"ssssssssssssssssssssssssssssssssssssssss" ; }
2、Model中的部分代码:修改Model中的某一项值。
//编辑一个项,(项索引,项值,角色) bool MoReconQueue::setData(const QModelIndex &index, const QVariant &value, int role) { //模型索引要有效,必须是修改角色 if (index.isValid()&& role == Qt::EditRole) { //行号 int row = index.row(); //列号 int column = index.column(); //获得原重建作业参数 ReconJob job = reconQueue.at(row); //更新重建作业参数 switch (column) { case 0: job.setReconJobId(value.toInt()); break; case 1: job.setReconJobState(value.toInt()); break; case 2: job.setPatientId(value.toInt()); break; case 3: job.setPatientName(value.toString()); break; case 4: job.setScanId(value.toInt()); case 5: job.setReconType(value.toInt()); break; case 6: job.setReconMode(value.toInt()); break; case 7: job.setSeriesDescrip(value.toString()); break; case 8: job.setSubTaskNum(value.toInt()); break; case 9: job.setFinishedSubTaskNum(value.toInt()); break; case 10: job.setRemainTime(value.toInt()); break; case 11: job.setPriority(value.toInt());; break; case 12: job.setRawDataFileName(value.toString());; break; default: return false; } //替换新的重建作业参数 reconQueue.replace(row,job); //某项发生改变,发射信号( between topLeft and bottomRight inclusive) emit dataChanged(index, index); return true; } return false; }
从自定义的数据源中获取数据
/** *函数介绍:获取类对象的属性值 *输入参数:无 *返回值: 无 */ QVariant MoReconQueue::reconQueueAt(int row, int column) const { QVariant var; int temp; int temp1; switch (column) { case 0: var = reconQueue.at(row).getReconJobId(); break; case 1: var = reconQueue.at(row).getReconJobState(); if(var == 1) var = "等待"; else if (var == 2) var = "进行中"; break; case 2: var = reconQueue.at(row).getPatientId(); //设置'病人Id'格式字符串: P:00000x;6位10进制数,不足补0; var = QString("P:%1").arg(var.toInt(), 6, 10, QChar('0')); break; case 3: var = reconQueue.at(row).getPatientName(); break; case 4: var = reconQueue.at(row).getPatientName(); break; case 5: var = reconQueue.at(row).getReconType(); if(var == 1) var = "PET重建"; else if (var == 2) var = "CT重建"; break; case 6: var = reconQueue.at(row).getReconMode(); if(var == 1) var = "auto"; else if (var == 2) var = "offline"; break; case 7: var = reconQueue.at(row).getSeriesDescrip(); break; case 8: var = reconQueue.at(row).getSubTaskNum(); break; case 9: temp = reconQueue.at(row).getFinishedSubTaskNum(); temp1 = reconQueue.at(row).getSubTaskNum(); //var = QString("%1 / %2").arg(temp,2,10,QChar('0')).arg(temp1,2,10,QChar('0')); var = temp; break; case 10: temp = reconQueue.at(row).getRemainTime(); var = QString("%1:%2s").arg(temp / 60, 2, 10, QChar('0')).arg(temp % 60, 2, 10, QChar('0'));; break; case 11: var = reconQueue.at(row).getPriority(); break; case 12: var = reconQueue.at(row).getRawDataFileName(); break; default: var = "无"; } return var; }
3、自定义委托中,重载Paint()函数
//重载绘制函数 void DelReconQueue::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { qDebug() << "`````````````````````行:"<< index.row() << "``````````````列:" << index.column() ; //如果是'已经完成子任务数' if (index.row()==0 && index.column() == 9) { const QAbstractItemModel *itemModel = index.model(); //获得索引对应Model中的数据 //double finishedSubTaskNum = itemModel->data(index, Qt::DisplayRole).toDouble(); int finishedSubTaskNum = index.data().toInt(); int subTaskNum = itemModel->data(itemModel->index(index.row(),8), Qt::DisplayRole).toInt(); qDebug() << "```````````````````````````````````finishedSubTaskNum:" << finishedSubTaskNum ; qDebug() << "```````````````````````````````````subTaskNum:" << subTaskNum ; //进度条的风格选项 QStyleOptionProgressBarV2 progressBarOption ; progressBarOption.rect = option.rect; progressBarOption.minimum = 0; progressBarOption.maximum = subTaskNum; progressBarOption.progress = finishedSubTaskNum; double t = finishedSubTaskNum/subTaskNum; progressBarOption.text = QString("%1 / %2").arg(finishedSubTaskNum,2,10,QChar('0')).arg(subTaskNum,2,10,QChar('0')); progressBarOption.textVisible = true; //绘制进度条 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter); } else { //否则调用默认委托 QStyledItemDelegate::paint(painter, option, index); } }
实现结果:
参考文章:
Qt自定义委托在QTableView中绘制控件、图片、文字