用表格来展示采集到的数据,是很多组态系统中最常见的方法,一个表格能够展示的数据特别多,在本系统中,默认做的也是通过表格的形式来展示数据,目前是将所有的设备放在一个表格中,后期可能按照不同控制器对应一个表格,一般来说一个场所对应一个控制器,一个控制器下面会有很多个探测器,相当于终端传感器,最终这些终端传感器采集到的数据,传给控制器,控制器打包上发,软件这边接收到以后根据不同的位解析对应的数据。
表格展示数据,需要对不同状态的数据不同颜色显示,这样一目了然,比如至少区分正常状态、低报状态、高报状态、离线状态这几种,对应的文字颜色正常绿色、低报黄色、高报红色、离线黑色等,当然这些具体颜色可以在系统设置中配置。理想是好的,现实很残忍,就比如这个颜色显示,调用setForeground是可以设置好文字颜色,但是使用过程中你会发现,和全局的样式表冲突了,鼠标移上去之后变成了悬停的颜色了,但是QTableWidgetItem并没有提供悬停颜色、按下颜色的单独设置。
这个时候委托就派上用场了,或者自定义一个QTableWidget拦截重新painter,终极大法建议用自定义委托,更万能更安全,而且更通用,相当于设置一个自定义禁用委托列,设置到对应的列,然后改列悬停也好按下也罢,都是按照默认的文字颜色绘制,并不要用全局样式表中的颜色,这样就完美的避开了冲突的缺陷。很多人其实都遇到了这个问题,明明通过setForeground、setTextColor设置了颜色,结果鼠标移上去就变了,导致看到的效果和实际的效果不一致。
void frmViewData::initForm()
{
//初始化设备表格数据
DeviceHelper::setTableData(ui->tableWidget);
DeviceHelper::initDeviceData();
//设置自定义委托以便原有的颜色不改变 不然选中行的时候会应用样式的颜色
DbDelegate *d_disable7 = new DbDelegate(this);
d_disable7->setDelegateEnable(false);
d_disable7->setDelegateColumn(7);
ui->tableWidget->setItemDelegateForColumn(7, d_disable7);
DbDelegate *d_disable9 = new DbDelegate(this);
d_disable9->setDelegateEnable(false);
d_disable9->setDelegateColumn(9);
ui->tableWidget->setItemDelegateForColumn(9, d_disable9);
}
void DeviceHelper::initDeviceData()
{
if (deviceData == NULL) {
return;
}
QList<QString> columnNames = AppData::TableDataColumns.split("|");
QList<int> columnWidths;
if (QUIHelper::deskWidth() < 1360) {
columnWidths << 50 << 100 << 110 << 100 << 120 << 90 << 80 << 70 << 70 << 70;
} else if (QUIHelper::deskWidth() < 1440) {
columnWidths << 50 << 110 << 130 << 110 << 140 << 100 << 80 << 70 << 70 << 70;
} else {
columnWidths << 55 << 115 << 140 << 130 << 150 << 120 << 80 << 70 << 70 << 70;
}
//设置列数列宽标题文本集合等
int columnCount = columnNames.count();
deviceData->setColumnCount(columnCount);
deviceData->setHorizontalHeaderLabels(columnNames);
for (int i = 0; i < columnCount; ++i) {
deviceData->setColumnWidth(i, columnWidths.at(i));
}
//载入数据
deviceData->setRowCount(DbData::NodeInfo_Count);
for (int i = 0; i < DbData::NodeInfo_Count; ++i) {
//过滤没有对应设备的探测器
int index = DbData::DeviceInfo_DeviceName.indexOf(DbData::NodeInfo_DeviceName.at(i));
if (index < 0) {
continue;
}
QStringList data;
data << QString::number(i + 1);
data << DbData::NodeInfo_PositionID.at(i);
data << DbData::NodeInfo_DeviceName.at(i);
data << DbData::DeviceInfo_DeviceType.at(index);
data << DbData::NodeInfo_NodeName.at(i);
data << DbData::NodeInfo_NodeType.at(i);
data << DbData::NodeInfo_NodeClass.at(i);
data << QString::number(0);
data << DbData::NodeInfo_NodeSign.at(i);
data << "离线";
//后面这几个值是为了方便判断报警范围
data << QString::number(DbData::NodeInfo_NodeUpper.at(i));
data << QString::number(DbData::NodeInfo_NodeLimit.at(i));
data << DbData::NodeInfo_AlarmType.at(i);
addData(data);
}
}
void DeviceHelper::addData(const QStringList &data)
{
if (deviceData == NULL) {
return;
}
//需要居中的列索引集合
QList<int> centerColumn;
centerColumn << 0 << 5 << 6 << 7 << 8 << 9;
//这里行数还必须是静态变量因为会多次调用
static int row = -1;
row++;
for (int i = 0; i < data.count() - 2; ++i) {
QTableWidgetItem *item = new QTableWidgetItem(data.at(i));
if (centerColumn.contains(i)) {
item->setTextAlignment(Qt::AlignCenter);
}
//加粗+不同颜色显示对应的数值和状态
if (i == 7 || i == 9) {
QFont font;
font.setPixelSize(QUIConfig::FontSize + 2);
font.setBold(true);
item->setFont(font);
//最后状态列调用函数设置一次
if (i == 9) {
float value = data.at(i - 2).toFloat();
float max = data.at(i + 1).toFloat();
float min = data.at(i + 2).toFloat();
setColor(deviceData->item(row, 7), item, value, max, min);
}
}
deviceData->setItem(row, i, item);
}
}
void DeviceHelper::clearData()
{
if (deviceData == NULL) {
return;
}
deviceData->clearContents();
}