【问题标题】:How to override 'paint' function of custom delegate class to draw QSpinBox如何覆盖自定义委托类的“绘制”功能以绘制 QSpinBox
【发布时间】:2018-08-08 09:42:20
【问题描述】:

我已向QTableView 添加了一个自定义委托人。当我双击一个项目时,我看到了一个“QSpinBox”的编辑器小部件,我可以很好地编辑该值。一旦失去焦点,这个编辑器小部件就会消失,我明白这一点。我想要的是QSpinBox 一直在那里。查看 Qt 示例 here 我知道我需要重写 QAbstractItemDelegate 类的 paint 函数来绘制 QSpinBox 但我不知道该怎么做。一般来说,我想知道如何在绘图函数中绘制任何 Qt 小部件。
作为参考,我有以下测试代码:

#include <QtWidgets/QApplication>
#include <QtGui>
#include <QTableview>
#include <QLayout>
#include <QColor>
#include <QStyledItemDelegate>
#include <QSpinbox>

class SpinBoxDeligate : public QStyledItemDelegate {
public:
    QWidget * createEditor(QWidget *parent,
        const QStyleOptionViewItem &option,
        const QModelIndex &index) const override {
        auto w = new QSpinBox(parent);
        w->setFrame(false);
        w->setMinimum(0);
        w->setMaximum(100);
        return w;
    }

    void setEditorData(QWidget *editor, const QModelIndex &index) const override {
        static_cast<QSpinBox*>(editor)->setValue(index.data(Qt::EditRole).toInt());
    }

    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override {
        model->setData(index, static_cast<QSpinBox*>(editor)->value(), Qt::EditRole);
    }

    void paint(QPainter *painter, const QStyleOptionViewItem &option,
        const QModelIndex &index) const
    {
        // What to replace below line with to have a QSpinBox
        QStyledItemDelegate::paint(painter, option, index);
    }
};


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

    QStandardItemModel model(3, 1);

    for (int r = 0; r < 3; ++r)
    {
        auto text = QString("%0").arg(r);
        QStandardItem* item = new QStandardItem(text);

        item->setFlags(Qt::ItemIsUserCheckable
            | Qt::ItemIsEnabled
            | Qt::ItemIsEditable
        );
        item->setData(Qt::Unchecked, Qt::CheckStateRole);
        item->setData(text, Qt::ToolTipRole);
        item->setData(QSize(100, 30), Qt::SizeHintRole);
        item->setData(QIcon(":/QtMVC/Desert.jpg"), Qt::DecorationRole);
        model.setItem(r, 0, item);
    }

    QTableView* table = new QTableView();
    table->setModel(&model);
    table->setItemDelegate(new SpinBoxDeligate());

    QWidget w;
    QVBoxLayout* containerLayout = new QVBoxLayout();
    w.setLayout(containerLayout);
    containerLayout->addWidget(table);
    w.show();

    return app.exec();
}

【问题讨论】:

    标签: c++ qt qt5 qstyleditemdelegate


    【解决方案1】:

    您的背景问题的一个可能解决方案是使用paint(),为此您可以创建一个 QSpinBox 并使用抓取来拍摄图像,但在此之前您应该计算几何形状以使其不覆盖 QCheckBox,如你看这是一项乏味的工作,另一种方法是使用 QStyle,但它仍然是更多的代码。

    一个简单的解决方案是使用openPersistentEditor() 方法使编辑器保持打开状态。

    int main(int argc, char** argv)
    {
        QApplication app(argc, argv);
    
        QStandardItemModel model(3, 1);
        QTableView* table = new QTableView();
        table->setModel(&model);
    
        table->setItemDelegate(new SpinBoxDeligate());
    
        for (int r = 0; r < 3; ++r)
        {
            auto text = QString("%0").arg(r);
            QStandardItem* item = new QStandardItem(text);
    
            item->setFlags(Qt::ItemIsUserCheckable
                | Qt::ItemIsEnabled
                | Qt::ItemIsEditable
            );
            item->setData(Qt::Unchecked, Qt::CheckStateRole);
            item->setData(text, Qt::ToolTipRole);
            item->setData(QSize(100, 30), Qt::SizeHintRole);
            item->setData(QIcon(":/QtMVC/Desert.jpg"), Qt::DecorationRole);
    
            model.setItem(r, 0, item);
            table->openPersistentEditor(model.indexFromItem(item));
        }
    
        QWidget w;
        QVBoxLayout* containerLayout = new QVBoxLayout();
        w.setLayout(containerLayout);
        containerLayout->addWidget(table);
        w.show();
    
        return app.exec();
    }
    

    【讨论】:

    • 感谢分享简单的解决方案,我不知道。如果可能的话,您能否分享与您提到的QStyle 相关的解决方案。我很想知道如何使用QStyle 绘制小部件。再次感谢所有帮助。
    • @Sajal 我在实现这个方面遇到了困难,首先是QCheckBox,我不知道如何计算它的大小,另一方面我相信它的实现意味着监控实现的元素对我来说,这涉及不必要的努力。
    • 没问题,我明白了。我只是想知道绘制QSpinBox 忽略复选框会更简单,假设我们有所有可用的项目空间来绘制QSpinBox
    【解决方案2】:

    我能想到两种可能的解决方案:

    1. 可以将小部件插入表格单元格。我知道这不是您想要做的,但它可以成为您问题的更好解决方案。检查setIndexWidget
    2. 如果你真的想渲染QSpinBox,你应该使用QWidget的render方法。要尝试,在您的 paint 方法中创建一个 QSpinBox 并调用它的渲染方法,并将 QPainter 指针传递给它。以这种方式工作后,您可以通过在 QTableView 中保存一个“模板”QSpinBox 实例并使用它在需要的单元格内呈现不同的QSpinBox 值来改进您的设计

    【讨论】:

      猜你喜欢
      • 2023-03-15
      • 1970-01-01
      • 2015-03-14
      • 1970-01-01
      • 2013-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多