前段时间,我接触了,如何在一个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(QList<QVariant> job)
{
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中绘制控件、图片、文字