从QStyledItemDelegate中的组合框中调用对话框

问题描述:

所以我在这里是QAbstractTableModel的委托代码。第二列(索引= 1)始终是一个组合框。该comboBox有我的模拟中给定单元可以执行的动作列表。点击构建或训练等特定动作后,我想要弹出一个对话框给用户一组选择。在做出选择之后,代表应该更新模型的数据并继续前进。从QStyledItemDelegate中的组合框中调用对话框

这里是我碰到的障碍。如果我尝试从setModelData(),setEditorData()调用对话框,那些函数是常量,所以我不能分配对话框的结果给任何东西。

我试图做的是从createEditor()中创建的QComboBox连接信号indexChanged(QString)。这至少允许我分配结果并仅在做出适当选择时调用对话框。但是我不断收到Seggy故障,并且QTCreator中的跟踪不会着陆在C代码上(33次调用程序集)。我不确定为什么我得到了那个seggy。

当我尝试这种方法时,对话框出现后,表格不再有组合框。它恢复到之前的状态,并且只要程序离开我为QComboBox :: indexChanged(QString)创建的插槽,就发生了seggy。

任何帮助将不胜感激,

JEC

DelegateAction.h

#ifndef DELEGATEACTION_H 
#define DELEGATEACTION_H 

#include <QVariant> 
#include <QStyledItemDelegate> 
#include <QString> 

#include <QApplication> 
#include <QWidget> 
#include <QLabel> 
#include <QComboBox> 
#include <QProgressBar> 
#include <QMouseEvent> 

#include <JECMessageTable.h> 

#include <UnitBase.h> 
#include <ModelListUnit.h> 

class DelegateAction : public QStyledItemDelegate 
{ 
    Q_OBJECT 
public: 
    explicit DelegateAction(QObject *parent = 0); 
    ~DelegateAction(); 

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; 
    void setEditorData(QWidget *editor, const QModelIndex &index) const; 
    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; 
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; 
    QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; 

public slots: 
    void setUnits(QList<Unit*>* units); 

protected: 
    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; 
    //bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index); 
private slots: 
    void comboChanged(QString string); 
    void comboDestroyed(); 

private: 
    bool comboUpdated; 
    const UnitBase* selectedUnit; 
    ModelListUnit *model;   // The model for the JECMessageTable. 

    QList<Unit*>* units;  // The current list of units. 

}; 

#endif // DELEGATEACTION_H 

DelegateAction.cpp

#include "DelegateAction.h" 

DelegateAction::DelegateAction(QObject *parent) : 
    QStyledItemDelegate(parent), 
    selectedUnit(0), 
    model(0) 
{ 
} 

DelegateAction::~DelegateAction() 
{ 
    delete model; 
} 

QWidget * DelegateAction::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    QWidget* editor = 0; 

    switch (index.column()) 
    { 
    case 0: 
    default: 
    { 
     editor = new QLabel(); 
     break; 
    } 
    case 1: 
    { 
     QComboBox* combo = new QComboBox(parent); 
     combo->addItem("Idle"); 
     combo->addItem("Gather"); 
     combo->addItem("Train"); 
     combo->addItem("Build"); 
     combo->addItem("Upgrade"); 
     editor = combo; 
//  connect(combo, SIGNAL(currentIndexChanged(QString)), this, SLOT(comboChanged(QString))); 
//  connect(combo, SIGNAL(destroyed()), this, SLOT(comboDestroyed())); 
     break; 
    } 
    case 4: 
    { 
     editor = new QProgressBar(parent); 
     break; 
    } 
    } 

    editor->installEventFilter(const_cast<DelegateAction*>(this)); 
    return editor; 
} 

void DelegateAction::setEditorData(QWidget *editor, const QModelIndex &index) const 
{ 
    QVariant value = index.model()->data(index, Qt::DisplayRole); 

    switch (index.column()) 
    { 
    case 0: 
    default: 
    { 
     QLabel* label = static_cast<QLabel*>(editor); 
     label->setText(value.toString()); 
     break; 
    } 
    case 1: 
    { 
     QComboBox* combo = static_cast<QComboBox*>(editor); 
     combo->setCurrentIndex(combo->findText(value.toString())); 

     break; 
    } 
    case 4: 
    { 
     QProgressBar* progress = static_cast<QProgressBar*>(editor); 
     progress->setValue(value.toInt()); 
     break; 
    } 
    } 

} 

void DelegateAction::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const 
{ 
    QVariant value; 
    switch (index.column()) 
    { 
    case 0: 
    default: 
    { 
     value = static_cast<QLabel*>(editor)->text(); 
     break; 
    } 
    case 1: 
    { 
     QString string = static_cast<QComboBox*>(editor)->currentText(); 

     switch (Action::getType(string)) 
     { 
     case Action::INVALID: 
     { 
      return; 
     } 
     case Action::IDLE: 
     { 
      return; 
     } 
     case Action::GATHER: 
     { 
      return; 
     } 
     case Action::BUILD: 
     { 
      return; 
     } 
     case Action::TRAIN: 
     { 
      // Summon the build choice dialog. 
      if (units == 0) 
      { 
       return; 
      } 

      JECMessageTable messageBox(this->model, "Test"); 
      messageBox.exec(); 

      if (messageBox.result() == QDialog::Accepted) 
      { 
       //selectedUnit = this->model->getSelectedUnit(); 
      } 
      else 
      { 
       //selectedUnit = 0; 
      } 

      return; 
     } 
     case Action::MORPH: 
     { 
      return; 
     } 
     case Action::UPGRADE: 
     { 

     } 
     } 

     break; 
    } 
    case 4: 
    { 
     value = static_cast<QProgressBar*>(editor)->value(); 
     break; 
    } 
    } 

    model->setData(index, value); 
} 

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

QSize DelegateAction::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 
{ 
    if (index.column() == 4) 
    { 
     return QSize(option.rect.width(), option.rect.height()); 
    } 
    else 
    { 
     return QStyledItemDelegate::sizeHint(option, index); 
    } 
} 

void DelegateAction::paint(QPainter *painter, const QStyleOptionViewItem &item, const QModelIndex &index) const 
{ 
    if (index.column() == 4 && index.isValid() == true) 
    { 
     QStyleOptionProgressBarV2 progress; 

     progress.minimum = 0; 
     progress.maximum = 100; 
     progress.progress = index.data().toInt(); 
     progress.rect = QRect(item.rect.x(), item.rect.y(), item.rect.width(), item.rect.height()); 

     QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progress, painter); 
    } 
    else 
    { 
     // Painting the cells normally. 
     QStyledItemDelegate::paint(painter, item, index); 
    } 
} 

void DelegateAction::setUnits(QList<Unit*> *units) 
{ 
    this->units = units; 

    if (units != 0) 
    { 
     if (units->length() > 0) 
     { 
      model = new ModelListUnit(&units->at(0)->getUnitBase()->getOptionUnit()); 
     } 
    } 
} 

void DelegateAction::comboChanged(QString string) 
{ 

// comboUpdated = true; 
// switch (Action::getType(string)) 
// { 
// case Action::INVALID: 
// { 
//  return; 
// } 
// case Action::IDLE: 
// { 
//  return; 
// } 
// case Action::GATHER: 
// { 
//  return; 
// } 
// case Action::BUILD: 
// { 
//  return; 
// } 
// case Action::TRAIN: 
// { 
//  // Summon the build choice dialog. 
//  if (units == 0) 
//  { 
//   return; 
//  } 

//  JECMessageTable messageBox(model, "Test"); 
//  messageBox.exec(); 

//  if (messageBox.result() == QDialog::Accepted) 
//  { 
//   selectedUnit = model->getSelectedUnit(); 
//  } 
//  else 
//  { 
//   selectedUnit = 0; 
//  } 

//  return; 
// } 
// case Action::MORPH: 
// { 
//  return; 
// } 
// case Action::UPGRADE: 
// { 

// } 
// } 

} 

void DelegateAction::comboDestroyed() 
{ 
    disconnect(this, SLOT(comboChanged(QString))); 
    disconnect(this, SLOT(comboDestroyed())); 
} 

//bool DelegateAction::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) 
//{ 
// QStyledItemDelegate::editorEvent(event, model, option, index); 

// if (comboUpdated == true && index.isValid() == true) 
// { 
//  comboUpdated = false; 

//  if (selectedUnit != 0) 
//  { 
//   units->at(index.row()); 
//  } 
// } 
//} 

我想通了这一点。如果任何人都对类似的东西感兴趣,我可以分类为QTableView。

在QTableView中我使用QTableView :: setIndexWidget()来使用QComboBoxes和QProgressBars。基本上我的子类有两种类型的小部件的QList,它们与表中的特定行相对应。

+1

你能发表这个子类的代码吗? – thestar

  1. 获得ComboBoxEditor从QComboBox
  2. 保持Action对象中ComboBoxEditor(存储在模型索引数据)
  3. 当委托的comboChanged()被调用,您可以访问通过发送者(行动),这是ComboBoxEditor 。

请参考官方示例StarDelegate。

http://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html