如何在 QGraphicsView 的中心显示 QDialog?

How to show a QDialog in center of a QGraphicsView?

我有一个 QGraphicsView 子类,我想在项目的上下文菜单上显示一个属性对话框。

我希望对话框在视图中居中...

我现在有,没有parent,显示在屏幕中央。

MyView::MyView(QWidget *parent) : QGraphicsView(parent) {}

void MyView::showProperties()
{
    TabDialog *tabDialog = new TabDialog();  // shows in center of screen
//    TabDialog *tabDialog = new TabDialog(this); // doesn't show at all
//    TabDialog *tabDialog = new TabDialog((QWidget*)this->parent()); // doesn't show at all
    tabDialog->setWindowFlags(Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
    tabDialog->exec();
    delete tabDialog;
}

视图放置在组框中...所以 parent 是组框...

如何使用 parent 调用对话框?

您必须将对话框设置为顶级 window,而不仅仅是将嵌入到您的视图中的子窗口小部件。您的 setWindowsFlags 调用会重置对话框中的相关标志。您需要手动保存它们。

您也不应该使用 exec() 重新进入事件循环,因为这需要您的许多其他代码也需要可重入。

一个最小的修复看起来像:

void MyView::showProperties()
{
  auto dialog = new TabDialog(this);
  dialog->setWindowFlags(Qt::Dialog | 
                         Qt::WindowCloseButtonHint | 
                         Qt::WindowSystemMenuHint);
  dialog->setAttribute(Qt::WA_DeleteOnClose);
  dialog->show();
}

也许您想缓存对话框:

class MyView : public ... {
  QPointer<TabDialog> m_tabDialog; // nulls itself when the dialog perishes
  QTimer m_tabDialogTimer;
  ...
};

MyView::MyView(...) {
  m_tabDialogTimer->setSingleShot(true);
  ...
}    

void MyView::showProperties() {
  if (! m_tabDialog) {
    m_tabDialog = new TabDialog(this);
    m_tabDialog->setWindowFlags(Qt::Dialog | 
                                Qt::WindowCloseButtonHint | 
                                Qt::WindowSystemMenuHint);
    QObject::connect(&m_tabDialogTimer, &QTimer::timeout, 
                     m_tabDialog, &QObject::deleteLater);
    QObject::connect(m_tabDialog, &QDialog::finished, [&this](int){
      // the dialog gets deleted 120 seconds after last use
      m_tabDialogTimer.start(120);
    });
  }
  m_tabDialogTimer.stop(); // reset pending timeout, if any
  m_tabDialog->show();
}