Сбой при вызове getOpenFileName из пользовательского редактора QItemDelegate

Предпосылки:

У меня есть собственный QItemDelegate, который создает собственный редактор для элементов дерева. Редактор состоит из QLineEdit и QToolButton. Кнопка используется для открытия файлового диалога для выбора файла и помещения его пути в строку редактирования. Я использую вызов QFileDialog::getOpenFileName, чтобы открыть диалоговое окно файла. Диалог является родным файловым диалогом Windows (это важно).

Когда редактор создается в первый раз, все работает нормально, независимо от того, как часто я нажимаю эту кнопку. Но после того, как редактор закрылся и снова открылся, первое нажатие на кнопку приводит к сбою. Причина сбоя в том, что мой пользовательский редактор в конечном итоге удаляется.

Вот код:

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);
}

person Artyom Chirkov    schedule 19.07.2016    source источник


Ответы (2)


Я немного покопался и выяснил, что вызов WinAPI-функции GetOpenFileName приводит к тому же результату: мой редактор удаляется (хотя сбоя не происходит). Кажется, что Qt также вызывает это внутри.

Я выяснил причину удаления моего редактора и обнаружил, что при вызове getOpenFileName активное окно изменяется, а вместе с ним и фокус. В первом случае фокус перемещается из элемента TreeView, а во втором — из самого редактора! Это приводит к удалению редактора из-за события "фокус вне".

Важно отметить, что такой ситуации не происходит, если при создании файлового диалога установлен флаг DontUseNativeDialog. Следовательно, это должно быть ошибкой в ​​управлении окнами Qt между собственными окнами и виджетами Qt.

В качестве обхода этой ошибки я предлагаю следующее решение: перед вызовом getOpenFileName установите фокус на саму кнопку.

    m_pUI->RunSetupBtn->setFocus();

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

Другим обходным решением является использование флага «DontUseNativeDialog», но результирующий диалог файла не выглядит родным, на самом деле он довольно уродлив. Если у кого-то есть лучшее решение, не стесняйтесь поделиться.

person Artyom Chirkov    schedule 19.07.2016

У меня аналогичная проблема с getOpenFileName и getSaveFileName. Мое решение: после getOpenFileName, getSaveFileName или в конце функции установите окна как активные с помощьюactivWindow().

person user9039915    schedule 01.12.2017