2017-03-29 3 views
1

J'ai exactement le même problem, mais je vais utiliser le widget QTableView. J'ai lu this et je me demandais si je peux remplacer la fonction createEditor à utiliser par exemple QFileDialog pour obtenir les nouvelles données.Créer PushButtons dans QTableView avec QStyledItemDelegate sous-classe

Si cela est possible, quelqu'un peut-il me fournir un exemple pour implémenter une telle sous-classe à QItemDelegate.

Et si non, quelqu'un peut-il me fournir un exemple pour implémenter une sous-classe à QItemDelegate, qui peut dessiner un bouton à côté d'un QLineEdit pour obtenir la fonctionnalité here. Edit: Peut-être que cette question est vraiment stupide et je ne réalise pas, parce que j'ai quitté le projet pendant environ une demi-année. Deuxièmement: est-il sûr de mettre à jour de Qt 5.7 à 5.8?

Répondre

0
  1. Utilisez QStyledItemDelegate, pas QItemDelegate.
  2. Lire le manuel Qt

QStyledItemDelegate class

Spinboxdelegate Example

  1. Exemple de code de sous-classé QStyledItemDelegate (dégrossi):

fichier d'en-tête

#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 

Fichier source

#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); 

} 
+0

Est-ce que cela fonctionne réellement? Par exemple, le contrôle disparaît une fois l'édition terminée. – Mikhail

+0

@Mikhail Ce code provient de mon application, donc cela devrait fonctionner. Mais il y a une chance que j'ai oublié de coller quelque chose, donc si vous l'avez essayé, et ça n'a pas marché, faites le moi savoir. – Szpaqn

+0

Oui, donc le bouton disparaîtra quand sa cellule n'est pas activée. Ou plus précisément, 'paint()' est appelé, ce qui ne fait rien. Comment garder le bouton présent lorsqu'il n'est pas activé n'est pas trivial, vous pouvez voir l'autre réponse utilisée une méthode de capture d'écran obsolète. – Mikhail

1

je l'ai fait de mon mieux et voici ma solution. Le code de la sous-classe QStyledItemDelegate est principalement de here.

Solution Photo

Cependant, il y a une des choses que je suis curieux de fixer: (peut-être quelqu'un peut me aider et a laissé un commentaire)

  • QPixmap::grabWidget is deprecated, use QWidget::grab() instead mais il ressemble QWidget::grab() n'est pas la bonne solution à cette fin.

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); 
     } 
    } 
} 

Mise en œuvre:

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); 

Edit: Voici le code pour les boutons du tableView. Connectez les signaux dans createEditor avec connect(btn, SIGNAL(pressed()), this, SLOT(buttonPressed())); et définissez le délégué au 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); 
    } 
} 
+0

J'ai utilisé Widget :: grab() comme ceci: painter-> drawPixmap (r.left(), r.right(), r.width(), r.height(), widget-> grab()) ; Mais il y a quelque temps, et je ne me souviens pas comment cela a fonctionné. – Szpaqn