Crash when calling getOpenFileName from QItemDeleg

2019-09-16 08:39发布

Prerequisites:

I have a custom QItemDelegate which creates custom editor for treeview items. The editor consists of a QLineEdit and QToolButton. The button is used to open the file dialog for selecting the file and placing it's path into line edit. I use a call to QFileDialog::getOpenFileName to open the file dialog. The dialog is native Windows file dialog (this is important).

When the editor is created the first time, everything works ok no matter how often I press that button. But after the editor is closed and reopened again the first press on the button results in a crash. The reason of the crash is that my custom editor eventually gets deleted.

Here is some code:

void CCustomEditor::on_RunSetupBtn_clicked()
{
    auto qFilename = QFileDialog::getOpenFileName(this,
        "Select application to run",
        QString(),
        "Executable files (*.exe)");

    if (qFilename.isEmpty())
        return;

    SetCommandLine(QDir::toNativeSeparators(qFilename), m_qParameters);
}

2条回答
Juvenile、少年°
2楼-- · 2019-09-16 09:13

I have a similar problem with getOpenFileName and getSaveFileName. My solution is, after getOpenFileName, getSaveFileName or at the end of the function set the windows as active with activateWindow().

查看更多
做个烂人
3楼-- · 2019-09-16 09:17

I have made some digging and found out that calling WinAPI function GetOpenFileName results in the very same way: my editor gets deleted (although crash doesn't happen). It seems that Qt calls it also internally.

I have tracked down the reason of why my editor gets deleted and found out that when getOpenFileName is called, active window changes and focus changes with it. In the first case the focus is moved from TreeView item, but in the second case it is moved from the editor itself! This results in the deletion of editor because of 'focus out' event.

It is important to say that this situation doesn't happen if 'DontUseNativeDialog' flag is set when file dialog is created. Therefore this should be a bug in Qt's window management between native windows and Qt widgets.

As a workaround of this bug I suggest the following solution: before making a call to getOpenFileName set the focus to the button itself.

    m_pUI->RunSetupBtn->setFocus();

    auto qFilename = QFileDialog::getOpenFileName(this,
            "Select application to run",
            QString(),
            "Executable files (*.exe)");

The other workaround is to use 'DontUseNativeDialog' flag, but the resulting file dialog doesn't look native, in fact it is quite ugly. If someone has a better solution, feel free to share.

查看更多
登录 后发表回答