- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
QT 4: программирование GUI на С++ - Жасмин Бланшет
Шрифт:
Интервал:
Закладка:
Многодокументный интерфейс
Приложения, которые обеспечивают работу со многими документами в центральной области главного окна, называются приложениями с многодокументным интерфейсом или MDI—приложениями. В Qt MDI—приложения создаются с использованием в качестве центрального виджета класса QWorkspace и путем представления каждого документа в виде дочернего окна QWorkspace.
Обычно MDI—приложения содержат пункт главного меню Windows (окна) с командами по управлению окнами и их списком. Активное окно отмечается галочкой. Пользователь может сделать любое окно активным, щелкая по его названию в меню Windows.
В данном разделе для демонстрации способов создания приложения с интерфейсом MDI и способов реализации его меню Windows мы разработаем MDI—приложение Editor (редактор), показанное на рис. 6.16.
Рис. 6.16. MDI—приложение Editor.
Это приложение состоит из двух классов: MainWindow и Editor. Его программный код находится на компакт-диске, и поскольку большая часть его либо совпадает, либо очень похожа на программный код приложения Электронная таблица из части I, здесь мы представим только новый программный код.
Рис. 6.17. Меню MDI—приложения Editor.
Давайте начнем с класса MainWindow.
01 MainWindow::MainWindow()
02 {
03 workspace = new QWorkspace;
04 setCentralWidget(workspace);
05 connect(workspace, SIGNAL(windowActivated(QWidget *)),
06 this, SLOT(updateMenus()));
07 createActions();
08 createMenus();
09 createToolBars();
10 createStatusBar();
11 setWindowTitle(tr("MDI Editor"));
12 setWindowIcon(QPixmap(":/images/icon.png"));
13 }
В конструкторе MainWindow мы создаем виджет QWorkspace и делаем его центральным виджетом. Мы связываем сигнал windowActivated() класса QWorkspace со слотом, который мы будем использовать для обеспечения актуального состояния меню Window.
01 void MainWindow::newFile()
02 {
03 Editor *editor = createEditor();
04 editor->newFile();
05 editor->show();
06 }
Слот newFile() соответствует пункту меню File | New. Он зависит от закрытой функции createEditor(), создающей дочерний виджет Editor.
01 Editor *MainWindow::createEditor()
02 {
03 Editor *editor = new Editor;
04 connect(editor, SIGNAL(copyAvailable(bool)),
05 cutAction, SLOT(setEnabled(bool)));
06 connect(editor, SIGNAL(copyAvailable(bool)),
07 copyAction, SLOT(setEnabled(bool)));
08 workspace->addWindow(editor);
09 windowMenu->addAction(editor->windowMenuAction());
10 windowActionGroup->addAction(editor->windowMenuAction());
11 return editor;
12 }
Функция createEditor() создает виджет Editor и устанавливает два соединения «сигнал—слот». Эти соединения обеспечивают включение или выключение пунктов меню Edit | Cut и Edit | Copy в зависимости от наличия выделенной области текста.
Поскольку мы используем интерфейс MDI, может оказаться, что работа будет вестись одновременно с несколькими виджетами Editor. На это надо обратить внимание, поскольку мы заинтересованы в ответе на сигнал copyAvailable(bool), поступающий только от активного окна редактора Editor, но не от других окон. Но эти сигналы могут порождаться только активным окном, поэтому это практически не составляет проблему.
После настройки Editor мы добавляем QAction для представления окна в меню Window. Это действие обеспечивается классом Editor, который мы скоро рассмотрим. Мы также добавляем это действие в объект QActionGroup. QActionGroup гарантирует, что в любой момент времени оказывается отмеченной только одна строка меню Window.
01 void MainWindow::open()
02 {
03 Editor *editor = createEditor();
04 if (editor->open()) {
05 editor->show();
06 } else {
07 editor->close();
08 }
09 }
Функция open() соответствует пункту меню File | Open. Этот пункт меню создает Editor для нового документа и вызывает функцию open() для Editor. Имеет смысл выполнять файловые операции в классе Editor, а не в классе MainWindow, поскольку каждый Editor требует поддержки своего собственного состояния.
Если функция open() завершится неудачей, мы просто закроем редактор, поскольку пользователь уже будет уведомлен об ошибке. Мы не обязаны сами явно удалять объект Editor; это происходит автоматически при условии установки атрибута виджета Qt::WA_DeleteOnClose, что и делается в конструкторе Editor.
01 void MainWindow::save()
02 {
03 if (activeEditor()) {
04 activeEditor()->save();
05 }
06 }
Слот save() вызывает функцию Editor::save() для активного редактора, если таковой имеется. И снова программный код по выполнению реальной работы находится в классе Editor.
01 Editor *MainWindow::activeEditor()
02 {
03 return qobject_cast<Editor *>(workspace->activeWindow());
04 }
Закрытая функция activeEditor() возвращает активное дочернее окно в виде указателя типа Editor или нулевой указатель при отсутствии такого окна.
01 void MainWindow::cut()
02 {
03 if (activeEditor())
04 activeEditor()->cut();
05 }
Слот cut() вызывает функцию Editor::cut() для активного редактора. Мы не приводим слоты copy(), paste() и del(), потому что они имеют такой же вид.
01 void MainWindow::updateMenus()
02 {
03 bool hasEditor = (activeEditor() != 0);
04 bool hasSelection = activeEditor()
05 && activeEditor()->textCursor().hasSelection();
06 saveAction->setEnabled(hasEditor);
07 saveAsAction->setEnabled(hasEditor);
08 pasteAction->setEnabled(hasEditor);
09 cutAction->setEnabled(hasSelection);
10 copyAction->setEnabled(hasSelection);
11 closeAction->setEnabled(hasEditor);
12 closeAllAction->setEnabled(hasEditor);
13 tileAction->setEnabled(hasEditor);
14 cascadeAction->setEnabled(hasEditor);
15 nextAction->setEnabled(hasEditor);
16 previousAction->setEnabled(hasEditor);
17 separatorAction->setVisible (hasEditor);
18 if (activeEditor())
19 activeEditor()->windowMenuAction()->setChecked(true);
20 }
Слот updateMenus() вызывается всякий раз, когда окно становится активным (и когда закрывается последнее окно) для обновления системы меню благодаря помещенному нами в конструктор MainWindow соединению «сигнал—слот».
Большинство пунктов меню имеет смысл при существовании активного окна, поэтому мы их отключаем при отсутствии активного окна. В конце мы вызываем setChecked() для QAction, представляющего активное окно. Благодаря использованию QActionGroup нам не требуется явно сбрасывать флажок предьщущего активного окна.
01 void MainWindow::createMenus()
02 {
03 windowMenu = menuBar()->addMenu(tr("&Window"));
04 windowMenu->addAction(closeAction);
05 windowMenu->addAction(closeAllAction);
06 windowMenu->addSeparator();
07 windowMenu->addAction(tileAction);
08 windowMenu->addAction(cascadeAction);
09 windowMenu->addSeparator();
10 windowMenu->addAction(nextAction);
11 windowMenu->addAction(previousAction);
12 windowMenu->addAction(separatorAction);
13 }
Закрытая функция createMenus() заполняет меню Window командами. Здесь используются типичные для такого рода меню команды, и они легко реализуются с применением слотов closeActiveWindow(), closeAllWindows(), tile() и cascade() класса QWorkspace. Всякий раз, когда пользователь открывает новое окно, в меню Window добавляется список действий. (Это делается в функции createEditor(), которую мы видели.) При закрытии пользователем окна редактора соответствующий ему пункт в меню Window удаляется (поскольку его владельцем является это окно редактора), т.е. пункт меню удаляется из меню Window автоматически.
01 void MainWindow::closeEvent(QCloseEvent *event)
02 {
03 workspace->closeAllWindows();
04 if (activeEditor()) {
05 event->ignore();
06 } else {
07 event->accept();
08 }
09 }
Функция closeEvent() переопределяется для закрытия всех дочерних окон, обеспечивая получение всеми дочерними виджетами сигнала о возникновении события закрытия. Если один из дочерних виджетов «игнорирует» свое событие закрытия (прежде всего из-за того, что пользователь нажал кнопку отмены при выдаче соответствующего сообщения о «несохраненных изменениях»), мы игнорируем событие закрытия для MainWindow; в противном случае мы принимаем его, и в результате Qt закрывает окно. Если бы мы не переопределили функцию closeEvent() в MainWindow, у пользователя не было бы никакой возможности сохранения ни одного из несохраненных изменений.

