你如何将QDialog粘贴到自定义代理中?

时间:2016-10-26 13:57:00

标签: qt

当您创建自己的自定义委托时,可以实施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()的不同部分,但没有任何工作正常。

3 个答案:

答案 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();
}