Russian Qt Forum
Ноябрь 24, 2024, 01:02 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Qt: Вылетает программа при закрытии главного окна  (Прочитано 10408 раз)
FluffyMan2000
Гость
« : Декабрь 09, 2012, 16:45 »

Доброго времени суток.

Делаю лабораторную работу на тему "многодокументный интерфейс". писать за меня не прошу. просто подскажите в чем ошибка.

Имеется QMainWindow с QMdiArea в качестве centralWodget. В QMdiArea создаются окна (объекты, наследники QTextEdit со своими слотами "сохранить", "сохранить как"). Реализовал вызов диалогового окна при закрытии документа и при закрытии главного окна что-то вроде "документ не сохранен. сохранить?".

Проблема в следующем:
1)если создаю несколько окон, и закрываю один за одним, то вылетает программа при закрытии последнего дочернего окна. То есть если создам одно окно и его закрою - вылетает с ошибкой в консоль "программа неожиданно завершилась"
2) если закрываю главное окно и в нем имеются дочерние - тоже вылетает с ошибкой той же самой.

Проект во вложении. Кому не лень, посмотрите пожалуйста. у меня уже мозг взрывается.
Записан
V1KT0P
Гость
« Ответ #1 : Декабрь 09, 2012, 17:31 »

Как минимум у тебя в функции:
Код
C++ (Qt)
void MainWindow::checkForActionsAvailable()
нету проверки:
Код
C++ (Qt)
ui->mdiArea->isActiveWindow()
Также при каждом касте qobject_cast надо проверять не возвращает ли он ноль.
Как по мне так у тебя проблемы с архитектурой из-за плохого понимания Qt.
Записан
FluffyMan2000
Гость
« Ответ #2 : Декабрь 09, 2012, 17:36 »

Также при каждом касте qobject_cast надо проверять не возвращает ли он ноль.
Как по мне так у тебя проблемы с архитектурой из-за плохого понимания Qt.

в чем непонимание? это (использование кастов) вообще в примерах Макса Шлее написано.
Записан
V1KT0P
Гость
« Ответ #3 : Декабрь 09, 2012, 17:40 »

в чем непонимание? это (использование кастов) вообще в примерах Макса Шлее написано.
qobject_cast это тебе не static_cast и может спокойно вернуть ноль и вот тут начнется веселье. Особенно если программа большая, а ошибка достаточно редкая.
Записан
FluffyMan2000
Гость
« Ответ #4 : Декабрь 09, 2012, 17:46 »

понял.

устроил проверку на ноль при сохранении в слотах delegateForSave и delegateForSaveAs - возвращает не ноль. но ошибка та же.

еще заметил, что если создать два документа и нажать в тулбаре сохранить, то диалог сохранения вылезет два раза.
Записан
Mikhail
Программист
*****
Offline Offline

Сообщений: 587


Просмотр профиля
« Ответ #5 : Декабрь 09, 2012, 18:02 »

Ты используешь QMdiArea и не прочитав описания класса подсовываешь ему не наследников QMdiSubWindow, а какую то "дрянь" наследников QTextEdit.

Из документации:
Subwindows in QMdiArea are instances of QMdiSubWindow. They are added to an MDI area with addSubWindow(). It is common to pass a QWidget, which is set as the internal widget, to this function, but it is also possible to pass a QMdiSubWindow directly.The class inherits QWidget, and you can use the same API as with a normal top-level window when programming. QMdiSubWindow also has behavior that is specific to MDI windows. See the QMdiSubWindow class description for more details.
Записан
V1KT0P
Гость
« Ответ #6 : Декабрь 09, 2012, 18:10 »

понял.
устроил проверку на ноль при сохранении в слотах delegateForSave и delegateForSaveAs - возвращает не ноль. но ошибка та же.
еще заметил, что если создать два документа и нажать в тулбаре сохранить, то диалог сохранения вылезет два раза.
Я же тебе уже указал на эту ошибку. Вот исправь для начала функцию "void MainWindow::checkForActionsAvailable()" на вот это, а затем уже выясняй что ты делаешь не так:
Код
C++ (Qt)
void MainWindow::checkForActionsAvailable()
{
   if( !ui->mdiArea->isActiveWindow() )
   {
       qDebug() << "Error: isActiveWindow() is false";
       return;
   }
   DocWindow *widget = qobject_cast<DocWindow*>( ui->mdiArea->activeSubWindow()->widget() );
   if( !widget )
   {
       qDebug() << "Error: activeSubWindow() is not DocWindow";
       return;
   }
   ui->actionUndo->setEnabled( widget->document()->isUndoAvailable() );
   ui->actionRedo->setEnabled( widget->document()->isRedoAvailable() );
   ui->actionPaste->setEnabled( widget->canPaste() );
}
Записан
FluffyMan2000
Гость
« Ответ #7 : Декабрь 09, 2012, 18:50 »

понял.
устроил проверку на ноль при сохранении в слотах delegateForSave и delegateForSaveAs - возвращает не ноль. но ошибка та же.
еще заметил, что если создать два документа и нажать в тулбаре сохранить, то диалог сохранения вылезет два раза.
Я же тебе уже указал на эту ошибку. Вот исправь для начала функцию "void MainWindow::checkForActionsAvailable()" на вот это, а затем уже выясняй что ты делаешь не так:
Код
C++ (Qt)
void MainWindow::checkForActionsAvailable()
{
   if( !ui->mdiArea->isActiveWindow() )
   {
       qDebug() << "Error: isActiveWindow() is false";
       return;
   }
   DocWindow *widget = qobject_cast<DocWindow*>( ui->mdiArea->activeSubWindow()->widget() );
   if( !widget )
   {
       qDebug() << "Error: activeSubWindow() is not DocWindow";
       return;
   }
   ui->actionUndo->setEnabled( widget->document()->isUndoAvailable() );
   ui->actionRedo->setEnabled( widget->document()->isRedoAvailable() );
   ui->actionPaste->setEnabled( widget->canPaste() );
}

Объясните, зачем проверять mdiArea на isActiveWindow()? и еще, программа крашится и без вызова MainWindow::checkForActionsAvailable(). так что скорее всего не в ней дело.
Записан
V1KT0P
Гость
« Ответ #8 : Декабрь 09, 2012, 18:58 »

Объясните, зачем проверять mdiArea на isActiveWindow()? и еще, программа крашится и без вызова MainWindow::checkForActionsAvailable(). так что скорее всего не в ней дело.
По крайней мере у меня под Kubuntu в процессе работы твоей программы ui->mdiArea->activeSubWindow() возвращает ноль. И вот из-за этого программа падает.
Записан
FluffyMan2000
Гость
« Ответ #9 : Декабрь 09, 2012, 18:58 »

Ты используешь QMdiArea и не прочитав описания класса подсовываешь ему не наследников QMdiSubWindow, а какую то "дрянь" наследников QTextEdit.

Из документации:
Subwindows in QMdiArea are instances of QMdiSubWindow. They are added to an MDI area with addSubWindow(). It is common to pass a QWidget, which is set as the internal widget, to this function, but it is also possible to pass a QMdiSubWindow directly.The class inherits QWidget, and you can use the same API as with a normal top-level window when programming. QMdiSubWindow also has behavior that is specific to MDI windows. See the QMdiSubWindow class description for more details.

в примерах от Макса Шлее именно так и делается
Записан
FluffyMan2000
Гость
« Ответ #10 : Декабрь 09, 2012, 19:00 »

Объясните, зачем проверять mdiArea на isActiveWindow()? и еще, программа крашится и без вызова MainWindow::checkForActionsAvailable(). так что скорее всего не в ней дело.
По крайней мере у меня под Kubuntu в процессе работы твоей программы ui->mdiArea->activeSubWindow() возвращает ноль. И вот из-за этого программа падает.

а с твоим кодом слота MainWindow::checkForActionsAvailable() не крашится при закрытии программы? и еще нюанс, у тебя Qt установлена еще нокиевская или диджитевская? потому что у меня уже был казус - программа собранная на нокиевской кьют некоректно работала на диждитевской кьют
Записан
V1KT0P
Гость
« Ответ #11 : Декабрь 09, 2012, 19:18 »

а с твоим кодом слота MainWindow::checkForActionsAvailable() не крашится при закрытии программы? и еще нюанс, у тебя Qt установлена еще нокиевская или диджитевская? потому что у меня уже был казус - программа собранная на нокиевской кьют некоректно работала на диждитевской кьют
Да, не крашится. Сборка у меня из репозитория убунты 4.8.3.
Запусти под отладчиком и посмотри бэктрейс при падении, что может быть проще?
Записан
FluffyMan2000
Гость
« Ответ #12 : Декабрь 09, 2012, 20:29 »

а с твоим кодом слота MainWindow::checkForActionsAvailable() не крашится при закрытии программы? и еще нюанс, у тебя Qt установлена еще нокиевская или диджитевская? потому что у меня уже был казус - программа собранная на нокиевской кьют некоректно работала на диждитевской кьют
Да, не крашится. Сборка у меня из репозитория убунты 4.8.3.
Запусти под отладчиком и посмотри бэктрейс при падении, что может быть проще?

давайте по-порядку: ты содаешь два документа, жмешь крестик в главном окне, вылазит дилаог. жмешь да. вылазят два диалога. жмешь дискард и у тебя программа не крашится? у меня крашится.

Qt 4.7.4 (32-х битная)
Записан
FluffyMan2000
Гость
« Ответ #13 : Декабрь 09, 2012, 20:36 »

при запуске в режиме отладке в консоль вывалилось "Error: isActiveWindow() is false" и крашится все равно. спасибо за направление. буду дальше думать
Записан
FluffyMan2000
Гость
« Ответ #14 : Декабрь 09, 2012, 21:06 »

Решил таким образом:

Код:
void MainWindow::checkForActionsAvailable()
{
    if (ui->mdiArea->subWindowList().count() != 0)
    {
        DocWindow *pDoc = qobject_cast<DocWindow*>(ui->mdiArea->activeSubWindow()->widget());

        if (pDoc != 0)
        {
            ui->actionUndo->setEnabled(pDoc->document()->isUndoAvailable());
            ui->actionRedo->setEnabled(pDoc->document()->isRedoAvailable());
            ui->actionPaste->setEnabled(pDoc->canPaste());
        }
    }
}

проблема была в том, что я приводил к DocWindow несуществующий объект, так как он закрывался почему-то (до сих пор не понял почему он уничтожался раньше времени)
« Последнее редактирование: Декабрь 09, 2012, 21:36 от FluffyMan2000 » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.408 секунд. Запросов: 23.