一. 关于十字形高亮的解决方法:
使用选择视图QItemSelectionModel
.
//将第row行与第column设置为高亮
void Widget::setHighlight(int row,int column)
{
QItemSelectionModel *selectionModel = tableWidget->selectionModel();
QModelIndex top = tableWidget->model()->index(row, column, QModelIndex());
QModelIndex bottom = tableWidget->model()->index(row, column, QModelIndex());
QItemSelection selection(top, bottom);
selectionModel->select(selection, QItemSelectionModel::Select|
QItemSelectionModel::Rows|QItemSelectionModel::Columns);
}
其中
QItemSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command)
Flags可以进行位操作。
参考资料:http://www.aichengxu.com/jiagou/6197787.htm
二. 关于将QtableWidget 中QComboBox的问题。
一开始自己的想法跑偏了(每点击单元格则生成QComboBox,第二次点击则将第一次的那个隐藏掉),如果这样的话,一个8行4列的table 最多需要实例化32个QComboBox,内存的问题就很严重了,而且怎么隐藏掉第一个也不好处理。(隐藏掉其实蛮好处理的,用成员变量记录上一次的cell,在本次点击时让其隐藏掉就好了。同时本次点击前要看一下点击的cell有没有被隐藏的combox 。 2017/1/23 修改)。
多谢老师的提醒:既然table中同一时刻只能显示一个QComboBox,那么不如将combox作为成员变量,整个表格就只有一个combox,这样一来不仅处理简单了,而且内存消耗也少了。
tableWidget->setCellWidget(row,column,combox);
下午发现这样做出现了一个问题, 一个单元格只能出现一次combox,暂时不知道是什么原因。
写了点东西调试一下很奇怪:
QWidget* tmp = tableWidget->cellWidget(row,column);
if(0 != tmp){
qDebug()<<"EEEnable"<<tmp->isEnabled();输出true
qDebug()<<"cellWidget" << tmp; //输出 QComboBox(0xa1a9f0)
qDebug()<<"1__Visible"<<tmp->isVisible(); //输出是 false
tmp->setVisible(true);
qDebug()<<"2__Visible"<< tmp->isVisible(); //输出还是 false
//delete tableWidget->cellWidget(row,column);
} else {
qDebug()<<"--------" << combox; //输出 QComboBox(0xa1a9f0)
combox->setVisible(true);
qDebug()<<"0__Visible"<<combox->isVisible(); //输出 false
tableWidget->setCellWidget(row,column,combox);
}
setVisible() 并没有发挥做用。
昨天下午问老师。老师说 一个combox 设置为多个cell 的widget 就好像一夫多妻制度一样不合时宜。 如果setcellwidget的话,最好是新建一个combox,每个cell里面都有自己的combox.一夫一妻制度。
昨晚问了一下Qt论坛的坛主,给的解释是这样的:
每个cell默认是有部件的,就是个label或lineEdit,现在用comboBox替换了那个label,就相当于把以前的label给delete掉了,那个cell都没有部件了,就变成不可选取了,所以你无法再向其中添加部件。
但是我在构造函数里加了段调试代码:
QWidget* tmp = tableWidget->cellWidget(1,1);
qDebug()<<"tmp"<<tmp; // 输出 tmp QWidget(0x0)
// qDebug()<<"enable"<<tmp->isEnabled();
//这句不注释掉会程序崩溃,应该是因为空指针的缘故。
if(0 != tmp){
qDebug() << 1;
}else{
qDebug()<<0;
}
这样看的话 默认状况下,cell里面应该是空才对。
另外一种解决方式是这样的:
计算一下cell的坐标,让combox 在cell那个位置显示。
一开始找到个系统自带的方法:
QRect rect = tableWidget->visualItemRect(tableWidget->item(row,column));
Returns the rectangle on the viewport occupied by the item at item.
但是问题在于 当item为空时,tableWidget->item(row,column)返回的是0。自然而然的返回的坐标就不对了。 因此这个方法不能用。
那就只能自己计算坐标了。行、列、行高、列宽,在加上tableWidget的坐标和主窗口坐标的一点偏差,就能算出来了。不过这种做法的健壮性就不知道怎样了。
int y = (row + 2)*highRow - (highRow/2);
int x = (column + 2)*widthCol - (widthCol/2);
// qDebug()<<"1_comboxVisible"<<combox->isVisible();
combox->setCurrentIndex(0);
combox->setVisible(true);
// qDebug()<<"2_comboxVisible"<<combox->isVisible();
combox->move(x,y);
这样实现,暂时并没有发现什么问题,希望能找到更好的方法。
这样做有问题: 扩大缩小窗口,就 不贴合了. 改用为每个cell建立combox得了。
四. 删除某一行的items
解决方式:
选定该行,然后遍历删除。
tableWidget->selectRow(row);
foreach (QTableWidgetItem *item, tableWidget->selectedItems()) {
delete item;
}
参考博客:http://www.educity.cn/wenda/190266.html
五.关于切片时显示
设计说明:使用QMessageBox 给用户显示切片牙齿。
void Widget::cutpiece()
{
int col = tableWidget->currentColumn();
int row = tableWidget->currentRow();
tableWidget->setItem(row,col,new QTableWidgetItem(QIcon(":/images/22.png"),"cutpiece",1));
QMessageBox::information(this,"CUTPIECE",tr("cut between %1 and %2").arg(row).arg(row+1));
}
五.关于加附件减附件成对出现
序列只能是 加减加减加减…且操作只能在序列最后添加。
在进行了加操作后,需要提醒用户设置减操作;
由于每次进行操作都保证了上面的条件,因此下一次操作依然满足条件。这样的话只需要判断距离(row,col)左右两侧是否存在附件并做相应操作就好了。
按照上面的思路写:
第一步.判断 (row,col) 到 (row,maxCol)如果有加减操作,则一切操作都不合法。
第二步.判断(row,col)到(row,0)第一个遇见的操作。是加操作则只能进行减操作,是减操作则只能进行加操作。
由于有三种附件类型,因此需要进行匹配。
可以将菜单中非法操作设置为不可选,这样用户无法进行点击。从而避免产生不成对现象。
有两种方式,
1.牺牲时间: 每次右击都检测该行的加减附件的操作。
2.牺牲空间: 建立新类Position 其成员变量有 ,操作类型(加,减),位置)
建立一个三个 Position 类型的数组,分别保存每一颗牙齿每一种附件的最后一个的操作类型以及位置。