如何重写自定义委托类的“绘制”功能以绘制QSpinBox

时间:2018-08-08 09:42:21

标签: c++ qt qt5 qstyleditemdelegate

我已向QTableView添加了一个自定义的委托人。当我双击一个项目时,我会看到编辑器窗口小部件,它是一个“ QSpinBox”,并且可以很好地编辑该值。一旦失去焦点,此编辑器小部件就会消失,据我所知。我想要的是QSpinBox一直在那儿。看一下Qt示例here,我知道我需要重写paint类的QAbstractItemDelegate函数来绘制QSpinBox,但是我不知道该怎么做。总的来说,我想知道如何在paint函数中绘制任何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();
}

2 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:1)

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

  1. 可以将小部件插入表单元格。我知道这不是您要尝试执行的操作,但是它可以解决您的问题。选中setIndexWidget
  2. 如果您确实要呈现QSpinBox,则应使用QWidget的render方法。要尝试,请在您的paint方法中创建一个QSpinBox并调用它的render方法,并将其传递给QPainter指针。以这种方式工作后,可以通过在QTableView中保留一个“模板” QSpinBox实例并在需要的地方使用它在单元格中呈现不同的QSpinBox值来改善设计