使用QStyledItemDelegate子类在QTableView中创建PushButtons

时间:2017-03-29 00:53:45

标签: qt qtableview qitemdelegate

我有完全相同的problem,但我将使用QTableView小部件。我读了this,想知道我是否可以覆盖createEditor函数来使用例如QFileDialog来获取新数据。

如果可以的话,任何人都可以向我提供一个实例来实现QItemDelegate这样的子类。

如果没有,任何人都可以向我提供一个实现QItemDelegate子类的示例,可以在QLineEdit旁边绘制一个按钮来获取功能here

编辑:也许这个问题真的很愚蠢而且我没有意识到,因为我离开了这个项目大约半年。

第二:从Qt 5.7更新到5.8是否安全?

2 个答案:

答案 0 :(得分:1)

我已尽力而为,这是我的解决方案。 QStyledItemDelegate子类的代码主要来自here

解决方案图片

然而,有一件事我很想解决:(也许有人可以帮助我并留下评论)

  • QPixmap::grabWidget is deprecated, use QWidget::grab() instead但看起来QWidget::grab()不是用于此目的的正确解决方案。

foo.h中:

#ifndef LIBRARYITEMDELEGATE_H
#define LIBRARYITEMDELEGATE_H

#include <QStyledItemDelegate>
#include <QWidget>
#include <QPushButton>
#include <QTableView>

class LibraryItemDelegate : public QStyledItemDelegate
{
    Q_OBJECT

public:
    explicit LibraryItemDelegate(QObject *parent = 0);
    ~LibraryItemDelegate();

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

public slots:
    void cellEntered(const QModelIndex &index);

private:
    QTableView *myView;
    QPushButton *btn;
    bool isOneCellInEditMode;
    QPersistentModelIndex currentEditedCellIndex;
};

#endif // LIBRARYITEMDELEGATE_H

Foo.cpp中:

#include "libraryitemdelegate.h"

#include <QPainter>
#include <QStylePainter>

LibraryItemDelegate::LibraryItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{
    if(QTableView *tableView = qobject_cast<QTableView*>(parent))
    {
        myView = tableView;
        btn = new QPushButton("...", myView);
        btn->hide();
        myView->setMouseTracking(true);
        connect(myView, SIGNAL(entered(QModelIndex)), this, SLOT(cellEntered(QModelIndex)));
        isOneCellInEditMode = false;
    }
}

LibraryItemDelegate::~LibraryItemDelegate(){}

void LibraryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
    {
        btn->setGeometry(option.rect);
        btn->setText("...");
        if(option.state == QStyle::State_Selected)
        {
            painter->fillRect(option.rect, option.palette.highlight());
        }
        QPixmap map = QPixmap::grabWidget(btn);
        painter->drawPixmap(option.rect.x(), option.rect.y(), map);
    }
    else
    {
        QStyledItemDelegate::paint(painter, option, index);
    }
}

//QSize LibraryItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
//{
//    // return the QSize of the item in Your view
//}

QWidget *LibraryItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
    {
        QPushButton *btn = new QPushButton(parent);
//        btn->setText(index.data().toString());
        btn->setText("...");
        return btn;
    }
    else
    {
        return QStyledItemDelegate::createEditor(parent, option, index);
    }
}

void LibraryItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
    {
        QPushButton *btn = qobject_cast<QPushButton*>(editor);
//        btn->setProperty("data_value", index.data());
        btn->setProperty("data_value", "...");
        btn->setText("...");
    }
    else
    {
        QStyledItemDelegate::setEditorData(editor, index);
    }
}

void LibraryItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
    {
        QPushButton *btn = qobject_cast<QPushButton*>(editor);
        model->setData(index, btn->property("data_value"));
    }
    else
    {
        QStyledItemDelegate::setModelData(editor, model, index);
    }
}

void LibraryItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

void LibraryItemDelegate::cellEntered(const QModelIndex &index)
{
    if(index.model()->headerData(index.column(), Qt::Horizontal, Qt::UserRole).toInt() == 1)
    {
        if(isOneCellInEditMode)
        {
            myView->closePersistentEditor(currentEditedCellIndex);
        }
        myView->openPersistentEditor(index);
        isOneCellInEditMode = true;
        currentEditedCellIndex = index;
    }
    else
    {
        if(isOneCellInEditMode)
        {
            isOneCellInEditMode = false;
            myView->closePersistentEditor(currentEditedCellIndex);
        }
    }
}

实现:

QStandardItemModel *myModel; // This is in the Header file

myModel = new QStandardItemModel(0,2,this);
myModel->setHeaderData(1, Qt::Horizontal, 1, Qt::UserRole);
myModel->setHorizontalHeaderLabels(QStringList(tr("Pfad zu den bibliotheks Ordnern")));

// Set Model and delegate to the View
ui->tableView_pathes->setModel(myModel);
LibraryItemDelegate *delegate = new LibraryItemDelegate(ui->tableView_pathes);
ui->tableView_pathes->setItemDelegate(delegate);

// Stretch only the first column
ui->tableView_pathes->horizontalHeader()->setSectionResizeMode(0,QHeaderView::Stretch);
ui->tableView_pathes->horizontalHeader()->setSectionResizeMode(1,QHeaderView::Fixed);

编辑:这是tableView中按钮的代码。将createEditor中的信号与connect(btn, SIGNAL(pressed()), this, SLOT(buttonPressed()));连接,并设置为委托提供对QStandardItemModel的引用。

void LibraryItemDelegate::buttonPressed()
{
    QString dir = QFileDialog::getExistingDirectory(new QWidget(), tr("Wähle die bibliotheks Ordner"), "/home", QFileDialog::ShowDirsOnly);

    qDebug() << "Test: " << dir;

    if(!dir.isEmpty())
    {
        QModelIndex ind = currentEditedCellIndex.model()->index(currentEditedCellIndex.row(), 0);
        myModel->setData(ind, dir, Qt::DisplayRole);
    }
}

答案 1 :(得分:0)

  1. 使用QStyledItemDelegate,而不是QItemDelegate。
  2. 阅读Qt手册
  3. QStyledItemDelegate class

    Spinboxdelegate Example

    1. 子类化QStyledItemDelegate的代码示例(已修剪):
    2. 标头文件

      #ifndef MYITEMDELEGATE_H
      #define MYITEMDELEGATE_H
      
      #include <QStyledItemDelegate>
      
      class KontaktForm;
      
      class MyItemDelegate : public QStyledItemDelegate
      {
          Q_OBJECT
      
          mutable SubscriberForm *subscriberForm;
      
      public:
          explicit MyItemDelegate(QObject *parent = 0);
          ~MyItemDelegate();
      
      
      ////////!Methods - You don't need all of them
          void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
          QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
          QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
          void setEditorData(QWidget *editor, const QModelIndex &index) const Q_DECL_OVERRIDE;
          void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const Q_DECL_OVERRIDE;
          void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE;
          void editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index);
      
      };
      
      #endif // MYITEMDELEGATE_H
      

      源文件

      #include "myitemdelegate.h"
      
      #include "mytreeview.h"
      #include <QModelIndex>
      #include <QSize>
      
      MyItemDelegate::MyItemDelegate(QObject *parent) : QStyledItemDelegate(parent),
          subscriberForm(Q_NULLPTR),
      {
      }
      
      QSize MyItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          //// return the QSize of the item in Your view
      }
      
      void MyItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          ////optional : implement custom painting - text, images, drawings, and such
      }
      
      
      QWidget *MyItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          subscriberForm = new SubscriberForm(parent);
          ////optional additional settings for Your editor
          return subscriberForm;      
      }
      
      void MyItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
      {
          editor->setGeometry(option.rect);
      }
      
      void MyItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
      {
          ////setup the editor - your data are in index.data(Qt::DataRoles) - stored in a QVariant;
          QString value = index.model()->data(index,Qt::EditRole).toString();
          SubscriberForm *subscriberForm =  static_cast<SubscriberForm*>(editor);
      }
      
      void MyItemDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
      {
          ////optional - if needed - return changed data, from editor to the model in a custom matter
      
          SubscriberForm *subscriberForm =  static_cast<SubscriberForm*>(editor);
          model->setData(index,QVariant(subscriberForm->getData()),Qt::EditRole);
      
      }