QTableView行样式

时间:2014-10-06 10:56:00

标签: c++ qt qtableview qt5.2 qtstylesheets

我有一个QTableView组件在行中显示几种类型的数据。我需要的是以不同的颜色显示每种类型的行。我的样式表看起来像这样:

RecordSheet::item {
        border: 0px;
        color: black;
        padding: 1px 0px 0px 3px;
}
RecordSheet::item:selected, RecordSheet::item:selected:!active {
        background-color: #e8b417;
        color: black;
}

我有两个想法如何实现这个目标:

  1. 在模型中使用data()方法并回复Qt::BackgroundColorRole。不幸的是,当我这样做时,背景颜色会被忽略,直到我从样式表中删除border: 0px;,当我删除边框时,样式面的填充将被忽略。奇怪...

  2. 为每种类型的行设置CSS / QSS类,并在样式表中设置它们的颜色。然后使用该模型为每种类型的行分配适当的类。所以样式表看起来像这样:

    RecordSheet::item {
        border: 0px;
        color: black;
        padding: 1px 0px 0px 3px;
    }
    RecordSheet::item[class=green_row] {
            background-color: green;
    }
    RecordSheet::item[class=red_row] {
            background-color: red;
    }
    

    我更喜欢这种方法,因为它将内容与外观分开,但我不知道如何做到这一点。也许使用ItemDelegate?

  3. 拜托,有没有人知道一个简单明了的解决方案?

    亲切的问候和非常感谢。

4 个答案:

答案 0 :(得分:2)

你不需要样式表来做这件事,styleshhet不是那么强大,无法做开发人员想要的所有事情。使用更强大的东西 - 委托。我将向您展示主要想法和工作实例。部首:

#ifndef ITEMDELEGATEPAINT_H
#define ITEMDELEGATEPAINT_H

#include <QStyledItemDelegate>

class ItemDelegatePaint : public QStyledItemDelegate
{
    Q_OBJECT
public:
    explicit ItemDelegatePaint(QObject *parent = 0);
    ItemDelegatePaint(const QString &txt, QObject *parent = 0);


protected:
    void paint( QPainter *painter,
                const QStyleOptionViewItem &option,
                const QModelIndex &index ) const;
    QSize sizeHint( const QStyleOptionViewItem &option,
                    const QModelIndex &index ) const;
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget * editor, const QModelIndex & index) const;
    void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
    void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;

signals:

public slots:

};

#endif // ITEMDELEGATEPAINT_H

这里有很多方法,但我只会给你画画,因为它对你来说是最重要的。有关您可以在web

中找到的其他方法的说明

CPP:

void ItemDelegatePaint::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QString txt = index.model()->data( index, Qt::DisplayRole ).toString();

    if(index.row() == 0)//green row
        painter->fillRect(option.rect,QColor(0,255,0));
    else
        if(index.row() == 1)//blue row
            painter->fillRect(option.rect,QColor(0,0,255));
    else
        if(index.row() == 2)//red row
            painter->fillRect(option.rect,QColor(255,0,0));
    //and so on

    if( option.state & QStyle::State_Selected )//we need this to show selection
    {
        painter->fillRect( option.rect, option.palette.highlight() );
    }


    QStyledItemDelegate::paint(painter,option,index);//standard processing
}

用法:

ui->tableView->setItemDelegate(new ItemDelegatePaint);

结果:

enter image description here

答案 1 :(得分:0)

尽管QItemDelegate是一个不错的选择,但是当你想要做的只是为一些细胞着色时,有时它只是一个过度杀戮。 你可以这样做:

QStandardItem *item = new QStandardItem("");
item->setData(Qt::gray, Qt::BackgroundColorRole);

这对我来说很有效。

答案 2 :(得分:0)

做一个尽可能简单和快速的事情是一个好主意。如果数据外观是您的概念,则无需添加额外的项目委托类,只需更改data()方法即可,它具有特定的作用,例如QT教程中的以下示例。 此方法适用于您不想更改数据(例如只读表)的情况,但是对于显示和编辑功能,@ Chernobyl提供了一个不错的解决方案QStyledItemDelegate

#ifndef MYMODEL_H
#define MYMODEL_H

#include <QAbstractTableModel>

class MyModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    MyModel(QObject *parent);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override ;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
};

#endif // MYMODEL_H


#include <QFont>
#include <QBrush>
#include "mymodel.h"
#include <QDebug>

MyModel::MyModel(QObject *parent)
    :QAbstractTableModel(parent)
{
}

int MyModel::rowCount(const QModelIndex & /*parent */) const
{
    return 2;
}

int MyModel::columnCount(const QModelIndex & /*parent */) const
{
    return 3;
}

//! [Quoting ModelView Tutorial]
// mymodel.cpp
QVariant MyModel::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    int col = index.column();
    // generate a log message when this method gets called
    qDebug() << QString("row %1, col%2, role %3")
            .arg(row).arg(col).arg(role);

    switch(role){
    case Qt::DisplayRole:
        if (row == 0 && col == 1) return QString("<--left");
        if (row == 1 && col == 1) return QString("right-->");

        return QString("Row%1, Column%2")
                .arg(row + 1)
                .arg(col +1);
        break;
    case Qt::FontRole:
        if (row == 0 && col == 0) //change font only for cell(0,0)
        {
            QFont boldFont;
            boldFont.setBold(true);
            return boldFont;
        }
        break;
    case Qt::BackgroundRole:

        if (row == 1 && col == 2)  //change background only for cell(1,2)
        {
            QBrush redBackground(Qt::red);
            return redBackground;
        }
        break;
    case Qt::TextAlignmentRole:

        if (row == 1 && col == 1) //change text alignment only for cell(1,1)
        {
            return Qt::AlignRight + Qt::AlignVCenter;
        }
        break;
    case Qt::CheckStateRole:

        if (row == 1 && col == 0) //add a checkbox to cell(1,0)
        {
            return Qt::Checked;
        }
    }
    return QVariant();
}
//! [Quoting ModelView Tutorial]


enter image description here

答案 3 :(得分:0)

有一种方法可以按照方法2使用CSS。以下代码显示了如何根据单元格的内容对每个单元格进行样式化。但是我敢肯定,您可以弄清楚如何将其扩展到为连续的每个单元格设置样式。同样,它是使用pyqt用python编写的,但仍处于关闭状态。

final List<Path> allFiles = Files.newDirectoryStream(folder)
                          .sorted((a, b) -> { ... })
                          .collect(Collectors.toList());

boolean firstHasBeenProcessed = false;
for (final Path currentFile: allFiles) {
    if (firstHasBeenProcessed) {
        processAsFollowUpFile(currentFile);
    } else {
        processAsFirstFile(currentFile);
        firstHasBeenProcessed = true;
    }
}

关键是将具有适当属性的窗口小部件传递给#!/usr/bin/python3 from PyQt5 import QtWidgets, QtGui, QtCore class_values = ["zero", "one", "two"] class Cell(QtWidgets.QWidget): def initFromItem(self, item): self.setProperty('dataClass', class_values[int(item.text())]) class TDelegate(QtWidgets.QStyledItemDelegate): def __init__(self, *a): super(TDelegate, self).__init__(*a) self.cell = Cell(self.parent()) def paint(self, painter, option, index): item = index.model().itemFromIndex(index) self.cell.initFromItem(item) self.initStyleOption(option, index) style = option.widget.style() if option.widget else QtWidgets.QApplication.style() style.unpolish(self.cell) style.polish(self.cell) style.drawControl(QtWidgets.QStyle.CE_ItemViewItem, option, painter, self.cell) class TTableModel(QtGui.QStandardItemModel): def __init__(self, parent=None): super(TTableModel, self).__init__(parent) for i in range(5): self.appendRow([QtGui.QStandardItem(str((x+i) % 3)) for x in range(5)]) class TTableView(QtWidgets.QTableView): def __init__(self, parent=None): super(TTableView, self).__init__(parent) self.setItemDelegate(TDelegate(self)) class Main(QtWidgets.QMainWindow): def __init__(self): super(Main, self).__init__() self.table = TTableView(self) self.model = TTableModel(self) self.table.setModel(self.model) self.setCentralWidget(self.table) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) app.setStyleSheet(""" Cell[dataClass=zero]::item { background-color: gray; } Cell[dataClass=one]::item { background-color: green; } Cell[dataClass=two]::itemn { background-color: cyan; } """) mainWin = Main() mainWin.show() sys.exit(app.exec_()) 。 CSS也必须引用drawControl才能发生任何事情。