Глава 34 – Главное окно, создание SDI- и MDI-приложений
Главное окно, создание SDI- и MDI-приложений
Приобрести книгу можно на сайте ozon.ru и в электронном виде на Google Play:
20 Replies to “Глава 34 – Главное окно, создание SDI- и MDI-приложений”
Здравствуйте.
Листинг 34.9 “Определение класса SDIProgram”, стр 487.
В определение класса подключается само определение класса ( #include “SDIProgram.h”). В электронном архиве данной строчки нет, вероятно опечатка.
В примере MDI приложения, в слотах MDIProgram::slotSave() и MDIProgram::slotSaveAs() закралась ошибка:
DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow());
а должно быть:
DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow()->widget());
Спасибо, Виталий! Да это действительно ошибка в методах MDIProgram::slotSave() и MDIProgram::slotSaveAs() нужно вызвать метод QMdiSubWindow::widget(), чтобы получить расположенные в дочерних окнах QMdiSubWindow виджеты. Тоесть в исходном коде необходимо заменить строчки DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow()) на DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow()->widget());
Здравствуйте, Макс!
На стр. 483 в листинге 34.3 функция loadModules(QSplashScreen*) завершается строчкой qApp->processEvents(). Объясните, пожалуйста, для чего нужна эта строчка?
Здравствуйте, Вячеслав! Это сделанно для того что бы дать немного “воздуха” и дать возможность приложению обработать события. Ведь мы сделали искуственно задержку при помощи цикла, и как бы создали имитацию загрузки модулей или плагинов, которые занимают время для загрузки у больших программных продуктов. Если бы мы не встроили возможность для отработки событий то в Windows мы бы увидели крутящиеся песочные часы и быть может еще в добавок сообщение о том что приложение не реагирует, а на Mac вращающуюся спираль.
Здравствуйте, Макс!
Может кому будет интересно. Вот так можно поменять слот slotChangeWindowsTitle (см. листинг 34.9), чтобы в заголовке окна отображалось только имя файла (без пути):
Макс, здравствуйте!
В программе “MDI Program” стр. 488 – 496 есть небольшой баг. Если пытаться сохранять файл, если не создано ни одного MDI-окна (документа), то приложение аварийно завершается. Варианты решения этой проблемы – это при запуске приложения создавать один пустой документ, либо в конструкторе класса MDIProgram делать неактивным (pactSave->setDisabled(true)) соответствующий “экшн”, и делать его активным, когда создается документ. Но тогда эта проблема проявится, когда пользователь закроет все открытые документы и попробует нажать “сохранить”. Какую “защиту от дурака” можно сделать в данном случае?
Здравствуйте, Вячеслав!
Самое правильное, как вы и сказали, это сделать объект QAction “Save” неактивным, причем это состояние должно устанавливаться всякий раз, когда в приложениий не имеет окон для редатирования.
Уважаемый Макс, Вы уж извините, но эта глава очень много вопросов вызвала у меня… Для закрытия приложения можно использовать статический слот quit() (например: qApp->quit() ), а можно closeAllWindows() (Вы его используете в коде своего приложения MDI ). Что предпочтительнее и для каких случаев? Спасибо!
Здравствуйте, Вячеслав! Думаю что придпочтительнее будет qApp->quit(), так как у приложения совсем не обязательно могут быть окна, напроимер приложение SystemTray или консольное. А qApp->quit() сработает во всех случаях.
Здравствуйте! На странице 478 книги есть текст “растровое изображение — массив растровых данных, хранящихся в файле формата ХРМ”, но в примере, который идёт вместе с книгой, ресурсы, на самом деле, хранятся в формате PNG.
Большое спасибо Дмитрий, Вы нашли артефакт из прошлых изданий. XPM формат уже в этой книге нигде не должен использоваться, все используемые в примерах файлы находятся в ресурсе проекта в формате PNG либо JPG.
Добрый день!
Листинг 34.10, файл MDIProgram.h, в private секции объявлена конструкция вида:
“DocWindow* MDIProgram::createNewDoc(); ”
Долго пытался понять, к чему здесь доступ к самому себе, пришел к выводу, что это оЧеПятка.
Добрый день, Макс!
Не знаю, как на момент написания книги, но сейчас QSignalMapper считается устаревшим. Всячески пытался заменить его на лямбду, в slotWindows, но успеха так и не достиг. Переписал параметры функции
void MDIProgram::slotSetActiveSubWindow(QMdiSubWindow * pwgt), чтобы принимать аргументы непосредственно QMdiSubWindow *, и пытался коннектить их из соответствующего слота:
//
QList listDoc = m_pMdiArea->subWindowList();
for(QMdiSubWindow* sub:listDoc)
{
pact = m_pMenuWindows->addAction(sub->windowTitle());
pact->setCheckable(true);
pact->setChecked(m_pMdiArea->activeSubWindow()==sub);
connect(pact,&QAction::triggered,this,[&]()
{
slotSetActiveSubWindow(sub);
});
}
//
Без толку. Получаю ошибку сегментации, видимо дело в области видимости, пытался использовать std::move и std::ref, – ничего. Нсли есть адекватный способ замены маппера на лямбду – пожалуйста, отпишитесь.
This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.AcceptRead More
Privacy & Cookies Policy
Privacy Overview
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.
Здравствуйте.
Листинг 34.9 “Определение класса SDIProgram”, стр 487.
В определение класса подключается само определение класса ( #include “SDIProgram.h”). В электронном архиве данной строчки нет, вероятно опечатка.
Спасибо Артем! Да, это действительно опечатка #include”SDIProgramm.h” в этом листинге не должно быть.
В примере MDI приложения, в слотах MDIProgram::slotSave() и MDIProgram::slotSaveAs() закралась ошибка:
DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow());
а должно быть:
DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow()->widget());
Спасибо, Виталий! Да это действительно ошибка в методах MDIProgram::slotSave() и MDIProgram::slotSaveAs() нужно вызвать метод QMdiSubWindow::widget(), чтобы получить расположенные в дочерних окнах QMdiSubWindow виджеты. Тоесть в исходном коде необходимо заменить строчки DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow()) на DocWindow* pdoc = qobject_cast(m_pma->activeSubWindow()->widget());
На стр. 477 в приведенном коде строчка “pmnu->addAction(pactSave)”, а должна быть “pmnuFile->addAction(pactSave)”.
Это опечатка. Должно быть pmnuFile->addAction(pactSave). Спасибо!
На стр. 479 в разделе “Доки” приведен код: “QLabel* plbl = new QLabel(“Label in Dock”, pdoc)”, вместо “pdoc” должно быть “pdock”.
Это опечатка. Должно быть QLabel(“Label in Dock”, pdock). Спасибо!
Здравствуйте, Макс!
На стр. 483 в листинге 34.3 функция loadModules(QSplashScreen*) завершается строчкой qApp->processEvents(). Объясните, пожалуйста, для чего нужна эта строчка?
Здравствуйте, Вячеслав! Это сделанно для того что бы дать немного “воздуха” и дать возможность приложению обработать события. Ведь мы сделали искуственно задержку при помощи цикла, и как бы создали имитацию загрузки модулей или плагинов, которые занимают время для загрузки у больших программных продуктов. Если бы мы не встроили возможность для отработки событий то в Windows мы бы увидели крутящиеся песочные часы и быть может еще в добавок сообщение о том что приложение не реагирует, а на Mac вращающуюся спираль.
Здравствуйте, Макс!
Может кому будет интересно. Вот так можно поменять слот slotChangeWindowsTitle (см. листинг 34.9), чтобы в заголовке окна отображалось только имя файла (без пути):
void slotChangeWindowTitle(const QString& str) {
QRegExp rxp(“\\w+\\.?\\w+$”);
QString strTmp = str.mid(str.indexOf(rxp),str.length()-str.indexOf(rxp));
setWindowTitle(strTmp);
}
Макс, здравствуйте!
В программе “MDI Program” стр. 488 – 496 есть небольшой баг. Если пытаться сохранять файл, если не создано ни одного MDI-окна (документа), то приложение аварийно завершается. Варианты решения этой проблемы – это при запуске приложения создавать один пустой документ, либо в конструкторе класса MDIProgram делать неактивным (pactSave->setDisabled(true)) соответствующий “экшн”, и делать его активным, когда создается документ. Но тогда эта проблема проявится, когда пользователь закроет все открытые документы и попробует нажать “сохранить”. Какую “защиту от дурака” можно сделать в данном случае?
Здравствуйте, Вячеслав!
Самое правильное, как вы и сказали, это сделать объект QAction “Save” неактивным, причем это состояние должно устанавливаться всякий раз, когда в приложениий не имеет окон для редатирования.
Уважаемый Макс, Вы уж извините, но эта глава очень много вопросов вызвала у меня… Для закрытия приложения можно использовать статический слот quit() (например: qApp->quit() ), а можно closeAllWindows() (Вы его используете в коде своего приложения MDI ). Что предпочтительнее и для каких случаев? Спасибо!
Здравствуйте, Вячеслав! Думаю что придпочтительнее будет qApp->quit(), так как у приложения совсем не обязательно могут быть окна, напроимер приложение SystemTray или консольное. А qApp->quit() сработает во всех случаях.
Всё понятно, спасибо!
Здравствуйте! На странице 478 книги есть текст “растровое изображение — массив растровых данных, хранящихся в файле формата ХРМ”, но в примере, который идёт вместе с книгой, ресурсы, на самом деле, хранятся в формате PNG.
Большое спасибо Дмитрий, Вы нашли артефакт из прошлых изданий. XPM формат уже в этой книге нигде не должен использоваться, все используемые в примерах файлы находятся в ресурсе проекта в формате PNG либо JPG.
Добрый день!
Листинг 34.10, файл MDIProgram.h, в private секции объявлена конструкция вида:
“DocWindow* MDIProgram::createNewDoc(); ”
Долго пытался понять, к чему здесь доступ к самому себе, пришел к выводу, что это оЧеПятка.
Добрый день, Макс!
Не знаю, как на момент написания книги, но сейчас QSignalMapper считается устаревшим. Всячески пытался заменить его на лямбду, в slotWindows, но успеха так и не достиг. Переписал параметры функции
void MDIProgram::slotSetActiveSubWindow(QMdiSubWindow * pwgt), чтобы принимать аргументы непосредственно QMdiSubWindow *, и пытался коннектить их из соответствующего слота:
//
QList listDoc = m_pMdiArea->subWindowList();
for(QMdiSubWindow* sub:listDoc)
{
pact = m_pMenuWindows->addAction(sub->windowTitle());
pact->setCheckable(true);
pact->setChecked(m_pMdiArea->activeSubWindow()==sub);
connect(pact,&QAction::triggered,this,[&]()
{
slotSetActiveSubWindow(sub);
});
}
//
Без толку. Получаю ошибку сегментации, видимо дело в области видимости, пытался использовать std::move и std::ref, – ничего. Нсли есть адекватный способ замены маппера на лямбду – пожалуйста, отпишитесь.