当您创建自己的自定义委托时,可以实施createEditor()
,setEditorData()
和setModelData()
。我面临以下问题。我见过的createEditor()
的所有示例都使用了QComboBox或QLineEdit等简单的东西,它们没有show()
或exec()
成员函数,每当我尝试使用QDialog时,该程序有未定义的行为(我认为)和QDialog显示但行为疯狂。我确实让我的程序工作,使用了一些信号/插槽魔法,但我想使用所描述的标准模式来实现它,例如,在这里:http://cep.xray.aps.anl.gov/software/qt4-x11-4.2.2/model-view-delegate.html我该怎么做?
要详细说明当我面对未定义的行为时会发生什么,如果我在createEditor()中设置QDialog的父级,那么QDialog根本不会显示,如果我没有设置它,它显示出来,然后当我拖动它时它消失了(这是错误的,我认为我必须总是设置父,因为否则我会有内存泄漏)。我想,现在我的问题归结为:我怎样才能使QDialog正确显示?我尝试将show()和exec()粘贴到setEditorData(),setModelData()和createEditor()的不同部分,但没有任何工作正常。
答案 0 :(得分:5)
编辑器委托必须是嵌入在视图中的窗口小部件。当然,如果它愿意,可以自由地创建一个顶级窗口,但它必须控制该窗口的可见性并适当地聚焦。也就是说,如果编辑器窗口小部件的可见性发生变化,那么对话框的可见性也会发生变化,如果编辑器窗口小部件获得焦点,则必须将焦点转移到对话框以获得良好的用户体验。
解决方案是让一个空的QWidget
有一个孩子QDialog
,这是一个顶级窗口:
QWidget * MyDelegate::createEditor(QWidget * parent,
const QStyleOptionViewItem &, const QModelIndex & index) const
{
auto editor = new QWidget{parent};
auto dialog = new QDialog{editor, Qt::Window};
...
return editor;
}
您的QDialog
- 编辑器不起作用的原因是它的几何和状态由视图管理。视图就像编辑器/代理的布局。您需要插入一个插入的小部件来保护对话框免受此类操作。不可否认,如果设置了Qt::Window
标志,那么视图可以检查编辑器的标志并避免调整几何等等,但是我不会因为没有实现它而责怪任何人。当然,您可以自由地向Qt提交更改!
答案 1 :(得分:1)
委托的方法适用于内嵌编辑器,小部件可以在视图中显示。
如果您想要一个extern编辑器,您可能只想对视图的信号作出反应,例如clicked()
并从该位置打开对话框。
答案 2 :(得分:0)
K。Ober的proposal above实现QStyledItemDelegate :: createEditor()来使用一个空的QWidget实例作为编辑器,并给它作为子对话框,这是一个可行的解决方案。
但是,根据Qt技术支持,QStyledItemDelegate不仅支持将QWidget嵌入表格单元中进行内联编辑,而且还通过QDialog作为编辑器在表格外部的单独窗口中进行编辑。 这意味着您可以直接将QDialog派生类作为createEditor()中的编辑器返回,如以下工作示例所示。
#include <QtWidgets>
class MyDelegate : public QStyledItemDelegate {
using QStyledItemDelegate::QStyledItemDelegate;
public:
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem&, const QModelIndex&) const {
auto *fd = new QFileDialog(parent);
fd->open();
return fd;
}
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
auto fd = qobject_cast<QFileDialog *>(editor);
if (!fd || fd->result() == QDialog::Rejected)
return;
model->setData(index, fd->selectedFiles().first(), Qt::DisplayRole);
}
};
int main(int argc, char **argv) {
QApplication a(argc, argv);
QStandardItemModel sim(5, 5);
for (int i = 0; i < 5; ++i)
for (int j = 0; j < 5; ++j)
sim.setItem(i, j, new QStandardItem("Item"));
QTableView tv;
tv.setModel(&sim);
tv.setItemDelegate(new MyDelegate(&tv));
tv.show();
return a.exec();
}