说明
关于Qt的MVC模型视图框架本文就不多介绍了,本文仅记录一次自定义模型时遇到的问题。
一、问题描述
重写headerData函数,设置表头数据时,发现BackgroundColorRole设置背景色无效的问题,而其他的例如ForegroundRole,FontRole等都正常。部分主要代码如下:
void PositionDataForm::initui()
{
m_delegate = new ItemDelegate(this);
pSetModel();
QList<QTableView*> pList;
pList.append(ui->tableView_posnight);
pList.append(ui->tableView_pos_dayshift);
foreach (QTableView* view, pList) {
view->setItemDelegate(m_delegate); //为视图设置委托
view->setDragEnabled(false); //控件不允许拖动
// view->setModel(mPositionModel);
view->show();
view->setShowGrid(false);
view->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);//ResizeToContents自适应宽度,Stretch各列平均分配列宽
view->verticalHeader()->setDefaultSectionSize(70);//设置默认行高
view->horizontalHeader()->resizeSection(0,50); //设置表头第一列的宽度为150
view->horizontalHeader()->setFixedHeight(50); //设置列表头的高度
view->verticalHeader()->setFixedWidth(100); //设置行表头的宽度
view->verticalHeader()->setVisible(false);
view->setSelectionMode(QAbstractItemView::SingleSelection);//单选
view->setEditTriggers(QAbstractItemView::NoEditTriggers);//禁止编辑
// view->setSelectionBehavior(QAbstractItemView::SelectRows); //设置选择行为时每次选择一行
// view->horizontalHeader()->setVisible(false);
// view->horizontalHeader()->setStretchLastSection(true); //设置充满表宽度
// view->setFrameShape(QFrame::NoFrame); //设置无边框
// view->verticalHeader()->setVisible(false); //设置垂直头不可见
// view->setSelectionMode(QAbstractItemView::ExtendedSelection); //可多选(Ctrl、Shift、 Ctrl+A都可以)
// view->setSelectionBehavior(QAbstractItemView::SelectRows); //设置选择行为时每次选择一行
}
whiteDayModel = new PSortFilterProxyModel(0,12,2);
nightModel = new PSortFilterProxyModel(12,24,2);
whiteDayModel->setSourceModel(mPositionModel);
nightModel->setSourceModel(mPositionModel);
ui->tableView_pos_dayshift->setModel(whiteDayModel);
ui->tableView_posnight->setModel(nightModel);
}
void PositionDataForm::pSetModel()
{
mPositionModel = new QStandardItemModel(24,7);
mPositionModel->setHorizontalHeaderLabels(TimeHorHeaderList);
QStringList TimeLabelList;
for(int i=0;i<24;i++){
TimeLabelList.append(QString("%1:30-%2:30").arg(8+i>=24?8+i-24:8+i).arg(8+i+1>=24?8+i+1-24:8+i+1));
}
for(int r =0;r<24;r++)
{
QStandardItem *item = new QStandardItem();
item->setData(TimeLabelList.at(r),Qt::UserRole);
item->setData(QColor(0,0,0),Qt::ForegroundRole);
item->setData(QColor(200,200,200),Qt::BackgroundRole);
mPositionModel->setItem(r, 0, item);
}
for (int row =0; row < 24; ++row) {
for (int column = 1; column < 7; ++column) {
QStandardItem *item = new QStandardItem(QString("%1-%2").arg(row).arg(column));
item->setData(QString("0(0%)"),Qt::UserRole);
item->setData(QColor(0,0,0),Qt::ForegroundRole);
item->setData(QColor(255,255,255),Qt::BackgroundRole);
mPositionModel->setItem(row, column, item);
}
}
}
模型使用QStandardItemModel作为源模型,ItemDelegate自定义委托,继承自QStyledItemDelegate,用于自定义绘制。PSortFilterProxyModel从QSortFilterProxyModel派生,主要作用为区分时间段白夜班,类定义如下:
#include "psortfilterproxymodel.h"
PSortFilterProxyModel::PSortFilterProxyModel(quint8 start, quint8 end, quint8 goodcol, QObject *parent):
QSortFilterProxyModel(parent),
sRow(start),eRow(end),mgoodcol(goodcol)
{
}
bool PSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
if(sRow <= source_row && source_row<eRow){
return true;
}else{
return false;
}
return QSortFilterProxyModel::filterAcceptsRow(source_row,source_parent);
}
QVariant PSortFilterProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(Qt::Horizontal == orientation && role == Qt::ForegroundRole){
return QVariant(QColor(0,0,255));
}else if(Qt::Horizontal == orientation && role == Qt::BackgroundColorRole){//此处不生效
if(section<mgoodcol) return QVariant(QColor(0,0,255));
else if(section==mgoodcol) return QVariant(QColor(0,255,0));
else return QVariant(QColor(255,0,0));
}else if(Qt::Horizontal == orientation && role == Qt::FontRole){
return QFont("微软雅黑", 15, QFont::Bold);
}
return QSortFilterProxyModel::headerData(section,orientation,role);
}
可以看到,字体及其颜色没毛病,但是背景设置无效,依然是白色!被这个问题困扰了三天,各种尝试,首先想到的肯定是直接设置样式tableview的setstylesheet,这个办法可以,但是没办法根据动态来调整不同列显示不同的背景色,因此放弃,继续寻找摸索。
百度了很久也没找到类似的帖子,只看到这个相同问题的:http://cn.voidcc.com/question/p-rtqtxfip-bdu.html
然后在Qt的bug反馈里面看到了一点有用的信息:https://bugreports.qt.io/browse/QTBUG-31804
据说好像是Qt的各平台风格的问题,QHeadView是通过绘制调色板来设置背景色,而有些风格样式不是基于调色板的,因此无效。
到了这里,总算搞清楚了,但是怎么解决呢?于是乎,继续百度windows的风格样式相关的,终于找到了,链接如下:
https://www.gxlsystem.com/qianduan-344170.html
QApplication::setStyle(QStyleFactory::create("fusion"));
抱着试一试的心态,居然可以了,真特么的坑啊。。。
#include "mainwindow.h"
#include <QApplication>
#include <QStyleFactory>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<< QStyleFactory::keys();//("Windows", "WindowsXP", "WindowsVista", "Fusion")
QApplication::setStyle(QStyleFactory::create("Fusion"));
MainWindow w;
w.show();
return a.exec();
}
//根据QT4文档的说明,windows下支持 "windows", "motif", "cde", "plastique" and "cleanlooks"
//而QT5文档说明,windows下只支持 "windows" and "fusion"
修改后运行如下:
虽然这个颜色看起来怪怪的,于是乎又尝试了windows的风格,如下:
QApplication::setStyle(QStyleFactory::create("Windows"));
效果:
好家伙,这才是255的蓝,由于字体也是255蓝,覆盖了,到了这里,问题也解决了。。。但还是不死心,于是有尝试了windowsxp和WindowsVista,发现无效,,合着不设置的话,那默认应该就是这两货之一。
另外,如果修改了全局的话,会影响其他控件,可以单独设置某个控件的风格,如下:
ui->tableView_pos_dayshift->setStyle(QStyleFactory::create("Fusion"));
这样也是可以的
总结
本文仅代表我个人方案,可能不适合所有人,如果你看到了这批文章或者你也遇到了类似的问题,并且有其他的解决方法或想法,欢迎留言讨论,共同进步。