Компания ALT Linux
Опубликован: 07.03.2015 | Доступ: свободный | Студентов: 2134 / 486 | Длительность: 24:14:00

Лекция 15: Разработка приложений с графическим интерфейсом

15.3 Программирование формы созданной в Qt Designer

Рассмотрим, как файлы форм интегрируются в проект. Как мы уже отмечали ранее, для того чтобы добавить файл формы в проект существует специальная переменная FORMS. Если мы откроем .рro-файл, то увидим:

FORMS += mainwindow.ui

Файлы форм, добавленные в проект, считываются и превращаются в эквивалентный С++ код с помощью специальной программы uic (это происходит во время предварительной обработки проекта с помощью qmake). Код, сгенерированный uic, создает виджеты и компоновки, содержит настройки свойств, сигнально-слотовые соединения и стили, необходимые для получения визуального отображения содержимого .ui-файла. Если мы откроем папку с проектом (или папку для shadow build), то увидим среди исходных текстов и сгенерированных файлов файл ui_mainwindow.h, содержащий сгенерированный для формы код. Конечно, этот файл должен быть добавлен где-то в коде программы с помощью директивы #include для того, чтобы можно было воспользоваться сгенерированным кодом. Но нет необходимости делать это самостоятельно — гораздо легче воспользоваться мастером создания файлов и проектов.

При создании проекта для нашего примера мы установили флажок "Generate form" для того, чтобы автоматически сгенерировать форму для главного окна и добавить необходимый код для доступа к элементам на форме в программе. Среди кода, мастер автоматически добавил к объявлению и реализации класса MainWindow:

  • предварительное объявление класса формы: /
    /Предварительное объявление класса формы созданной из .ui-файла
    namespace Ui {
    	class MainWindow;
    }
  • указатель на объект формы, позволяющий получить доступ к элементам на форме:
    class MainWindow : public QMainWindow
    {
    .....
    private :
    	//Указатель на объект формы созданной из .ui-файла
    	Ui::MainWindow * ui;
    };
  • Конструктор главного окна создает объект класса формы и инициализирует переменную ui, а также вызывает метод ui->setupUi(this), который создает все элементы которые есть на форме и устанавливает текущий виджет как родительский для них; /
    /Файл сгенерированный uic при обработке файла формы
    #include " ui_mainwindow.h "
    MainWindow::MainWindow ( QWidget  * parent ) :
    	QMainWindow ( parent ),
    	ui(new Ui::MainWindow ) //Создаем объект формы, созданной в QtDesigner
    {
    ui->setupui( this ); //Применяем дизайн, который мы создали в QtDesigner
    	//к текущему окну
    .....
  • Деструктор: удаляет объект на который ссылается указатель ui
    MainWindow::˜ MainWindow ( )
    {
    	//Удалить форму из памяти
    	delete ui;
    }

Таким образом, через указатель ui мы можем получить доступ к созданной форме и элементам на ней. Например, мы можем получить доступ к действиям добавленным к главному меню нашего редактора и задать горячие клавиши для них:

//Задаём комбинации клавиш для действий
ui->action_Undo->set Shortcut ( QKeySequence::Undo );
ui->action_Redo->set Shortcut ( QKeySequence::Redo );
ui->action_Cut->set Shortcut ( QKeySequence::Cut );
ui->action_Copy->set Shortcut ( QKeySequence::Copy );
ui->action_Past e->set Shortcut ( QKeySequence::Paste );
ui->action_Select_all ->set Shortcut ( QKeySequence::selectAll );
ui->action_New->set Shortcut ( QKeySequence::New);
ui->action_Open->set Shortcut ( QKeySequence::Open );
ui->action_Save->set Shortcut ( QKeySequence::Save );
ui->action_Exit->set Shortcut ( QKeySequence::Quit );

Обратите внимание на то, как мы используем класс Qt QKeySequence для того, чтобы задать горячие клавиши для действий. Помимо возможности задать комбинацию клавиш текстовой строкой (например QKeySequence (Ctrl + X)) или с помощью специально определенных констант для клавиш (например QKeySequence (Qt :: CTRL + Qt :: Key_X)), можно воспользоваться набором стандартных клавиатурных сокращений, которые будут соответствовать стандартам системы. Так для повторения отмененного действия в ОС Linux пользователь сможет воспользоваться комбинацией клавиш Ctrl+Shift+Z, а в ОС Windows привычной комбинацией Ctrl+Y.

Нашему текстовому редактору еще не хватает функциональности: нам необходимо запрограммировать создание, открытие и сохранение текстового файла, а также пункты меню Help.

Для начала добавим объявления слота для создания нового файла и добавим поле для сохранения пути текущего открытого файла:

private slots :
	void slotNew ( );
	
private :
	QString mFileName;

Мы используем частный метод updateTitle() для того, чтобы обновить заголовок окна и вывести название программы и путь к текущему открытому файлу:

private :
	void updateTitle ( );

Реализация метода обновления заголовка:

//Метод обновления заголовка окна
void MainWindow::updateTitle ( )
{
//Подставляем в название заголовка имя текущего открытого файла.
//Комбинацией символов " [ * ] " обозначаем место, где будет выводиться знак "*" в случае,
//когда содержимое окна модифицировано.
QString lTitle=QString ( " TextEditor - % 1 [ * ] " ).arg ( mFileName.FileName ( ) );
//устанавливаем заголовок окна
setWindowTitle ( lTitle );
}

Метод setWindowTitle() позволяет не только задать текст заголовка для окна, но и отметить несохраненные изменения в текущем открытом документе. Для этого, после заголовка мы добавили шаблон [*]. Теперь, если сообщить главному окну о редактировании содержимого посредством вызова слота QWidget::setWindowModified(bool) со значением true, то после текста заголовка появится символ "*", означающий, что содержание главного окна изменено и его следует сохранить. Слот setWindowModified(bool) мы соединили с сигналом modificationChanged(bool) текстового поля QPlanTextEdit с помощью редактора сигнально-слотовых соединений в редакторе форм (см. предыдущий пункт).

Добавим реализацию слота MainWindow::slotNew():

//Слот для создания нового документа
void MainWindow::slotNew ( )
{
	mFileName = " Untitled File "; //Задать имя для нового файла по умолчанию
	ui->plainTextEdit ->clear ( ); //Очистить текстовое поле
	setWindowModified ( false ); //Установить — содержание не модифицировано
	updateTitle ( ); //Обновить заголовок окна
}

Теперь присоединим объект QAction для создания нового документа к слоту:

connect(ui->action_New, SIGNAL(triggered()),this, SLOT(slotNew()), Qt::UniqueConnection);

Сигнал выпускается при выполнении действия (вызова пункта меню, нажатие кнопки на панели инструментов, для которой была добавлено действие и т.д.). В конце конструктора вызовем слот slotNew():

MainWindow::MainWindow ( QWidget * parent ) :
	QMainWindow ( parent ),
ui(new Ui::MainWindow )
//Создаем объект, который содержит дизайн созданный в редакторе форм
{
..... .
//В конце вызываем слот для нового документа. Таким образом, пользователь сможет сразу
//же приступить к работе
	slotNew ( );
}

Остальные пункты меню мы запрограммируем в следующем параграфе, в котором мы рассмотрим работу со стандартными системными диалогами в Qt.

Сергей Радыгин
Сергей Радыгин

Символы кириллицы выводит некорректно. Как сделать чтобы выводился читабельный текст на русском языке?

Тип приложения - не Qt,

Qt Creator 4.5.0 основан на Qt 5.10.0. Win7.

 

Юрий Герко
Юрий Герко

Кому удалось собрать пример из раздела 13.2 Компоновка (Layouts)? Если создавать проект по изложенному алгоритму, автоматически не создается  файл mainwindow.cpp. Если создавать этот файл вручную и добавлять в проект, сборка не получается - компилятор сообщает об отсутствии класса MainWindow. Как правильно выполнить пример?