Qt5子类化QStyledItemDelegate格式化

时间:2016-08-31 08:20:32

标签: qt qt5 qstyleditemdelegate

我正在为Qt5中的SQLite数据库开发GUI。我使用QSqlQueryModelQTableView来存储和显示数据。

然后我创建了一个自定义委托,使用switch语句将某些列的数值替换为表视图中的文字(例如1 =“Hello”,2 =“World”)。

委托显示数据,并且功能正常。但是,与QStyledItemDelegate的默认绘制方法相比,自定义委托绘制的列具有不同的格式。值在左上角而不是左上角,更改的列不再自动扩展列以显示完整值,并且列中的单元格在选中时不会变为蓝色或具有虚线轮廓。

我创建了这个示例程序:

#include <QApplication>
#include <QModelIndex>
#include <QPainter>
#include <QStandardItemModel>
#include <QStyledItemDelegate>
#include <QTableView>


class TestDelegate: public QStyledItemDelegate {

    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)
        const Q_DECL_OVERRIDE
    {
        if (index.column() == 0) {
            int value = index.model()->data(index, Qt::DisplayRole).toInt();
            QString str;
            switch (value) {
            case 1:
                str = "Hello0000";
                break;
            case 2:
                str = "World0000";
                break;
            }
            if (option.state.testFlag (QStyle::State_Selected)) {
                painter->fillRect(option.rect, option.palette.highlight());
                qApp->style()->drawItemText(painter, option.rect, option.displayAlignment, option.palette, true, str, QPalette::HighlightedText);
            } else { 
                painter->drawText(option.rect, option.displayAlignment, str);
            } 
        } else {
            return QStyledItemDelegate::paint(painter, option, index);
        }
    }

};


int main(int argc, char **argv) {
    QApplication app(argc, argv);

    QStandardItemModel model(2, 2);
    model.setHorizontalHeaderItem(0, new QStandardItem(QString("A")));
    model.setHorizontalHeaderItem(1, new QStandardItem(QString("B")));
    model.setData(model.index(0, 0, QModelIndex()), 1);
    model.setData(model.index(1, 0, QModelIndex()), 2);
    model.setItem(0, 1, new QStandardItem(QString("Hello")));
    model.setItem(1, 1, new QStandardItem(QString("World0000")));

    QTableView view;
    view.setItemDelegate(new TestDelegate);
    view.setModel(&model);
    view.resizeColumnsToContents();

    view.show();
    app.exec();
}

这可以通过将options.displayAlignment添加到painter->drawText()来修复文本对齐方式。我还在if(option.state & QStyle::State_Selected)语句中添加了其他代码,根据其选择状态绘制单元格。因此,如果未选中,则文本为黑色,如果是文本变为白色且背景为蓝色。但是,我仍然无法扩展列以适应单元格的内容,或者在单元格外部添加虚线,就像使用标准委托一样。

使用自定义绘制方法时,是否有一种简单的方法来维护表视图的默认样式?

1 个答案:

答案 0 :(得分:0)

代表是一种相当迂回且不必要的方式。我们已经有了一个视图,可以完美地描绘元素,无需重做。我们只需要将修改后的数据传递给视图。因此,我们在源和视图之间插入QIdentityProxyModel视图模型。

// https://github.com/KubaO/stackoverflown/tree/master/questions/proxy-reformat-39244309
#include <QtWidgets>

class RewriteProxy : public QIdentityProxyModel {
    QMap<QVariant, QVariant> m_read, m_write;
    int m_column;
public:
    RewriteProxy(int column, QObject * parent = nullptr) :
        QIdentityProxyModel{parent}, m_column{column} {}
    void addReadMapping(const QVariant & from, const QVariant & to) {
        m_read.insert(from, to);
        m_write.insert(to, from);
    }
    QVariant data(const QModelIndex & index, int role) const override {
        auto val = QIdentityProxyModel::data(index, role);
        if (index.column() != m_column) return val;
        auto it = m_read.find(val);
        return it != m_read.end() ? it.value() : val;
    }
    bool setData(const QModelIndex & index, const QVariant & value, int role) override {
        auto val = value;
        if (index.column() == m_column) {
            auto it = m_write.find(value);
            if (it != m_write.end()) val = it.value();
        }
        return QIdentityProxyModel::setData(index, val, role);
    }
};

int main(int argc, char ** argv) {
    QApplication app{argc, argv};
    QStandardItemModel model{2,2};
    model.setData(model.index(0, 0), 1);
    model.setData(model.index(1, 0), 2);
    model.setData(model.index(0, 1), "Zaphod");
    model.setData(model.index(1, 1), "Beeblebrox");

    RewriteProxy proxy{0};
    proxy.setSourceModel(&model);
    proxy.addReadMapping(1, "Hello");
    proxy.addReadMapping(2, "World");

    QTableView ui;
    ui.setModel(&proxy);
    ui.show();
    return app.exec();
}