Qt5 QFileDialog также закрывает родительский диалог

#c #linux #qt #dialog #qt5

Вопрос:

У меня есть пользовательский QDialog с кнопкой «Сохранить», которая должна запрашивать у пользователя QFileDialog и сохранять содержимое виджета таблицы в файл, но сохранять диалоговое окно открытым.

Это функция, которая открывает диалоговое окно и сохраняет данные:

 bool ResultsDialog::saveData()
{
    QString outfile = QFileDialog::getSaveFileName(this, tr("Save results"), tr(""), tr("CSV Files (*.csv)") );
    if (outfile.isNull() || outfile.isEmpty() )
        return false;
    if (!CSVIO::write_to_csv(*ui->tableWidget, outfile) )
    {
        QMessageBox::critical(this, "Failed to save...", QString("Could not save file: %1").arg(outfile) );
        return false;
    }
    return true;
}
 

Это код для слота кнопки Сохранить:

 void ResultsDialog::on_saveButton_clicked()
{
    if (saveData() )
    {
        saved = true;
    }
}
 

РЕДАКТИРОВАТЬ: Это код, который создает и открывает каталог результатов:

 void MainWindow::displayResults()
{
    ResultsDialog *resultsDialog = new ResultsDialog(this);
    resultsDialog->setWindowTitle(windowTitle() );
    resultsDialog->setWindowIcon(windowIcon() );

    connect(resultsDialog, amp;ResultsDialog::finished, this, amp;MainWindow::close);

    resultsDialog->fill(playlistTable, notes);
    resultsDialog->setModal(true);
    resultsDialog->open();
    this->hide();
}
 

Проблема в том, что, как только QFileDialog закрывается, мой QDialog закрывается вместе с ним, и на консоли выводится следующее сообщение:

в Qt.qpa по.xcb: QXcbConnection: XCB ошибки: 3 (BadWindow), последовательность: 13049, идентификатора ресурса: 25205189, майор код: 40 (TranslateCoords), незначительные код: 0
11:59:01: /главная/пользователь user1/рабочее пространство/строительство-приложение-рабочий стол-отладка/приложение завершился с кодом 0

Обратите внимание, что главное окно, которое является родительским для моего пользовательского диалога, скрыто. Когда он не скрыт, эта проблема исчезает, но это не вариант, так как я хочу, чтобы главное окно было скрыто.

Я использую Qt 5.15 в Debian Bullseye.

Комментарии:

1. Просто проверяю, хорошо ли я понимаю: значит, если ваше главное окно не скрыто, то ваш каталог результатов автоматически не закрывается после закрытия QFileDialog?

2. Это правильно. Я добавляю код, который открывает каталог результатов.

Ответ №1:

Вы подключаете завершение основного окна к сигналу, который отправляется, пока ResultsDialog все еще обрабатывается. ResultsDialog имеет главное окно в качестве родителя, поэтому родитель (и его потомки!!) уничтожаются, пока ребенок еще бежит. Из этой конструкции не выйдет ничего хорошего.

Редактировать: Сообщение об ошибке, которое вы видите, не является источником проблемы, а просто указывает на то, что окно было внезапно закрыто. И это именно то, что вы описываете.

Редактировать 2: Смотрите раздел комментариев для обходного пути (передача 0 в качестве родителя в диалоговом окне) и некоторых предположений о том, почему обходной путь работает.

Комментарии:

1. Это может быть проблемой, а может и не быть, но проблема не в этом. У меня не было никаких других проблем с этой конструкцией. Предполагается, что приложение завершит работу, когда журнал результатов будет закрыт. Есть что — то, что делает QFileDialog, что заставляет ResultsDialog закрываться раньше, чем это должно быть, и я не могу выяснить, что это такое-вот в чем проблема.

2. Я упустил тот момент, что было закрыто намеренно и что действительно закрылось волшебным образом. Здесь происходит что-то непонятное: можете ли вы открыть каталог результатов с помощью exex() вместо open (), чтобы сделать его подходящим модальным диалогом приложения (для этого вам, возможно, придется инвертировать вызов hide и exec)? Что произойдет, если вы нарушите родительскую иерархию и передадите 0 в конструкторе ResultsDialog и GetSaveFileName?

3. Я мог бы поклясться, что пытался передать 0 в качестве родителя для ResultsDialog, но, похоже, теперь это сработало. По крайней мере, в Linux — так как приложение также должно работать на Mac и Windows, я тоже протестирую на них. Передача 0 в GetSaveFileName не оказала никакого эффекта. Изменение между exec() и open() также не имеет значения.

4. Я предполагаю, что какой-то внутренний пытается получить доступ к размеру панели инструментов главного окна, который, вероятно, дает 0, когда скрыт, и что какой-то элемент пытается использовать этот 0 в делении. Цепочка доступа к скрытой панели прерывается, передавая 0.

5. Это приятно знать… Я заметил интересное поведение с этой ошибкой: я отключил отклонение() для ResultsDialog для отображения QMessageBox если пользователь попытается закрыть, не сохраняя данные, и при QFileDialog отменен, он запускает эту функцию и окно сообщения приложение сохраняет жив — хотя приложение все еще умирает, когда сообщение, окно закрывается, даже если Go Back кнопка была нажата. Я могу подтвердить, что этот обходной путь работает на macOS и Windows, поэтому я приму ваш ответ.