从 QStyledItemDelegate 中的 ComboBox 调用对话框
所以我这里有的是 QAbstractTableModel
的委托代码。第二列(索引 = 1)始终是一个组合框。该组合框具有我的模拟中给定单元可以执行的操作列表。单击“构建”或“训练”等某些操作后,我希望弹出一个对话框,为用户提供一组选择。做出选择后,代表应该更新模型的数据并继续。
这是我遇到的障碍。如果我尝试从 setModelData()
、setEditorData()
调用对话框,这些函数是 const
,因此我无法分配 对话框的结果可以是任何内容。
我试图做的是从 createEditor()
创建的 QComboBox
连接信号 indexChanged(QString)
。这至少允许我分配结果并仅在做出适当的选择时调用对话框。然而,我不断遇到段错误,QTCreator
中的跟踪不会落在 C 代码上(33 次汇编调用)。我不确定为什么我会这样。
当我尝试这种方法时,一旦对话框出现,表格就不再有组合框。它恢复到之前的状态,一旦程序离开我为 QComboBox::indexChanged(QString) 制作的槽,seggy 就会发生。
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());
// }
// }
//}
So what I have here is my delegate code for a QAbstractTableModel
. The 2nd column (index = 1), is always a comboBox
. That comboBox
has a list of actions that a given Unit in my simulation can perform. Upon clicking certain actions like Build or Train, I want a Dialog to pop up giving the user a set of choices. After making there choice, the delegate is supposed to update the model's data and move on.
Here is the snag I've run into. If I try to call a dialog from setModelData()
, setEditorData()
, those functions are const
so I can't assign the results of the dialog to anything.
What I have tried to do is to connect the signal indexChanged(QString)
from the QComboBox
created in createEditor()
. This at least allowed me to assign the result and call the dialog only when the appropriate choice was made. However I keep getting a seggy fault and the trace in QTCreator
will not land on C code (33 calls of assembly). I'm unsure as to why I got that seggy.
When I tried that approach, the table no longer had the combobox
once the dialog appeared. It reverted to its previous state and as soon as the program left the slot I made for QComboBox::indexChanged(QString)
, the seggy happened.
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());
// }
// }
//}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我明白了这一点。如果有人对类似的东西感兴趣,我将
QTableView
子类化。在
QTableView
内部,我使用QTableView::setIndexWidget()
来使用QComboBox
es和QProgressBar
s。基本上,我的子类有一个包含两种类型小部件的 QList,它们对应于表中的特定行。I figured this out. If anyone is interested in something similar, I sub classed
QTableView
.Inside
QTableView
i usedQTableView::setIndexWidget()
to useQComboBox
es andQProgressBar
s. Basically my subclass had aQList
of both types of widgets and they corresponded to a particular row in the table.QComboBox
派生ComboBoxEditor
comboChanged()
时,您可以访问通过 sender() 执行操作,即ComboBoxEditor
。请参考官方示例
StarDelegate
。http://doc.qt.io/qt-5/ qtwidgets-itemviews-stardelegate-example.html
ComboBoxEditor
fromQComboBox
comboChanged()
is called, you can access the Action via sender(), that isComboBoxEditor
.Please refer to the official example,
StarDelegate
.http://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html