Файл: Лабораторная работа 3 20 Тема Ипользование вспомогательных функций и вывод нескольких чисел c помощью одного элемента управления 20.docx
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 18.03.2024
Просмотров: 53
Скачиваний: 0
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
Тема: «Работа со строками»
П ример 1: программа, которая переводит число из 16-ой системы в 10-ую. При вводе выполняется проверка вводимых символов.
Спроектируйте окно как показано на рисунке.
Добавьте слот для кнопки «Перевести» и напишите код, показанный ниже.
#include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); // делаем размеры окна минимально-необходимыми QRegExp regExp("[A-Fa-f0-9]{,10}"); // задаем набор допустимых символов и их максимальное количество QRegExpValidator* valid = new QRegExpValidator(regExp, this); // создаем указатель на объект валидатор для проверки вводимых символов ui->lineEdit->setValidator(valid); // устанавливаем для первого окна валидатор } Dialog::
Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { int dec = 0; // десятичное значение QString str = ui->lineEdit->text(); // прочитали 16-ое число str = str.toUpper(); // сделали все буквы прописными for (int i=0; iПример 2: программа, которая считывает строку символов, состоящую из русских букв, запятых и пробелов и выводит на экран множество символов этой строки.
Спроектируйте окно как показано на рисунке.
#include"dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); QRegExp reg(trUtf8("[а-яА-Я, ]+")); // регулярное выражение, описывающее набор допустимых символов QRegExpValidator* valid = new QRegExpValidator(reg, this); // объявляем указатель на объект валидатор, использующий регулярное выражение ui->lineEdit->setValidator(valid); /* устанавливаем валидатор для элемента lineEdit, предназначенного для ввода исходных данных */ connect(ui->lineEdit, SIGNAL(textChanged(QString)),
this, SLOT(SetofSymbols(QString))); /* соединяем сигнал об изменении содержимого строки со слотом, который будет вызываться в ответ на это изменение */ }
Добавьте в файл dialog.h объявление слота:
public slots: void SetofSymbols(QString);
Добавьте в файл dialog.cpp определение слота:
// Обратите внимание на то, что исходная строка автоматически передается слоту: void Dialog::SetofSymbols(QString str) { QList
Пример 3: программа, которая считывает текст из элемента tetxEdit и выводит в столбик числа, содержащиеся в тексте с помощью другого элемента типа textEdit.
Спроектируйте окно как показано на рисунке, используя 2 элемента типа textEdit.
В файл dialog.cpp внесите код, показанный ниже:
#include "dialog.h" #include "ui_dialog.h" #include
this, SLOT(FindWords())); }
В файл dialog.h вставьте объявление слота:
public slots: void FindWords();
В файле dialog.cpp напишите определение слота:
void Dialog::FindWords() { QString str = ui->textEdit->toPlainText(); // считываем текст из окна textEdit (текст может быть многострочным) QTextStream in(&str, QIODevice::ReadOnly); // создаем поток для чтения слов из текста QString rez; // текст, который будет выводиться во втором окне QString number; // строка, в которую будет считываться одно слово из текста while (!in.atEnd()) // пока поток не закончен { in >> number; // считываем одно слово QDoubleValidator* validator = new QDoubleValidator; // создаем указатель на валидатор int pos = 0; /* позиция в строке, с которой будет начинаться проверка (эта переменная нужна для функции validate() ) */ if(validator->validate(number, pos)) // проверяем слово number rez += number + '\n'; // если слово является числом, добавляем его к тексту } ui->textEdit_2->setText(rez); // выводим полученные числа на экран }
Задания для самостоятельного выполнения
-
Из двух вводимых с клавиатуры строк, состоящих только из слов, записанных латинскими буквами, разделенных запятыми и пробелами (с проверкой правильности ввода), создать третью строку, которая должна содержать символы, присутствующие одновременно в обеих исходных строках. В результирующую строку каждый символ должен входить только один раз. (См. пример 2)
-
Из двух вводимых с клавиатуры строк, состоящих только из слов, записанных русскими буквами, разделенных точками и пробелами (с проверкой правильности ввода), создать третью строку, которая должна содержать символы, присутствующие только во второй строке. В результирующую строку каждый символ должен входить только один раз. (См. пример 2) -
Создать приложение, которое считывает строку текста, состоящую только из слов записанных латинскими буквами, разделенных запятыми и пробелами (с проверкой правильности ввода). Если за запятой не стоит пробел, вставить его и получившуюся строку вывести на экран. -
Создать приложение, которое считывает строку текста, состоящую только из слов записанных русскими буквами, разделенных точками и пробелами (с проверкой правильности ввода). Если перед точкой стоят пробелы, удалить их и получившуюся строку вывести на экран. -
Создать приложение, которое считывает строку текста, состоящую только из слов записанных латинскими буквами, разделенных точками и пробелами (с проверкой правильности ввода). Если первое слово, идущее за точкой, начинается с маленькой буквы, заменить эту букву большой и получившуюся строку вывести на экран. -
Создать приложение, которое считывает строку текста, состоящую только из чисел, разделенных пробелами (с проверкой правильности ввода). Удалить лишние пробелы между числами, т.е. из нескольких идущих подряд пробелов оставить только один. Получившуюся строку вывести на экран. -
Создать приложение, которое считывает строку текста, состоящую только из слов, записанных русскими буквами, разделенных пробелами (с проверкой правильности ввода). Если в слове встречаются две идущие подряд большие буквы, заменить вторую большую букву маленькой. -
Создать приложение которое считывает строку текста и подсчитывает, сколько раз заданный символ встречается в этой строке. При вводе символа не позволять пользователю вводить более одного. -
Создать приложение, которое считывает две строки символов и проверяет, является ли вторая строка анаграммой первой (т.е. можно ли получить вторую строку путем перестановки символов первой), например: "корт" и "крот".
Указание: отсортируйте обе строки и сравните. -
Создать приложение, которое считывает строку символов, состоящую только из цифр и латинских букв (с проверкой правильности ввода). Вставить после каждого символа запятую и полученную строку вывести на экран. -
Создать приложение, которое считывает строку текста, состоящую только из цифр и запятых (с проверкой правильности ввода). Удалить запятые из строки и результат вывести на экран. -
Создать приложение, которое считывает строку текста, состоящую только из русских букв и запятых (с проверкой правильности ввода). Заменить запятые пробелами и результат вывести на экран. -
Создать приложение, которое считывает строку текста, содержащую фамилию, имя и отчество. Заменить фамилию на новую, которая вводится в другом окне редактирования. Полученную строку вывести на экран. -
Создать приложение, которое считывает строку текста и переносит первое слово в конец строки. Результат вывести на экран. -
Создать приложение, которое считывает строку текста и переносит последнее слово в начало строки. Результат вывести на экран. -
Создать приложение, которое считывает строку текста и выводит на экран те слова, которые начинаются и заканчиваются на одну и ту же букву. -
Создать приложение, которое считывает строку текста и выводит на экран те слова, которые начинаются с цифры. -
Создать приложение, которое считывает строку текста и после второго слова вставляет новое, которое вводится в другом окне редактирования. Полученную строку вывести на экран.
Лабораторная работа № 5
1 2 3 4 5 6 7
Тема: «Главные окна. Меню. Работа с файлами»
Пример 1: программа, которая считывает текст из файла и выводит его в главном окне; используется файл ресурсов.
Создайте проект на базе класса QMainWindow.
В этой программе мы будем использовать команды меню «Открыть файл» и «Выход» и соответствующие иконки на панели инструментов. Используя команду операционной системы «Search for Files>, найдите файлы fileopen.png и exit.png. Скопируйте эти файлы в папку проекта.
Графические изображения и другие ресурсы лучше хранить в самом исполняемом файле программы.
Для подключения файлов к ресурсам программы вернитесь в Qt Creator и выберите в меню File | New File or Project. Нам нужно создать файл ресурсов. Для этого выберите в появившемся окне Qt | Qt Resource file и нажмите Choose.
В появившемся окне Choose the Location нужно задать имя файла ресурсов (например res) и путь к этому файлу (оставьте установленный по умолчанию путь к папке Вышего проекта). Нажмите кнопу .
В следующем окне нажмите .
Появится окно редактирования файла ресурсов. Расширение имени файла ресурсов — qrc, поэтому в заголовке окна должно быть указано res.qrc.
Нажмите кнопку <Add> в этом окне и в выпадающем меню - <Add Prefix>.
Обычно в качестве префикса используют Slash (/). Задайте Prefix как показано на рисунке.
Щелкните опять по кнопке Add и выберите Add Files. В появившемя окне выделите имена файлов-рисунков (*.png) и щелкните по кнопке . Имена файлов должны появиться в окне для работы с ресурсами. Сохраните файл ресурсов (Ctrl+s) и закройте окно ресурсов (Ctrl+w).
Вернитесь к проектированию окна программы.
Окно типа QMainWindow содержит вверху полоску меню и на ней заготовку кнопки с надписью Type Here. Сделайте двойной щелчок мышью по этой кнопке и напишите имя команды: Файл. Нажмите . Появится заготовка выпадающего меню.
В выпадающем меню сделайте двойной щелчок по заготовке кнопки с надписью Type Here, напишите: Открыть файл и нажмите . После этого сделайте двойной щелчок по расположенной ниже кнопке , в результате будет добавлен разделитель между кнопками выпадающего меню.
В свойствах созданной кнопки (справа) задайте свойство objectName: actionOpen (команды выпадающего меню называются actions (действия)).
Сделайте двойной щелчок по следующей заготовке кнопки (по надписи Type Here) и задайте название команды: Выход и идентификатор objectName: actionQuit.
Под проектом окна программы располагается окно со вкладкой Action Editor. Перейдите на эту вкладку. Вы увидите список созданных действий.
Сделайте двойной щелчок по строке аctionOpen. Откроется окно редактирования свойств соответствующей кнопки. В этом окне в строке Icon: щелкните по кнопке с тремя точками.
Откроется окно Select Resource. Щелкните по строке , должны появиться значки.
Выберите нужный значок для команды ищелкните по кнопке .
В текущем окне выделите окно с надписью Shortcut и нажмите комбинацию клавиш, которая будет активизировать команду (например Ctrl + О) (буква латинская). Название «горячих клавиш» автоматически отобразится в этом окне и будет отображаться рядом с названием команды меню во время выполнения программы. Для того, чтобы убрать «горячую клавишу» используйте расположенную справа кнопку с красной стрелочкой.
Нажмите .
Проделайте те же действия для строки actionQuit. Установите клавишу для вызова команды «Выход». Нажмите .
Теперь для каждой команды будет установлен значок.
Перетащите мышью значки команд из окна Action Editor в заготовку окна программы на полоску панели инструментов, располагающуюся под меню.
Накройте рабочую поверхность окна элементом text Edit, с его помощью мы будем отображать текст файла.
Т еперь проект окна должен иметь вид как на рисунке.
Перейдите в окно, располагающееся под проектом окна программы на вкладку «Signals & Slots Editor». Добавьте новую связь, щелкнув по зеленому крестику.
Свяжите сигнал triggered() (вызвана) кнопки с идентификатором actionQuit со слотом close() для главного окна.
Отредактируйте файл main.cpp как показано на рисунке.
#include #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.move(400,200); // перемещаем окно по экрану w.show(); return a.exec(); }
Запустите приложение и проверьте работу команды «Выход» (в том числе и клавишу ).
Вернитесь к проектированию окна программы.
В окне редактирования команд меню перейдите на вкладку Action Editor.
Щелкните правой кнопкой мыши по команде actionOpen и в контекстном меню выберите Go to slot. Создайте слот для сигнала triggered().
В начало файла mainwindow.cpp добавьте команды:
#include #include
Отредактируйте текст слота как показано ниже.
void MainWindow::on_actionOpen_triggered() { QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); QFile file(":/test.txt"); /* объявляем файл, файл мы будем брать из ресурсов программы (на это указывает префикс « :/ » в имени файла */ if (file.exists()) // если файл найден { file.open(QIODevice::ReadOnly|QIODevice::Text); // открываем его QString text = file.readAll(); // считываем весь текст ui->textEdit->setText(text); // выводим текст файла на экран } else ui->textEdit->setText("Файл не найден"); }
Создайте текстовый файл для проверки работы программы. Для этого в окне Qt Creator вызовите команду File | New File or Project. В появившемся окне выберите General | Text File и нажмите кнопку Choose. На следующем шаге задайте имя файла test. Выберите каталог, в котором содержится исполняемый файл Вашей программы (он будет открываться первым), и нажмите кнопку . На следующем шаге нажмите .
В появившемся окне напишите 3-4 строчки текста и сохраните файл.
Наша первая программа будет работать с одним конкретным файлом. Чтобы не указывать полный путь к файлу, можно включить его в ресурсы программы. В окне, отображающем структуру проекта, в разделе Resources сделайте двойной щелчок по имени файла ресурсов (res.qrc) и добавьте файл в ресурсы с помощью кнопки Add. Сохраните файл ресурсов и запустите программу. Откройте файл и убедитесь, что текст файла отображается в окне.
Пример 2: программа, которая считывает текст из файла и половину строк переписывает в другой файл; используются специальные окна для работы с файлами.
Создайте проект на основе класса QMainWindow, добавьте меню с командами «Открыть файл», «Сохранить файл» и «Выход». Свяжите сигнал triggered() кнопки «Выход» со слотом close() главного окна (см. пример 1).
Объявите в классе MainWindow файл и счетчик строк:
QFile file; int counter; В начало файла mainwindow.h вставьте подключение заголовочного файла: #include Перейдите в файл mainwindow.cpp и подключите заголовочные файлы: #include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include В конструкторе задайте кодировку, обеспечивающую использование кириллицы: MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); } MainWindow::
MainWindow() { delete ui; }
Создайте слот для команды actionOpen:
void MainWindow::on_actionOpen_triggered() { QString fileName = QfileDialog::getOpenFileName( this, // указатель на родительское окно "Открыть файл", // заголовок окна QString(), // выбор начинается с текущего каталога QString("Текстовые файлы (*.txt);;Все файлы (*.*)") ); // фильтры для списка файлов if (!fileName.isEmpty()) // если имя файла выбрано { file.setFileName(fileName); // связываем объект file с физическим файлом file.open(QIODevice::ReadOnly|QIODevice::Text); // открываем файл для чтения QString text = "Файл " + fileName + ": \n"; // выводим название файла QString line; // строка для чтения файла counter = 0; while (!file.atEnd()) // пока файл не закончен { line = file.readLine(); // считываем строку из файла counter++; // увеличиваем счетчик строк text += line; // добавляем строку к тексту } QString tmp; // вспомогательная строка для отображения результата tmp = Qstring( "\nКоличество строк в файле %1 \n").arg(counter); text += tmp; // добавляем результат к выводимому тексту ui->textEdit->setText(text); // отображаем текст на экране } }
Создайте слот для команды actionSave:
void MainWindow::on_actionSave_triggered() { QString fileName = QFileDialog::getSaveFileName(this, "Сохранить файл", Qstring(), QString("Текстовые файлы (*.txt);;Все файлы (*.*)") ); // используем окно для задания имени сохраняемого файла QFile rezFile; // Результирующий файл if (!fileName.isEmpty()) // Если имя файла задано { QString line; // строка из файла if (file.isOpen()) // если исходный файл открыт { file.seek(0); // переходим в начало файла rezFile.setFileName(fileName); // присваиваем физическое имя результирующему файлу rezFile.open(QIODevice::WriteOnly|QIODevice::Text); // открываем сохраняемый файл QTextStream out(&rezFile); /* создаем поток, связанный с файлом (запись файла обычно выполняется с помощью потока) */ for (int i = 1; i <= counter/2; ++i) // отсчитываем половину строк { line = file.readLine(); // считываем строку из исходного файла out << line; // записываем в результирующий файл } rezFile.close(); // закрываем создаваемый файл rezFile.open(QIODevice::ReadOnly|QIODevice::Text); // открываем сохраненнный файл для чтения QString text = rezFile.readAll(); // считываем результирующий файл ui->textEdit->setText(text); // выводим полученный файл на экран } } else ui->textEdit->setText("Файл не сохранен"); }
Пример 3: программа, которая считывает текст из файла и подсчитывает количество видимых символов и количество русских букв.
Создайте проект на основе класса QMainWindow, добавьте меню с командами «Открыть файл» и «Выход». Свяжите сигнал triggered() кнопки «Выход» со слотом close() главного окна (см. пример 1).
Подключите заголовочные файлы:
#include "mainwindow.h" #include "ui_mainwindow.h" #include #include #include Добавьте команды, обеспечивающие использование кириллицы: MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); } MainWindow::
MainWindow() { delete ui; }
Тема: «Главные окна. Меню. Работа с файлами»
Пример 1: программа, которая считывает текст из файла и выводит его в главном окне; используется файл ресурсов.
Создайте проект на базе класса QMainWindow.
В этой программе мы будем использовать команды меню «Открыть файл» и «Выход» и соответствующие иконки на панели инструментов. Используя команду операционной системы «Search for Files>, найдите файлы fileopen.png и exit.png. Скопируйте эти файлы в папку проекта.
Графические изображения и другие ресурсы лучше хранить в самом исполняемом файле программы.
Для подключения файлов к ресурсам программы вернитесь в Qt Creator и выберите в меню File | New File or Project. Нам нужно создать файл ресурсов. Для этого выберите в появившемся окне Qt | Qt Resource file и нажмите Choose.
В появившемся окне Choose the Location нужно задать имя файла ресурсов (например res) и путь к этому файлу (оставьте установленный по умолчанию путь к папке Вышего проекта). Нажмите кнопу
В следующем окне нажмите
Появится окно редактирования файла ресурсов. Расширение имени файла ресурсов — qrc, поэтому в заголовке окна должно быть указано res.qrc.
Нажмите кнопку <Add> в этом окне и в выпадающем меню - <Add Prefix>.
Обычно в качестве префикса используют Slash (/). Задайте Prefix как показано на рисунке.
Щелкните опять по кнопке Add и выберите Add Files. В появившемя окне выделите имена файлов-рисунков (*.png) и щелкните по кнопке
Вернитесь к проектированию окна программы.
Окно типа QMainWindow содержит вверху полоску меню и на ней заготовку кнопки с надписью Type Here. Сделайте двойной щелчок мышью по этой кнопке и напишите имя команды: Файл. Нажмите
В выпадающем меню сделайте двойной щелчок по заготовке кнопки с надписью Type Here, напишите: Открыть файл и нажмите
В свойствах созданной кнопки (справа) задайте свойство objectName: actionOpen (команды выпадающего меню называются actions (действия)).
Сделайте двойной щелчок по следующей заготовке кнопки (по надписи Type Here) и задайте название команды: Выход и идентификатор objectName: actionQuit.
Под проектом окна программы располагается окно со вкладкой Action Editor. Перейдите на эту вкладку. Вы увидите список созданных действий.
Сделайте двойной щелчок по строке аctionOpen. Откроется окно редактирования свойств соответствующей кнопки. В этом окне в строке Icon: щелкните по кнопке с тремя точками.
Откроется окно Select Resource. Щелкните по строке
Выберите нужный значок для команды ищелкните по кнопке
В текущем окне выделите окно с надписью Shortcut и нажмите комбинацию клавиш, которая будет активизировать команду (например Ctrl + О) (буква латинская). Название «горячих клавиш» автоматически отобразится в этом окне и будет отображаться рядом с названием команды меню во время выполнения программы. Для того, чтобы убрать «горячую клавишу» используйте расположенную справа кнопку с красной стрелочкой.
Нажмите
Проделайте те же действия для строки actionQuit. Установите клавишу
Теперь для каждой команды будет установлен значок.
Перетащите мышью значки команд из окна Action Editor в заготовку окна программы на полоску панели инструментов, располагающуюся под меню.
Накройте рабочую поверхность окна элементом text Edit, с его помощью мы будем отображать текст файла.
Т еперь проект окна должен иметь вид как на рисунке.
Перейдите в окно, располагающееся под проектом окна программы на вкладку «Signals & Slots Editor». Добавьте новую связь, щелкнув по зеленому крестику.
Свяжите сигнал triggered() (вызвана) кнопки с идентификатором actionQuit со слотом close() для главного окна.
Отредактируйте файл main.cpp как показано на рисунке.
#include
Запустите приложение и проверьте работу команды «Выход» (в том числе и клавишу
Вернитесь к проектированию окна программы.
В окне редактирования команд меню перейдите на вкладку Action Editor.
Щелкните правой кнопкой мыши по команде actionOpen и в контекстном меню выберите Go to slot. Создайте слот для сигнала triggered().
В начало файла mainwindow.cpp добавьте команды:
#include
Отредактируйте текст слота как показано ниже.
void MainWindow::on_actionOpen_triggered() { QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); QFile file(":/test.txt"); /* объявляем файл, файл мы будем брать из ресурсов программы (на это указывает префикс « :/ » в имени файла */ if (file.exists()) // если файл найден { file.open(QIODevice::ReadOnly|QIODevice::Text); // открываем его QString text = file.readAll(); // считываем весь текст ui->textEdit->setText(text); // выводим текст файла на экран } else ui->textEdit->setText("Файл не найден"); }
Создайте текстовый файл для проверки работы программы. Для этого в окне Qt Creator вызовите команду File | New File or Project. В появившемся окне выберите General | Text File и нажмите кнопку Choose. На следующем шаге задайте имя файла test. Выберите каталог, в котором содержится исполняемый файл Вашей программы (он будет открываться первым), и нажмите кнопку
В появившемся окне напишите 3-4 строчки текста и сохраните файл.
Наша первая программа будет работать с одним конкретным файлом. Чтобы не указывать полный путь к файлу, можно включить его в ресурсы программы. В окне, отображающем структуру проекта, в разделе Resources сделайте двойной щелчок по имени файла ресурсов (res.qrc) и добавьте файл в ресурсы с помощью кнопки Add. Сохраните файл ресурсов и запустите программу. Откройте файл и убедитесь, что текст файла отображается в окне.
Пример 2: программа, которая считывает текст из файла и половину строк переписывает в другой файл; используются специальные окна для работы с файлами.
Создайте проект на основе класса QMainWindow, добавьте меню с командами «Открыть файл», «Сохранить файл» и «Выход». Свяжите сигнал triggered() кнопки «Выход» со слотом close() главного окна (см. пример 1).
Объявите в классе MainWindow файл и счетчик строк:
QFile file; int counter; В начало файла mainwindow.h вставьте подключение заголовочного файла: #include
Создайте слот для команды actionOpen:
void MainWindow::on_actionOpen_triggered() { QString fileName = QFileDialog::getOpenFileName(this, "Открыть файл", Qstring(), QString("Текстовые файлы (*.txt);;Все файлы (*.*)") ); // выбираем файл для чтения if (!fileName.isEmpty()) // если имя файла выбрано { QFile file; file.setFileName(fileName); // связываем объект file с физическим файлом file.open(QIODevice::ReadOnly|QIODevice::Text); // открываем файл для чтения QFileInfo fi(fileName); // объект, который хранит информацию о файле QString name = fi.fileName(); // получаем чистое имя файла (без пути) QString text; // здесь будет храниться текст файла QChar sym; // один символ из файла QTextStream in(&file); // поток для чтения файла int counter = 0; // счетчик символов while (!in.atEnd()) // пока поток не закончен { in >> sym; // считываем символ if (sym.isPrint()) counter++; /* если это видимый (печатный) символ, увеличиваем счетчик (пробелы относятся к печатным символам) */ text += sym; // добавляем символ к тексту } QString tmp1 = QString("Количество видимых символов = %1 \n").arg(counter); // строка для вывода количества символов counter = text.count(QRegExp("[А-Яа-я]")); // подсчитываем количество русских букв QString tmp2 = QString("Количество русских букв = %1\n").arg(counter); // строка для вывода количества русских букв text += tmp1; text += tmp2; text = "Файл " + name + ": \n\n" + text; // заголовок ui->textEdit->setText(text); // вывод результата } }
Создайте текстовый файл для проверки работы программы (см. пример 1).
Запустите программу и проверьте ее работу.
Пример 4: программа, которая считывает текст из файла и переписывает в другой файл строки, заменяя одну последовательность символов на другую; cимволы задают с помощью специального диалогового окна, появляющегося при нажатии кнопки на панели инструментов.
Создайте проект на основе класса QMainWindow, добавьте меню с командами «Открыть файл», «Сохранить файл» и «Выход». Свяжите сигнал triggered() кнопки «Выход» со слотом close() главного окна (см. пример 1). Подключите иконки к действиям и создайте три кнопки на панели инструментам, соответствующие командам меню.
Найдите файл с какой-нибудь иконкой (*.png), которую Вы будете использовать для кнопки, при нажатии на которую будет появляться диалоговое окно. Скопируйте этот файл в папку Вашего проекта и добавьте его в ресурсы.
В качестве примера создадим кнопку «Задание», которая будет присутствовать только на панели инструментов, не имея аналога в меню.
В окне Action Editor нажмите кнопку New.
О
ткроется окно для задания свойств нового действия (action). Задайте свойства как показано на рисунке.
Подключите иконку к кнопке.
Нажмите
Перетащите иконку нового действия на панель инструментов. Теперь в меню должно быть 3 команды, а на панели инструментов - 4.
Накройте рабочую поверхность окна элементом textEdit.
Добавьте слот для кнопки «Открыть файл» и внесите в него код как показано ниже:
void MainWindow::on_actionOpen_triggered() { QString fileName = QFileDialog::getOpenFileName(this, "Открыть файл", Qstring(), QString("Текстовые файлы (*.txt);;Все файлы (*.*)" )); // получаем имя файла QFile file; // объявляем объект для работы с файлом if (!fileName.isEmpty()) // если имя файла выбрано { file.setFileName(fileName); // связываем объект с физическим файлом file.open(QIODevice::ReadOnly|QIODevice::Text); // открываем файл QFileInfo fi(fileName); // объект, содержащий информацию о файле QString name = fi.fileName(); // получаем чистое имя файла ui->textEdit->setText( "Файл " + name + ": \n"); // выводим заголовок text = file.readAll(); // считываем текст файла ui->textEdit->append(text); // выводим текст файла в окно } }
Теперь добавим новое диалоговое окно (вместе с классом, который его описывает). Для этого выберите в меню Qt Creator команду File|New File or Progect и в появившемся окне выберите Qt | Qt Designer Form Class.
Появится окно, в котором нужно выбрать шаблон диалогового окна. Выберите один из двух шаблонов с кнопками, например: Dialog with Buttons Right. Кнопка
В следующем окне нужно задать имя класса, который будет описывать диалоговое окно, и имена файлов, которые будут содержать описание класса. Оставьте предложенные имена и нажмите
Спроектируйте окно как показано на рисунке. Для ввода последовательностей символов используйте элементы lineEdit.
Для того, чтобы получить символы, которые будет вводить пользователь в диалоговом окне, нам нужно в классе Dialog, который описывает диалоговое окно, предусмотреть функции, которые будут предоставлять доступ к этим последовательностям символов. В файле dialog.h объявите функции: QString GetOld(); // символы, которые нужно заменить QString GetNew(); // символы, на которые нужно заменить В файле dialog.cpp определим эти функции: QString Dialog::GetOld() { return ui->lineEdit->text(); } QString Dialog::GetNew() { return ui->lineEdit_2->text(); }
В окне Action Editor перейдите к слоту для действия actionTask и внесите в слот код, показанный ниже:
void MainWindow::on_actionTask_triggered() { Dialog dlg; // объект, соответствующий диалоговому окну dlg.move(420,220); // определяем положение окна на экране if(dlg.exec()==QDialog::Accepted) // выводим окно на экран и если была нажата кнопка
В окне Action Editor перейдите к слоту для действия actionSave и внесите в слот код, показанный ниже:
void MainWindow::on_actionSave_triggered() { QString fileName = QFileDialog::getSaveFileName(this, "Сохранить файл", Qstring(), QString("Текстовые файлы (*.txt);;Все файлы (*.*)") ); // определяем имя, под которым нужно сохранить файл QFile rezFile; // объявляем объект, соответствующий новому файлу if (!fileName.isEmpty()) // если имя файла задано { rezFile.setFileName(fileName); // связываем объект и файл rezFile.open(QIODevice::WriteOnly|QIODevice::Text); // открываем файл QTextStream out(&rezFile); // создаем поток для работы с файлом out << text; // переписываем текст в файл rezFile.close(); // обязательно закрываем созданный файл rezFile.open(QIODevice::ReadOnly|QIODevice::Text); // открываем файл для чтения text = rezFile.readAll(); // считываем текст из файла ui->textEdit->setText("Новый файл:\n"); // выводим заголовок ui->textEdit->append(text); // выводим текст нового файла } else ui->textEdit->setText("Файл не сохранен"); }
Задания для самостоятельного выполнения
-
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, выравнивая длину каждой строки до заданной.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Длину строки считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов.
-
Написать программу с окном типа QMainWindow, которое считывает текст из файла, выводит его на экран и подсчитывает, сколько раз заданный символ содержится в тексте.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символ считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла, выводит его на экран и подсчитывает, сколько раз заданное слово содержится в тексте.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Слово считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов.
-
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран первые n символов этого файла.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Количество символов считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран первые n слов этого файла.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Количество слов считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран первые n строк этого файла.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Количество строк считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран первые n символов каждой строки.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Количество символов считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран те строки, которые начинаются с заданной последовательности символов.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символы считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран первые n слов каждой строки. Если в строке меньше слов, то выводится вся строка.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Количество слов считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран те строки, которые заканчиваются заданной последовательностью символов.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символы считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран те слова, которые начинаются на заданную последовательность символов.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символы считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран те слова, которые содержат заданную последовательность символов.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символы считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран те слова, которые заканчиваются заданной последовательностью символов.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символы считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем выводит на экран те слова, длина которых равна заданной.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Длину слов считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем повторно выводит на экран текст из файла, вставляя после заданного символа пробел, если он еще не стоит там.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символ считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов. -
Написать программу с окном типа QMainWindow, которое считывает текст из файла и выводит его на экран, затем повторно выводит его на экран, удаляя перед заданным символом пробелы, если они стоят там.
Имя файла должно считываться с помощью специального диалогового окна для открытия файлов.
Символ считывать с помощью вспомогательного диалогового окна, которое выводится на экран при нажатии на кнопку на панели инструментов.
Лабораторная работа № 6
Тема: «Графические элементы и строки состояния»
Пример 1: программа, которая вписывает N-угольник в окружность. При соединении вершин их можно проходить с шагом M, например через две или через три. Окружность задается двумя щелчками мыши (в центре и на окружности). Числа N и M считываются с клавиатуры в главном окне.
Создайте проект на основе класса QMainWindow. Щелкните по центру заготовки окна и в свойствах окна (MainWindow) измените свойство palette : сделайте двойной щелчок справа от этого слова и в появившемся окне Edit Palette найдите в списке Window (это свойство определяет цвет поверхности окна). Сделайте двойной щелчок справа от этого слова, появиттся окно Select Color. Выберите белый цвет окна. Закройте окна, щелкнув по кнопке OK.
Запустите программу и посмотрите как выглядит окно.
Вставьте в файл main.cpp код, показанный ниже:
#include
#include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.resize(400,400); // задаем размер окна w.move(450,250); // перемещаем окно в центр экрана w.show(); return a.exec(); }
Вставьте в объявление класса MainWindow (файл mainwindow.h) объявления переменных:
int n, m; // количество вершин многоугольника и шаг прохождения через вершины QPoint p[2]; // точки, по которым мы щелкаем мышью int counter; // счетчик щелчков мышью QString str; // строка, которая хранит задаваемые числа bool flag; // признак окончания ввода QLabel *label1, *label2; // панели для строки состояния double koef; // масштабный коэффициент для перевода радиуса в см Добавьте сюда же объявления функций: void paintEvent(QPaintEvent *); // эта функция автоматически вызывается при перерисовке окна void mousePressEvent(QMouseEvent *); // вызывается при нажатии кнопки мыши void keyPressEvent(QKeyEvent *); // вызывается при нажатии клавиши на клавиатуре
Вставьте в файл mainwindow.cpp код, показанный ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include // обеспечивает работу графического интерфейса MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf-8")); // обеспечиваем использование кириллицы m = n = 1; counter = 0; flag = false; label1 = new Qlabel(ui->statusBar); // создаем панель для строки состояния label1->setFrameStyle(QFrame::Panel | QFrame::Sunken); // задаем вид панели (утопленная) // то же самое для второй панели: label2 = new QLabel(ui->statusBar); label2->setFrameStyle(QFrame::Panel | QFrame::Sunken); // Определяем вид строки состояния: QPalette pal = ui->statusBar->palette(); // считывам палитру строки состояния pal.setColor(QPalette::Background, QСolor(215,220,210)); // задаем цвет фона строки состояния pal.setColor(QPalette::Foreground, QСolor(0,50,0)); // Задаем цвет текста в стороке состояния ui->statusBar->setPalette(pal); // Устанавливаем новую палитру ui->statusBar->setAutoFillBackground(true); // Нужно вызвать эту функцию, чтобы строка состояния закрасилась ui->statusBar->setSizeGripEnabled(false); // запрещаем показ маркера изменения размеров окна (это не обязательно) // Добавляем в правую часть строки состояния панели: ui->statusBar->addPermanentWidget(label1); ui->statusBar->addPermanentWidget(label2); /* Определим разрешение экрана для определения масштабного коэффициента для пересчета размеров в см: */ QDesktopWidget *desktop = QApplication::desktop(); int width = desktop->width(); // ширина экрана в точках int height = desktop->height(); // высота экрана в точках qDebug() << width <<" "<< height; // можно посмотреть, что получилось koef = 2.54*19/sqrt(width*width+height*height); /* вычисляем длину диагонали в см (в данном случае предполагается, что длина диагонали 19 дюймов) и делим на длину диагонали в точках */ qDebug()<<"koef = " << koef; // посмотрите значение масштабного коэффициента } MainWindow::
MainWindow() { delete ui; } // функция, обрабатывающая щелчки мышью: void MainWindow::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) // если щелкнули левой кнопкой мыши { counter %= 2; // номер точки может быть равен 0 или 1 p[counter++] = event->pos(); // записываем координаты точки, в которой пользователь щелкнул мышью update(); // перерисовываем окно } } // функция, обрабатывающая нажатие клавиш на клавиатуре: void MainWindow::keyPressEvent(QKeyEvent *event ) { QRegExp reg("[0-9]{1,3} [0-9]{1}"); // позволим вводить первое число не более, чем из 3 цифр и второе - из одной QRegExpValidator* validator = new QRegExpValidator(reg, this); // создаем валидатор для проверки строки на основе регулярного выражения int pos = 0; // эта переменная нужна для вызова валидатора if (flag) // если клавиша уже была нажата { str.clear(); // начинаем ввод сначала flag = false; } else { switch (event->key()) // проверяем, какая клавиша была нажата { case Qt::Key_Return: // если : { QTextStream in(&str,QIODevice::ReadOnly); // создаем поток из строки in >> n >> m; // считываем n и m flag = true; // запоминаем, что ввод выполнен } break; case Qt::Key_Backspace: // обеспечиваем возможность стирания: { int len = str.length(); // определяем длину строки str.remove(len-1, 1); // удаляем последний символ } break; default: QString ch = event->text(); // если обычный символ, считываем его QString tmp = str + ch; // попробуем добавить его к строке if (validator->validate(tmp, pos)) // если временная строка соответствует шаблону str += ch; // добавляем символ к используемой строке } } update(); // обновляем экран ui->statusBar->showMessage("Готово"); // Выводим сообщение в левой части строки состояния } // описываем, что нужно нарисовать в окне: void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); // объект для рисования painter.setBrush(QBrush(QColor(0,255,255))); // кисть QRect rect(0,0,width(), height()); // прямоугольник окна painter.setFont(QFont("Bitstream Charter",12)); // шрифт int r = 0; // радиус окружности if (counter == 2) // если окружность задана, рисуем ее { painter.setPen(QPen(QColor(0,255,0), 1)); // перо r = sqrt(pow(p[0].x() - p[1].x(), 2) + pow(p[0].y() - p[1].y(), 2)); // радиус окружности painter.drawEllipse(p[0], r, r); // рисуем окружность с центром в точке p[0] if (flag) // если числа заданы { QPoint* v = new QPoint[n]; // создаем массив для хранения вершин v[0] = p[0] + QPoint(r,0); // начальная вершина многоугольника double da = 2 * M_PI / n; // угол между вершинами double a = 0; // угол, соотвествующий очередной вершине for (int i = 1; i < n; ++i) // проходим вершины (кроме начальной) { a += m * da; // изменяем угол // вычисляем координаты: v[i].setX(p[0].x() + r*cos(a)); v[i].setY(p[0].y() - r*sin(a)); } painter.setBrush(Qt::darkCyan); // цвет многоугольника painter.drawPolygon(v, n, Qt::WindingFill); // рисуем закрашенный многоугольник } } // описываем вывод в зависимости от количества щелчков мышью: painter.setPen(QPen(QColor(100, 0, 100), 3));// цвет текста switch (counter) { case 0: painter.drawText(10, 40, "Задайте окружность двумя щелчками мыши"); break; case 1: painter.drawEllipse(p[0].x(), p[0].y(), 2, 2); break; case 2: if (flag) painter.drawText(10, 40, "Задайте число разбиений и шаг " + str); else painter.drawText(10, 40, "Задайте число разбиений и шаг " + str + '_'); } // Выводим информацию с помощью панелей строки состояния: QString text = QString("Координаты центра: %1, %2").arg(p[0].x()).arg(p[0].y()); label1->setText(text); double rsm = r*koef; // радиус в см text = QString(" радиус %1 см ").arg(rsm, 0,'f',1); // выводим радиус с точностью 1 знак после точки label2->setText(text); }
Пример 2: программа, в которой используется область отсечения QRegion и котекстное меню для выбора способа заливки этой области.
Создайте проект на основе класса QMainWindow. Добавьте в класс MainWindow (файл mainwindow.h) объявления данных и функций:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include // обеспечивает программирование графического интерфейса namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0);
MainWindow(); void contextMenuEvent(QContextMenuEvent *event); // обрабатывет щелчок правой кнопкой мыши void paintEvent(QPaintEvent *); // перерисовывает окно QRegion region; // область отсечения QMenu* contextMenu; // указатель для создания контекстного меню QBrush brush; // кисть для закрашивания области отсечения qreal x, y; // начальная точка области рисования qreal width, height; // ширина и высота области рисования qreal cx, cy; // координаты центра области рисования bool diagcross; // признак диагональной заливки public slots: void Solid(); // для действия «Сплошная» void Semitransparent(); // «Полупрозрачная» void Gradient(); // «Градиентная» void DiagCross(); // «Сетка» p rivate: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
Вставьте в файл mainwindow.cpp определения функций как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // обеспечиваем использование кириллицы: QTextCodec* codec = QTextCodec::codecForName("Utf-8"); QtextCodec::setCodecForCStrings(codec); contextMenu = new QMenu(this); // создаем контекстное меню // Действия для контекстного меню: QAction* actSolid = new QAction("Сплошная", this); contextMenu->addAction(actSolid); connect(actSolid, SIGNAL(triggered()), this, SLOT(Solid())); contextMenu->addSeparator(); QAction* actSemitransparent = new QAction("Полупрозрачная", this); contextMenu->addAction(actSemitransparent); connect(actSemitransparent, SIGNAL(triggered()), this, SLOT(Semitransparent())); contextMenu->addSeparator(); QAction* actGradient = new QAction("Градиентная", this); contextMenu->addAction(actGradient); connect(actGradient, SIGNAL(triggered()), this, SLOT(Gradient())); contextMenu->addSeparator(); QAction* actDiagcross = new QAction("Сетка", this); contextMenu->addAction(actDiagcross); connect(actDiagcross, SIGNAL(triggered()), this, SLOT(DiagCross())); brush = QBrush(Qt::darkGreen); // начальный цвет кисти diagcross = false; // в начале заливка - сплошная } MainWindow::
MainWindow() { delete ui; } void MainWindow::paintEvent(QPaintEvent * e) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // установили режим сглаживания линий // Начальные координаты области рисования относительно главного окна: x = centralWidget()->x(); y = centralWidget()->y(); //qDebug() << x << y; // посмотрите значения этих координат width = centralWidget()->width(); // ширина области рисования height = centralWidget()->height(); // высота области рисования // Координаты центра области рисования: cx = x + width/2; cy = y + height/2; qreal right = x+width; // координата правой границы области рисования qreal bottom = y+height; // координата нижней границы области рисования // Закрашиваем область рисования: QColor color = QColor(200,150,100); painter.setBrush(color); QRectF rect(x,y,width, height); painter.drawRect(rect); // Отступы от границ для эллипса qreal dx = width/10; qreal dy = height/10; // определяем область в виде эллипса: QRegion ellipticRgn = QRegion(x+dx, y+dy, width-2*dx, height-2*dy, QRegion::Ellipse); // Определяем многоугольник: QPolygon polygon; // Отступы от границ области рисования dx = width/20; dy = height/20; // Определяем вершины многоугольника: polygon << QPoint(x+dx, y+dy) << QPoint(cx, cy) << QPoint (right - dx, y+dy) << QPoint(right - dx, bottom-dy) << QPoint(cx,cy) << QPoint(x+dx, bottom-dy); QRegion polygonRgn(polygon); // Область отсечения в виде двух треугольников region = ellipticRgn.xored(polygonRgn); // Объединяем области с помощью оперции «исключающее или» painter.setClipRegion(region); // устанвливаем область отсечения // Если выбрана «Сетка»: if (diagcross) painter.fillRect(e->rect(),QBrush(Qt::green)); // заливаем фон области отсечения (это не обязательно) painter.fillRect(e->rect(), brush); /* заливаем область отсечения выбранным способом (указываем весь прямоугольник окна, но закрашена будет только область отсечения) */ painter.setClipping(false); // Отменяем установку области отсечения /* рисуем диагонали области рисования (для проверки, что она восстановлена, и для проверки, что фигура центрирована) */ painter.drawLine(x,y,right, bottom); painter.drawLine(right,y, x, bottom ); } // Функция, которая выводит на экран void MainWindow::contextMenuEvent(QContextMenuEvent *event) { QPoint point = event->pos(); // определяем координаты курсора мыши if (region.contains(point)) // проверяем, щелкнули ли мы внутри области отсечения { contextMenu->exec(event->globalPos()); // выводим меню на экран } } // Слот для команды «Сплошная»: void MainWindow::Solid() { brush = QBrush(Qt::darkGreen); diagcross = false; update(); } // Слот для команды «Полупрозрачная» : void MainWindow::Semitransparent() { QColor color(0, 128, 0, 100); // последний параметр определяет прозрачность (255 — не прозрачный) diagcross = false; brush = QBrush(color); update(); } // Слот для команды «Градиентная»: void MainWindow::Gradient() { QRadialGradient gradient(QPoint(cx, cy),width/2,QPoint(cx, cy)); // параметры: центральная точка, радиус и точка фокуса // определяем цвета заливки, которые будут переходить друг в друга: gradient.setColorAt(0, Qt::yellow); QColor color(255, 100, 0); gradient.setColorAt(0.5, color); gradient.setColorAt(1, Qt::darkGreen); brush = QBrush(gradient); // устанавливаем кисть для градиентной заливки diagcross = false; update(); } void MainWindow::DiagCross() { brush = QBrush(Qt::darkGreen, Qt::DiagCrossPattern); // определяем кисть для заливки сеткой diagcross = true; /* устанавливаем признак заливки сеткой (чтобы предварительно залить фон для сетки) */ update(); }
Задания для самостоятельного выполнения
-
Зарисовать окно «пчелиными сотами» (правильными шестиугольниками). Процесс зарисовки начинается при нажатии одной из кнопок мыши. Размер стороны шестиугольника - 1/n – ая часть длины меньшей стороны окна. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. В строке состояния вывести длину стороны шестиугольника и общее количество сот.
-
Окружность разделить на N равных частей. Соединить все точки разбиения хордами. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя! Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр окружности и одну точку, принадлежащую окружности, отметить нажатием левой кнопки мыши. В строке состояния вывести радиус окружности и длину хорды в точках и см.
-
Каждую сторону квадрата разделить на N равных частей. Соединить все точки разбиения, включая вершины, отрезками. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя! Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, принадлежащую стороне квадрата, отметить нажатием левой кнопки мыши. В строке состояния вывести координаты центра квадрата и длину стороны квадрата в точках и см.
-
Каждую сторону равностороннего треугольника разделить на N равных частей. Соединить все точки разбиения, имеющие одинаковые номера, отрезками вписав, таким образом, N треугольников в исходный треугольник. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя!Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр треугольника отметить нажатием левой кнопки мыши. Длину стороны взять максимально возможную для отмеченной точки, но чтобы треугольник не выходил за пределы окна. В строке состояния вывести координаты центра треугольника и длину его стороны в точках и см.
-
Каждую сторону прямоугольника разделить на N равных частей. Соединить все точки разбиения, имеющие одинаковые номера, отрезками вписав, таким образом, N четырехугольников в исходный прямоугольник. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! Центр прямоугольника и одну из его вершин отметить нажатием левой кнопки мыши. В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
-
Построить на экране дисплея произвольный прямоугольник, фиксируя его центр и одну из вершин с помощью кнопки мыши. Заштриховать внутреннюю область прямоугольника прямоугольной сеткой (горизонтальными и вертикальными отрезками, параллельными сторонам прямоугольника). Расстояние между линиями штриховки – 1/n – ая часть длины меньшей стороны прямоугольника. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
-
Построить на экране дисплея произвольный прямоугольник, фиксируя его центр и одну из вершин с помощью кнопки мыши. Заштриховать внутреннюю область прямоугольника наклонной сеткой (отрезками с наклоном 45 и 135 градусов). Расстояние между линиями штриховки – 1/n – ая часть длины меньшей стороны прямоугольника. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
-
На экране дисплея построить правильный N-угольник, вписанный в окружность. Число N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр многоугольника и одну точку на окружности зафиксировать с помощью кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра окружности и площадь N-угольника в точках и см2.
-
Окружность разделить на N равных частей. Из каждой точки разбиения, как из центра, провести окружность радиусом, равным половине радиуса исходной окружности. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр окружности и одну точку, принадлежащую окружности, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра исходной окружности и площадь одной маленькой окружности в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Из каждой точки разбиения, включая вершины, как из центра, провести окружность радиусом, равным расстоянию от точки до центра квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, лежащую на стороне квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Каждую точку разбиения, включая вершины, соединить с центром квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Соединить симметричные точки разбиения, лежащие на противоположных сторонах квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Соединить точки разбиения, лежащие на смежных сторонах квадрата и имеющие одинаковые номера. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
Лабораторная работа № 7
Тема: «Рисование мышью»
Пример 1: программа, которая рисует траектории движения мыши при нажатой левой кнопке выбранным цветом и стирает рисунок при щелчке правой кнопкой мыши.
Создайте проект на основе главного окна и задайте белый цвет фона в свойствах этого окна.
В файле mainwindow.h объявите функции:
void mousePressEvent(QMouseEvent *e); // функция, вызываемая при нажатии кнопки мыши void mouseMoveEvent(QMouseEvent *e); // функция, вызываемая при движении мыши void paintEvent(QPaintEvent *); // функция, автоматически вызываемая при перерисовке окна
Тамже объявите переменные и объекты:
QColor color; // цвет линий QPoint p[2]; // точки, определяющие линию (фрагмент траектории движения мыши) bool drawMode; // признак рисования QList DrawBuffer; // список для хранения линий QList ColorBuffer; // список для хранения цветов линий public slots: void showDialog(); // слот, вызываемый при нажатии кнопки в меню
Отредактируйте файл mainwindow.cpp как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // обеспечиваем использование кириллицы: QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); // добавляем в меню кнопку без выпадающего списка QAction* act = ui->menuBar->addAction("Выбор цвета"); // устанавливаем акселератор: act->setShortcut(QString("Alt+C")); // при нажатии на кнопку в меню должно появиться окно для выбора цвета: connect(act, SIGNAL(triggered()), this, SLOT(showDialog())); // задаем начальные значения: p[0] = p[1] = QPoint(0,0); color = QColor(0,100,100); drawMode = false; } MainWindow::
MainWindow() { delete ui; } void MainWindow::showDialog() { color = QColorDialog::getColor(); // считываем цвет } void MainWindow::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) // если нажата левая кнопка мыши { drawMode = true; // устанавливаем признак рисования p[0] = e->pos(); // запоминаем координаты начальной точки } if (e->button() == Qt::RightButton) // если нажата правая кнопка { color = QColor(0,100,100); // восстанавливаем первоначальный цвет DrawBuffer.clear(); // очищаем списки ColorBuffer.clear(); drawMode = false; // правой кнопкой запретим рисовать update(); // перерисовываем окно } } void MainWindow::mouseMoveEvent(QMouseEvent *e) { if (drawMode) // если установлен режим рисования { p[1] = e->pos(); // запоминаем текущую точку DrawBuffer.append(QLine(p[0],p[1])); // добавляем линию в список ColorBuffer.append(color); // добавляем текущий цвет в список p[0] = p[1]; // текущую точку делаем начальной для следующего фрагмента линии update(); } } void MainWindow::paintEvent(QPaintEvent *) { if (DrawBuffer.size() < 1) return; // если рисовать нечего, выходим из функции QPainter painter(this); // объявляем итераторы для работы со списками: QList::const_iterator it = DrawBuffer.begin(); QList::const_iterator cit = ColorBuffer.begin(); // перерисовываем линии: do { painter.setPen(*cit++); // определяем перо того цвета, которое хранится в списке painter.drawLine(*it++); // рисуем фрагмент линии } while (it!= DrawBuffer.end()); // повторяем рисование, пока не закончится список }
Пример 2: программа, которая рисует окружности с помощью мыши (окружность видима в процессе построения). Нарисованные окружности можно сохранить в файле и загрузить из файла.
Создайте проект на основе главного окна и задайте белый цвет фона в свойствах этого окна.
По аналогии с предыдущим примером мы будем запоминать нарисованные окружности в списке. Но для того, чтобы использовать такие списки нам нужно определить класс, описывающий окружности.
Щелкните в окне, описывающем структуру проекта (слева), по имени проекта правой кнопкой мыши и в появившемся контекстном меню выберите Add New...
В появившемся диалоговом окне выберите С++ | C++ Class. Задайте имя класса Circle и завершите создание класса. К проекту будут добавлены файлы circle.h и circle.cpp, содержащие описание нашего класса.
Для описания окружности мы будем использовать координаты центра, радиус и цвет окружности. Хранить в списках можно только такие объекты, для которых определены конструктор по умолчанию, конструктор копирования и оператор присваивания. Кроме того нам потребуется основной коструктор.
Отредактируйте файл circle.h как показано ниже:
#ifndef CIRCLE_H #define CIRCLE_H #include // обеспечивает графическую систему class Circle { public: QPoint p; // координаты центра окружности int r; // радиус QColor color; // цвет Circle(); // конструктор по умолчанию Circle(QPoint& _p, int _r, QColor col); // основной конструктор Circle(const Circle& ); // конструктор копирования Circle& operator = (const Circle& ); // оператор присваивания }; #endif // CIRCLE_H
Отредактируйте файл circle.cpp как показано ниже:
#include "circle.h" Circle::Circle() { p = QPoint(0,0); r = 0; color = Qt::darkCyan; } Circle::Circle(QPoint &_p, int _r, QColor col = Qt::darkCyan) { p = _p; r = _r; color = col; } Circle::Circle(const Circle & circle) { p = circle.p; r = circle.r; color = circle.color; } Circle& Circle::operator =(const Circle & circle) { p = circle.p; r = circle.r; color = circle.color; return *this; }
Перейдите к редактированию дизайна окна. Добавьте в меню команду Файл.
В выпадающее меню добавьте действия: Открыть (actionOpen), Сохранить (actionSave) и Выход (actionQuit). Определите акселераторы для этих действий. Свяжите нажатие кнопки «Выход» со слотом close() главного окна.
Добавьте в меню команду Редактирование. В выпадающее меню добавьте действия: Выбрать цвет (actionColor), Отменить (actionAnnul), Очистить (actionClear).
Отредактируйте файл mainwindow.h как показано ниже:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include "circle.h" // обеспечивает использование типа Circle namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0);
MainWindow(); QPoint p[2]; // точки, которые определяют текущую окружность int r; // радиус bool drawMode; // признак рисования QList DrawBuffer; // список окружностей (ради этой строчки мы создали класс Circle) QColor color; // цвет текущей окружности void mousePressEvent(QMouseEvent *); // обрабатывает нажатие кнопки мыши void mouseMoveEvent(QMouseEvent *); // обрабатывает движение мыши void mouseReleaseEvent(QMouseEvent *); // обрабатывает отпускание кнопки мыши void paintEvent(QPaintEvent *); // описывает, что нужно нарисовать в окне public slots: void Annul(); // для кнопки «Отменить» void Clear(); // для кнопки «Очистить» void showDialog(); // для кнопки «Выбрать цвет» void save(); // для кнопки «Сохранить» void open(); // для кнопки «Открыть» private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
Отредактируйте файл mainwindow.cpp как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" /* Для того, чтобы можно было сохранить список окружностей, нужно научить программу сохранять каждый объект класса Circle: */ QDataStream& operator <<(QDataStream& ostream, const Circle& c) { ostream << c.p.x()<< c.p.y() << c.r << c.color ; return ostream; } // Описываем, как считывать из потока каждый объект класса circle: QDataStream& operator >> (QDataStream& istream, Circle& c) { int x, y; istream >> x >> y >> c.r >> c.color; c.p.setX(x); c.p.setY(y); return istream; } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // связываем сигналы от команд меню с соответствующими слотами: connect(ui->actionAnnul, SIGNAL(triggered()), this, SLOT(Annul())); connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(Clear())); connect(ui->actionColor, SIGNAL(triggered()), this, SLOT(showDialog())); connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(save())); connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(open())); // инициализируем элементы данных класса MainWindow: drawMode = false; p[0] = p[1] = QPoint(0,0); r = 0; color = Qt::darkCyan; } MainWindow::
MainWindow() { delete ui; } // Обрабатываем нажатие кнопки мыши: void MainWindow::mousePressEvent(QMouseEvent * e) { if (e->button() ==Qt::LeftButton) // если нажата левая кнопка { drawMode = true; // разрешаем рисование p[0] = e->pos(); // запоминаем центр окружности } } // Обрабатываем движение мыши: void MainWindow::mouseMoveEvent(QMouseEvent * e) { if (drawMode) // если прижата левая кнопка { p[1] = e->pos(); // запоминаем текущую точку на окружности r = sqrt(pow(p[1].x()-p[0].x(),2) + pow(p[1].y()-p[0].y(),2)); // вычисляем радиус окружности update(); // перерисовываем окно } } // Обрабатываем отпускание кнопки мыши: void MainWindow::mouseReleaseEvent(QMouseEvent *) { drawMode = false; // запрещаем рисование int r = sqrt(pow(p[1].x()-p[0].x(),2) + pow(p[1].y()-p[0].y(),2)); // вычисляем текущий радиус DrawBuffer.append(Circle(p[0], r, color)); // добавляем окружность в список update(); // перерисовываем окно } // Описываем, что нужно нарисовать в окне void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); int size = DrawBuffer.size(); if (size) // Если список не пуст: { // рисуем окружности, сохраненные в списке: QList
Тема: «Графические элементы и строки состояния»
Пример 1: программа, которая вписывает N-угольник в окружность. При соединении вершин их можно проходить с шагом M, например через две или через три. Окружность задается двумя щелчками мыши (в центре и на окружности). Числа N и M считываются с клавиатуры в главном окне.
Создайте проект на основе класса QMainWindow. Щелкните по центру заготовки окна и в свойствах окна (MainWindow) измените свойство palette : сделайте двойной щелчок справа от этого слова и в появившемся окне Edit Palette найдите в списке Window (это свойство определяет цвет поверхности окна). Сделайте двойной щелчок справа от этого слова, появиттся окно Select Color. Выберите белый цвет окна. Закройте окна, щелкнув по кнопке OK.
Запустите программу и посмотрите как выглядит окно.
Вставьте в файл main.cpp код, показанный ниже:
#include
#include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.resize(400,400); // задаем размер окна w.move(450,250); // перемещаем окно в центр экрана w.show(); return a.exec(); }
Вставьте в объявление класса MainWindow (файл mainwindow.h) объявления переменных:
int n, m; // количество вершин многоугольника и шаг прохождения через вершины QPoint p[2]; // точки, по которым мы щелкаем мышью int counter; // счетчик щелчков мышью QString str; // строка, которая хранит задаваемые числа bool flag; // признак окончания ввода QLabel *label1, *label2; // панели для строки состояния double koef; // масштабный коэффициент для перевода радиуса в см Добавьте сюда же объявления функций: void paintEvent(QPaintEvent *); // эта функция автоматически вызывается при перерисовке окна void mousePressEvent(QMouseEvent *); // вызывается при нажатии кнопки мыши void keyPressEvent(QKeyEvent *); // вызывается при нажатии клавиши на клавиатуре
Вставьте в файл mainwindow.cpp код, показанный ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include // обеспечивает работу графического интерфейса MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf-8")); // обеспечиваем использование кириллицы m = n = 1; counter = 0; flag = false; label1 = new Qlabel(ui->statusBar); // создаем панель для строки состояния label1->setFrameStyle(QFrame::Panel | QFrame::Sunken); // задаем вид панели (утопленная) // то же самое для второй панели: label2 = new QLabel(ui->statusBar); label2->setFrameStyle(QFrame::Panel | QFrame::Sunken); // Определяем вид строки состояния: QPalette pal = ui->statusBar->palette(); // считывам палитру строки состояния pal.setColor(QPalette::Background, QСolor(215,220,210)); // задаем цвет фона строки состояния pal.setColor(QPalette::Foreground, QСolor(0,50,0)); // Задаем цвет текста в стороке состояния ui->statusBar->setPalette(pal); // Устанавливаем новую палитру ui->statusBar->setAutoFillBackground(true); // Нужно вызвать эту функцию, чтобы строка состояния закрасилась ui->statusBar->setSizeGripEnabled(false); // запрещаем показ маркера изменения размеров окна (это не обязательно) // Добавляем в правую часть строки состояния панели: ui->statusBar->addPermanentWidget(label1); ui->statusBar->addPermanentWidget(label2); /* Определим разрешение экрана для определения масштабного коэффициента для пересчета размеров в см: */ QDesktopWidget *desktop = QApplication::desktop(); int width = desktop->width(); // ширина экрана в точках int height = desktop->height(); // высота экрана в точках qDebug() << width <<" "<< height; // можно посмотреть, что получилось koef = 2.54*19/sqrt(width*width+height*height); /* вычисляем длину диагонали в см (в данном случае предполагается, что длина диагонали 19 дюймов) и делим на длину диагонали в точках */ qDebug()<<"koef = " << koef; // посмотрите значение масштабного коэффициента } MainWindow::
MainWindow() { delete ui; } // функция, обрабатывающая щелчки мышью: void MainWindow::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) // если щелкнули левой кнопкой мыши { counter %= 2; // номер точки может быть равен 0 или 1 p[counter++] = event->pos(); // записываем координаты точки, в которой пользователь щелкнул мышью update(); // перерисовываем окно } } // функция, обрабатывающая нажатие клавиш на клавиатуре: void MainWindow::keyPressEvent(QKeyEvent *event ) { QRegExp reg("[0-9]{1,3} [0-9]{1}"); // позволим вводить первое число не более, чем из 3 цифр и второе - из одной QRegExpValidator* validator = new QRegExpValidator(reg, this); // создаем валидатор для проверки строки на основе регулярного выражения int pos = 0; // эта переменная нужна для вызова валидатора if (flag) // если клавиша уже была нажата { str.clear(); // начинаем ввод сначала flag = false; } else { switch (event->key()) // проверяем, какая клавиша была нажата { case Qt::Key_Return: // если : { QTextStream in(&str,QIODevice::ReadOnly); // создаем поток из строки in >> n >> m; // считываем n и m flag = true; // запоминаем, что ввод выполнен } break; case Qt::Key_Backspace: // обеспечиваем возможность стирания: { int len = str.length(); // определяем длину строки str.remove(len-1, 1); // удаляем последний символ } break; default: QString ch = event->text(); // если обычный символ, считываем его QString tmp = str + ch; // попробуем добавить его к строке if (validator->validate(tmp, pos)) // если временная строка соответствует шаблону str += ch; // добавляем символ к используемой строке } } update(); // обновляем экран ui->statusBar->showMessage("Готово"); // Выводим сообщение в левой части строки состояния } // описываем, что нужно нарисовать в окне: void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); // объект для рисования painter.setBrush(QBrush(QColor(0,255,255))); // кисть QRect rect(0,0,width(), height()); // прямоугольник окна painter.setFont(QFont("Bitstream Charter",12)); // шрифт int r = 0; // радиус окружности if (counter == 2) // если окружность задана, рисуем ее { painter.setPen(QPen(QColor(0,255,0), 1)); // перо r = sqrt(pow(p[0].x() - p[1].x(), 2) + pow(p[0].y() - p[1].y(), 2)); // радиус окружности painter.drawEllipse(p[0], r, r); // рисуем окружность с центром в точке p[0] if (flag) // если числа заданы { QPoint* v = new QPoint[n]; // создаем массив для хранения вершин v[0] = p[0] + QPoint(r,0); // начальная вершина многоугольника double da = 2 * M_PI / n; // угол между вершинами double a = 0; // угол, соотвествующий очередной вершине for (int i = 1; i < n; ++i) // проходим вершины (кроме начальной) { a += m * da; // изменяем угол // вычисляем координаты: v[i].setX(p[0].x() + r*cos(a)); v[i].setY(p[0].y() - r*sin(a)); } painter.setBrush(Qt::darkCyan); // цвет многоугольника painter.drawPolygon(v, n, Qt::WindingFill); // рисуем закрашенный многоугольник } } // описываем вывод в зависимости от количества щелчков мышью: painter.setPen(QPen(QColor(100, 0, 100), 3));// цвет текста switch (counter) { case 0: painter.drawText(10, 40, "Задайте окружность двумя щелчками мыши"); break; case 1: painter.drawEllipse(p[0].x(), p[0].y(), 2, 2); break; case 2: if (flag) painter.drawText(10, 40, "Задайте число разбиений и шаг " + str); else painter.drawText(10, 40, "Задайте число разбиений и шаг " + str + '_'); } // Выводим информацию с помощью панелей строки состояния: QString text = QString("Координаты центра: %1, %2").arg(p[0].x()).arg(p[0].y()); label1->setText(text); double rsm = r*koef; // радиус в см text = QString(" радиус %1 см ").arg(rsm, 0,'f',1); // выводим радиус с точностью 1 знак после точки label2->setText(text); }
Пример 2: программа, в которой используется область отсечения QRegion и котекстное меню для выбора способа заливки этой области.
Создайте проект на основе класса QMainWindow. Добавьте в класс MainWindow (файл mainwindow.h) объявления данных и функций:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include // обеспечивает программирование графического интерфейса namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0);
MainWindow(); void contextMenuEvent(QContextMenuEvent *event); // обрабатывет щелчок правой кнопкой мыши void paintEvent(QPaintEvent *); // перерисовывает окно QRegion region; // область отсечения QMenu* contextMenu; // указатель для создания контекстного меню QBrush brush; // кисть для закрашивания области отсечения qreal x, y; // начальная точка области рисования qreal width, height; // ширина и высота области рисования qreal cx, cy; // координаты центра области рисования bool diagcross; // признак диагональной заливки public slots: void Solid(); // для действия «Сплошная» void Semitransparent(); // «Полупрозрачная» void Gradient(); // «Градиентная» void DiagCross(); // «Сетка» p rivate: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
Вставьте в файл mainwindow.cpp определения функций как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // обеспечиваем использование кириллицы: QTextCodec* codec = QTextCodec::codecForName("Utf-8"); QtextCodec::setCodecForCStrings(codec); contextMenu = new QMenu(this); // создаем контекстное меню // Действия для контекстного меню: QAction* actSolid = new QAction("Сплошная", this); contextMenu->addAction(actSolid); connect(actSolid, SIGNAL(triggered()), this, SLOT(Solid())); contextMenu->addSeparator(); QAction* actSemitransparent = new QAction("Полупрозрачная", this); contextMenu->addAction(actSemitransparent); connect(actSemitransparent, SIGNAL(triggered()), this, SLOT(Semitransparent())); contextMenu->addSeparator(); QAction* actGradient = new QAction("Градиентная", this); contextMenu->addAction(actGradient); connect(actGradient, SIGNAL(triggered()), this, SLOT(Gradient())); contextMenu->addSeparator(); QAction* actDiagcross = new QAction("Сетка", this); contextMenu->addAction(actDiagcross); connect(actDiagcross, SIGNAL(triggered()), this, SLOT(DiagCross())); brush = QBrush(Qt::darkGreen); // начальный цвет кисти diagcross = false; // в начале заливка - сплошная } MainWindow::
MainWindow() { delete ui; } void MainWindow::paintEvent(QPaintEvent * e) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); // установили режим сглаживания линий // Начальные координаты области рисования относительно главного окна: x = centralWidget()->x(); y = centralWidget()->y(); //qDebug() << x << y; // посмотрите значения этих координат width = centralWidget()->width(); // ширина области рисования height = centralWidget()->height(); // высота области рисования // Координаты центра области рисования: cx = x + width/2; cy = y + height/2; qreal right = x+width; // координата правой границы области рисования qreal bottom = y+height; // координата нижней границы области рисования // Закрашиваем область рисования: QColor color = QColor(200,150,100); painter.setBrush(color); QRectF rect(x,y,width, height); painter.drawRect(rect); // Отступы от границ для эллипса qreal dx = width/10; qreal dy = height/10; // определяем область в виде эллипса: QRegion ellipticRgn = QRegion(x+dx, y+dy, width-2*dx, height-2*dy, QRegion::Ellipse); // Определяем многоугольник: QPolygon polygon; // Отступы от границ области рисования dx = width/20; dy = height/20; // Определяем вершины многоугольника: polygon << QPoint(x+dx, y+dy) << QPoint(cx, cy) << QPoint (right - dx, y+dy) << QPoint(right - dx, bottom-dy) << QPoint(cx,cy) << QPoint(x+dx, bottom-dy); QRegion polygonRgn(polygon); // Область отсечения в виде двух треугольников region = ellipticRgn.xored(polygonRgn); // Объединяем области с помощью оперции «исключающее или» painter.setClipRegion(region); // устанвливаем область отсечения // Если выбрана «Сетка»: if (diagcross) painter.fillRect(e->rect(),QBrush(Qt::green)); // заливаем фон области отсечения (это не обязательно) painter.fillRect(e->rect(), brush); /* заливаем область отсечения выбранным способом (указываем весь прямоугольник окна, но закрашена будет только область отсечения) */ painter.setClipping(false); // Отменяем установку области отсечения /* рисуем диагонали области рисования (для проверки, что она восстановлена, и для проверки, что фигура центрирована) */ painter.drawLine(x,y,right, bottom); painter.drawLine(right,y, x, bottom ); } // Функция, которая выводит на экран void MainWindow::contextMenuEvent(QContextMenuEvent *event) { QPoint point = event->pos(); // определяем координаты курсора мыши if (region.contains(point)) // проверяем, щелкнули ли мы внутри области отсечения { contextMenu->exec(event->globalPos()); // выводим меню на экран } } // Слот для команды «Сплошная»: void MainWindow::Solid() { brush = QBrush(Qt::darkGreen); diagcross = false; update(); } // Слот для команды «Полупрозрачная» : void MainWindow::Semitransparent() { QColor color(0, 128, 0, 100); // последний параметр определяет прозрачность (255 — не прозрачный) diagcross = false; brush = QBrush(color); update(); } // Слот для команды «Градиентная»: void MainWindow::Gradient() { QRadialGradient gradient(QPoint(cx, cy),width/2,QPoint(cx, cy)); // параметры: центральная точка, радиус и точка фокуса // определяем цвета заливки, которые будут переходить друг в друга: gradient.setColorAt(0, Qt::yellow); QColor color(255, 100, 0); gradient.setColorAt(0.5, color); gradient.setColorAt(1, Qt::darkGreen); brush = QBrush(gradient); // устанавливаем кисть для градиентной заливки diagcross = false; update(); } void MainWindow::DiagCross() { brush = QBrush(Qt::darkGreen, Qt::DiagCrossPattern); // определяем кисть для заливки сеткой diagcross = true; /* устанавливаем признак заливки сеткой (чтобы предварительно залить фон для сетки) */ update(); }
Задания для самостоятельного выполнения
-
Зарисовать окно «пчелиными сотами» (правильными шестиугольниками). Процесс зарисовки начинается при нажатии одной из кнопок мыши. Размер стороны шестиугольника - 1/n – ая часть длины меньшей стороны окна. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. В строке состояния вывести длину стороны шестиугольника и общее количество сот.
-
Окружность разделить на N равных частей. Соединить все точки разбиения хордами. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя! Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр окружности и одну точку, принадлежащую окружности, отметить нажатием левой кнопки мыши. В строке состояния вывести радиус окружности и длину хорды в точках и см.
-
Каждую сторону квадрата разделить на N равных частей. Соединить все точки разбиения, включая вершины, отрезками. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя! Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, принадлежащую стороне квадрата, отметить нажатием левой кнопки мыши. В строке состояния вывести координаты центра квадрата и длину стороны квадрата в точках и см.
-
Каждую сторону равностороннего треугольника разделить на N равных частей. Соединить все точки разбиения, имеющие одинаковые номера, отрезками вписав, таким образом, N треугольников в исходный треугольник. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя!Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр треугольника отметить нажатием левой кнопки мыши. Длину стороны взять максимально возможную для отмеченной точки, но чтобы треугольник не выходил за пределы окна. В строке состояния вывести координаты центра треугольника и длину его стороны в точках и см.
-
Каждую сторону прямоугольника разделить на N равных частей. Соединить все точки разбиения, имеющие одинаковые номера, отрезками вписав, таким образом, N четырехугольников в исходный прямоугольник. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! Центр прямоугольника и одну из его вершин отметить нажатием левой кнопки мыши. В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
-
Построить на экране дисплея произвольный прямоугольник, фиксируя его центр и одну из вершин с помощью кнопки мыши. Заштриховать внутреннюю область прямоугольника прямоугольной сеткой (горизонтальными и вертикальными отрезками, параллельными сторонам прямоугольника). Расстояние между линиями штриховки – 1/n – ая часть длины меньшей стороны прямоугольника. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
-
Построить на экране дисплея произвольный прямоугольник, фиксируя его центр и одну из вершин с помощью кнопки мыши. Заштриховать внутреннюю область прямоугольника наклонной сеткой (отрезками с наклоном 45 и 135 градусов). Расстояние между линиями штриховки – 1/n – ая часть длины меньшей стороны прямоугольника. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
-
На экране дисплея построить правильный N-угольник, вписанный в окружность. Число N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр многоугольника и одну точку на окружности зафиксировать с помощью кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра окружности и площадь N-угольника в точках и см2.
-
Окружность разделить на N равных частей. Из каждой точки разбиения, как из центра, провести окружность радиусом, равным половине радиуса исходной окружности. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр окружности и одну точку, принадлежащую окружности, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра исходной окружности и площадь одной маленькой окружности в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Из каждой точки разбиения, включая вершины, как из центра, провести окружность радиусом, равным расстоянию от точки до центра квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, лежащую на стороне квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Каждую точку разбиения, включая вершины, соединить с центром квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Соединить симметричные точки разбиения, лежащие на противоположных сторонах квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
-
Каждую сторону квадрата разделить на N равных частей. Соединить точки разбиения, лежащие на смежных сторонах квадрата и имеющие одинаковые номера. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
Лабораторная работа № 7
Тема: «Рисование мышью»
Пример 1: программа, которая рисует траектории движения мыши при нажатой левой кнопке выбранным цветом и стирает рисунок при щелчке правой кнопкой мыши.
Создайте проект на основе главного окна и задайте белый цвет фона в свойствах этого окна.
В файле mainwindow.h объявите функции:
void mousePressEvent(QMouseEvent *e); // функция, вызываемая при нажатии кнопки мыши void mouseMoveEvent(QMouseEvent *e); // функция, вызываемая при движении мыши void paintEvent(QPaintEvent *); // функция, автоматически вызываемая при перерисовке окна
Тамже объявите переменные и объекты:
QColor color; // цвет линий QPoint p[2]; // точки, определяющие линию (фрагмент траектории движения мыши) bool drawMode; // признак рисования QList DrawBuffer; // список для хранения линий QList ColorBuffer; // список для хранения цветов линий public slots: void showDialog(); // слот, вызываемый при нажатии кнопки в меню
Отредактируйте файл mainwindow.cpp как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // обеспечиваем использование кириллицы: QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); // добавляем в меню кнопку без выпадающего списка QAction* act = ui->menuBar->addAction("Выбор цвета"); // устанавливаем акселератор: act->setShortcut(QString("Alt+C")); // при нажатии на кнопку в меню должно появиться окно для выбора цвета: connect(act, SIGNAL(triggered()), this, SLOT(showDialog())); // задаем начальные значения: p[0] = p[1] = QPoint(0,0); color = QColor(0,100,100); drawMode = false; } MainWindow::
MainWindow() { delete ui; } void MainWindow::showDialog() { color = QColorDialog::getColor(); // считываем цвет } void MainWindow::mousePressEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) // если нажата левая кнопка мыши { drawMode = true; // устанавливаем признак рисования p[0] = e->pos(); // запоминаем координаты начальной точки } if (e->button() == Qt::RightButton) // если нажата правая кнопка { color = QColor(0,100,100); // восстанавливаем первоначальный цвет DrawBuffer.clear(); // очищаем списки ColorBuffer.clear(); drawMode = false; // правой кнопкой запретим рисовать update(); // перерисовываем окно } } void MainWindow::mouseMoveEvent(QMouseEvent *e) { if (drawMode) // если установлен режим рисования { p[1] = e->pos(); // запоминаем текущую точку DrawBuffer.append(QLine(p[0],p[1])); // добавляем линию в список ColorBuffer.append(color); // добавляем текущий цвет в список p[0] = p[1]; // текущую точку делаем начальной для следующего фрагмента линии update(); } } void MainWindow::paintEvent(QPaintEvent *) { if (DrawBuffer.size() < 1) return; // если рисовать нечего, выходим из функции QPainter painter(this); // объявляем итераторы для работы со списками: QList
Тема: «Графические элементы и строки состояния»
Пример 1: программа, которая вписывает N-угольник в окружность. При соединении вершин их можно проходить с шагом M, например через две или через три. Окружность задается двумя щелчками мыши (в центре и на окружности). Числа N и M считываются с клавиатуры в главном окне.
Создайте проект на основе класса QMainWindow. Щелкните по центру заготовки окна и в свойствах окна (MainWindow) измените свойство palette : сделайте двойной щелчок справа от этого слова и в появившемся окне Edit Palette найдите в списке Window (это свойство определяет цвет поверхности окна). Сделайте двойной щелчок справа от этого слова, появиттся окно Select Color. Выберите белый цвет окна. Закройте окна, щелкнув по кнопке OK.
Запустите программу и посмотрите как выглядит окно.
Вставьте в файл main.cpp код, показанный ниже:
#include
#include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.resize(400,400); // задаем размер окна w.move(450,250); // перемещаем окно в центр экрана w.show(); return a.exec(); }
Вставьте в объявление класса MainWindow (файл mainwindow.h) объявления переменных:
int n, m; // количество вершин многоугольника и шаг прохождения через вершины QPoint p[2]; // точки, по которым мы щелкаем мышью int counter; // счетчик щелчков мышью QString str; // строка, которая хранит задаваемые числа bool flag; // признак окончания ввода QLabel *label1, *label2; // панели для строки состояния double koef; // масштабный коэффициент для перевода радиуса в см Добавьте сюда же объявления функций: void paintEvent(QPaintEvent *); // эта функция автоматически вызывается при перерисовке окна void mousePressEvent(QMouseEvent *); // вызывается при нажатии кнопки мыши void keyPressEvent(QKeyEvent *); // вызывается при нажатии клавиши на клавиатуре
Вставьте в файл mainwindow.cpp код, показанный ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include // обеспечивает работу графического интерфейса MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf-8")); // обеспечиваем использование кириллицы m = n = 1; counter = 0; flag = false; label1 = new Qlabel(ui->statusBar); // создаем панель для строки состояния label1->setFrameStyle(QFrame::Panel | QFrame::Sunken); // задаем вид панели (утопленная) // то же самое для второй панели: label2 = new QLabel(ui->statusBar); label2->setFrameStyle(QFrame::Panel | QFrame::Sunken); // Определяем вид строки состояния: QPalette pal = ui->statusBar->palette(); // считывам палитру строки состояния pal.setColor(QPalette::Background, QСolor(215,220,210)); // задаем цвет фона строки состояния pal.setColor(QPalette::Foreground, QСolor(0,50,0)); // Задаем цвет текста в стороке состояния ui->statusBar->setPalette(pal); // Устанавливаем новую палитру ui->statusBar->setAutoFillBackground(true); // Нужно вызвать эту функцию, чтобы строка состояния закрасилась ui->statusBar->setSizeGripEnabled(false); // запрещаем показ маркера изменения размеров окна (это не обязательно) // Добавляем в правую часть строки состояния панели: ui->statusBar->addPermanentWidget(label1); ui->statusBar->addPermanentWidget(label2); /* Определим разрешение экрана для определения масштабного коэффициента для пересчета размеров в см: */ QDesktopWidget *desktop = QApplication::desktop(); int width = desktop->width(); // ширина экрана в точках int height = desktop->height(); // высота экрана в точках qDebug() << width <<" "<< height; // можно посмотреть, что получилось koef = 2.54*19/sqrt(width*width+height*height); /* вычисляем длину диагонали в см (в данном случае предполагается, что длина диагонали 19 дюймов) и делим на длину диагонали в точках */ qDebug()<<"koef = " << koef; // посмотрите значение масштабного коэффициента } MainWindow::
MainWindow() { delete ui; } // функция, обрабатывающая щелчки мышью: void MainWindow::mousePressEvent(QMouseEvent* event) { if (event->button() == Qt::LeftButton) // если щелкнули левой кнопкой мыши { counter %= 2; // номер точки может быть равен 0 или 1 p[counter++] = event->pos(); // записываем координаты точки, в которой пользователь щелкнул мышью update(); // перерисовываем окно } } // функция, обрабатывающая нажатие клавиш на клавиатуре: void MainWindow::keyPressEvent(QKeyEvent *event ) { QRegExp reg("[0-9]{1,3} [0-9]{1}"); // позволим вводить первое число не более, чем из 3 цифр и второе - из одной QRegExpValidator* validator = new QRegExpValidator(reg, this); // создаем валидатор для проверки строки на основе регулярного выражения int pos = 0; // эта переменная нужна для вызова валидатора if (flag) // если клавиша уже была нажата { str.clear(); // начинаем ввод сначала flag = false; } else { switch (event->key()) // проверяем, какая клавиша была нажата { case Qt::Key_Return: // если : { QTextStream in(&str,QIODevice::ReadOnly); // создаем поток из строки in >> n >> m; // считываем n и m flag = true; // запоминаем, что ввод выполнен } break; case Qt::Key_Backspace: // обеспечиваем возможность стирания: { int len = str.length(); // определяем длину строки str.remove(len-1, 1); // удаляем последний символ } break; default: QString ch = event->text(); // если обычный символ, считываем его QString tmp = str + ch; // попробуем добавить его к строке if (validator->validate(tmp, pos)) // если временная строка соответствует шаблону str += ch; // добавляем символ к используемой строке } } update(); // обновляем экран ui->statusBar->showMessage("Готово"); // Выводим сообщение в левой части строки состояния } // описываем, что нужно нарисовать в окне: void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this); // объект для рисования painter.setBrush(QBrush(QColor(0,255,255))); // кисть QRect rect(0,0,width(), height()); // прямоугольник окна painter.setFont(QFont("Bitstream Charter",12)); // шрифт int r = 0; // радиус окружности if (counter == 2) // если окружность задана, рисуем ее { painter.setPen(QPen(QColor(0,255,0), 1)); // перо r = sqrt(pow(p[0].x() - p[1].x(), 2) + pow(p[0].y() - p[1].y(), 2)); // радиус окружности painter.drawEllipse(p[0], r, r); // рисуем окружность с центром в точке p[0] if (flag) // если числа заданы { QPoint* v = new QPoint[n]; // создаем массив для хранения вершин v[0] = p[0] + QPoint(r,0); // начальная вершина многоугольника double da = 2 * M_PI / n; // угол между вершинами double a = 0; // угол, соотвествующий очередной вершине for (int i = 1; i < n; ++i) // проходим вершины (кроме начальной) { a += m * da; // изменяем угол // вычисляем координаты: v[i].setX(p[0].x() + r*cos(a)); v[i].setY(p[0].y() - r*sin(a)); } painter.setBrush(Qt::darkCyan); // цвет многоугольника painter.drawPolygon(v, n, Qt::WindingFill); // рисуем закрашенный многоугольник } } // описываем вывод в зависимости от количества щелчков мышью: painter.setPen(QPen(QColor(100, 0, 100), 3));// цвет текста switch (counter) { case 0: painter.drawText(10, 40, "Задайте окружность двумя щелчками мыши"); break; case 1: painter.drawEllipse(p[0].x(), p[0].y(), 2, 2); break; case 2: if (flag) painter.drawText(10, 40, "Задайте число разбиений и шаг " + str); else painter.drawText(10, 40, "Задайте число разбиений и шаг " + str + '_'); } // Выводим информацию с помощью панелей строки состояния: QString text = QString("Координаты центра: %1, %2").arg(p[0].x()).arg(p[0].y()); label1->setText(text); double rsm = r*koef; // радиус в см text = QString(" радиус %1 см ").arg(rsm, 0,'f',1); // выводим радиус с точностью 1 знак после точки label2->setText(text); }
Пример 2: программа, в которой используется область отсечения QRegion и котекстное меню для выбора способа заливки этой области.
Создайте проект на основе класса QMainWindow. Добавьте в класс MainWindow (файл mainwindow.h) объявления данных и функций:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include // обеспечивает программирование графического интерфейса namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0);
MainWindow(); void contextMenuEvent(QContextMenuEvent *event); // обрабатывет щелчок правой кнопкой мыши void paintEvent(QPaintEvent *); // перерисовывает окно QRegion region; // область отсечения QMenu* contextMenu; // указатель для создания контекстного меню QBrush brush; // кисть для закрашивания области отсечения qreal x, y; // начальная точка области рисования qreal width, height; // ширина и высота области рисования qreal cx, cy; // координаты центра области рисования bool diagcross; // признак диагональной заливки public slots: void Solid(); // для действия «Сплошная» void Semitransparent(); // «Полупрозрачная» void Gradient(); // «Градиентная» void DiagCross(); // «Сетка» p rivate: Ui::MainWindow *ui; }; #endif // MAINWINDOW_HТема: «Графические элементы и строки состояния»
Пример 1: программа, которая вписывает N-угольник в окружность. При соединении вершин их можно проходить с шагом M, например через две или через три. Окружность задается двумя щелчками мыши (в центре и на окружности). Числа N и M считываются с клавиатуры в главном окне.Создайте проект на основе класса QMainWindow. Щелкните по центру заготовки окна и в свойствах окна (MainWindow) измените свойство palette : сделайте двойной щелчок справа от этого слова и в появившемся окне Edit Palette найдите в списке Window (это свойство определяет цвет поверхности окна). Сделайте двойной щелчок справа от этого слова, появиттся окно Select Color. Выберите белый цвет окна. Закройте окна, щелкнув по кнопке OK.
Запустите программу и посмотрите как выглядит окно.
Вставьте в файл main.cpp код, показанный ниже:
#include
#include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.resize(400,400); // задаем размер окна w.move(450,250); // перемещаем окно в центр экрана w.show(); return a.exec(); }
Вставьте в объявление класса MainWindow (файл mainwindow.h) объявления переменных:
int n, m; // количество вершин многоугольника и шаг прохождения через вершины QPoint p[2]; // точки, по которым мы щелкаем мышью int counter; // счетчик щелчков мышью QString str; // строка, которая хранит задаваемые числа bool flag; // признак окончания ввода QLabel *label1, *label2; // панели для строки состояния double koef; // масштабный коэффициент для перевода радиуса в см Добавьте сюда же объявления функций: void paintEvent(QPaintEvent *); // эта функция автоматически вызывается при перерисовке окна void mousePressEvent(QMouseEvent *); // вызывается при нажатии кнопки мыши void keyPressEvent(QKeyEvent *); // вызывается при нажатии клавиши на клавиатуре
Вставьте в файл mainwindow.cpp код, показанный ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include
Пример 2: программа, в которой используется область отсечения QRegion и котекстное меню для выбора способа заливки этой области.
Создайте проект на основе класса QMainWindow. Добавьте в класс MainWindow (файл mainwindow.h) объявления данных и функций:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include
Вставьте в файл mainwindow.cpp определения функций как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // обеспечиваем использование кириллицы: QTextCodec* codec = QTextCodec::codecForName("Utf-8"); QtextCodec::setCodecForCStrings(codec); contextMenu = new QMenu(this); // создаем контекстное меню // Действия для контекстного меню: QAction* actSolid = new QAction("Сплошная", this); contextMenu->addAction(actSolid); connect(actSolid, SIGNAL(triggered()), this, SLOT(Solid())); contextMenu->addSeparator(); QAction* actSemitransparent = new QAction("Полупрозрачная", this); contextMenu->addAction(actSemitransparent); connect(actSemitransparent, SIGNAL(triggered()), this, SLOT(Semitransparent())); contextMenu->addSeparator(); QAction* actGradient = new QAction("Градиентная", this); contextMenu->addAction(actGradient); connect(actGradient, SIGNAL(triggered()), this, SLOT(Gradient())); contextMenu->addSeparator(); QAction* actDiagcross = new QAction("Сетка", this); contextMenu->addAction(actDiagcross); connect(actDiagcross, SIGNAL(triggered()), this, SLOT(DiagCross())); brush = QBrush(Qt::darkGreen); // начальный цвет кисти diagcross = false; // в начале заливка - сплошная } MainWindow::
Зарисовать окно «пчелиными сотами» (правильными шестиугольниками). Процесс зарисовки начинается при нажатии одной из кнопок мыши. Размер стороны шестиугольника - 1/n – ая часть длины меньшей стороны окна. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. В строке состояния вывести длину стороны шестиугольника и общее количество сот.
Окружность разделить на N равных частей. Соединить все точки разбиения хордами. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя! Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр окружности и одну точку, принадлежащую окружности, отметить нажатием левой кнопки мыши. В строке состояния вывести радиус окружности и длину хорды в точках и см.
Каждую сторону квадрата разделить на N равных частей. Соединить все точки разбиения, включая вершины, отрезками. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя! Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, принадлежащую стороне квадрата, отметить нажатием левой кнопки мыши. В строке состояния вывести координаты центра квадрата и длину стороны квадрата в точках и см.
Каждую сторону равностороннего треугольника разделить на N равных частей. Соединить все точки разбиения, имеющие одинаковые номера, отрезками вписав, таким образом, N треугольников в исходный треугольник. Число разбиений N ввести с клавиатуры. Диалоговое окно использовать нельзя!Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр треугольника отметить нажатием левой кнопки мыши. Длину стороны взять максимально возможную для отмеченной точки, но чтобы треугольник не выходил за пределы окна. В строке состояния вывести координаты центра треугольника и длину его стороны в точках и см.
Каждую сторону прямоугольника разделить на N равных частей. Соединить все точки разбиения, имеющие одинаковые номера, отрезками вписав, таким образом, N четырехугольников в исходный прямоугольник. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! Центр прямоугольника и одну из его вершин отметить нажатием левой кнопки мыши. В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
Построить на экране дисплея произвольный прямоугольник, фиксируя его центр и одну из вершин с помощью кнопки мыши. Заштриховать внутреннюю область прямоугольника прямоугольной сеткой (горизонтальными и вертикальными отрезками, параллельными сторонам прямоугольника). Расстояние между линиями штриховки – 1/n – ая часть длины меньшей стороны прямоугольника. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
Построить на экране дисплея произвольный прямоугольник, фиксируя его центр и одну из вершин с помощью кнопки мыши. Заштриховать внутреннюю область прямоугольника наклонной сеткой (отрезками с наклоном 45 и 135 градусов). Расстояние между линиями штриховки – 1/n – ая часть длины меньшей стороны прямоугольника. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра прямоугольника и длины его сторон в точках и см.
На экране дисплея построить правильный N-угольник, вписанный в окружность. Число N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр многоугольника и одну точку на окружности зафиксировать с помощью кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра окружности и площадь N-угольника в точках и см2.
Окружность разделить на N равных частей. Из каждой точки разбиения, как из центра, провести окружность радиусом, равным половине радиуса исходной окружности. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр окружности и одну точку, принадлежащую окружности, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра исходной окружности и площадь одной маленькой окружности в точках и см2.
Каждую сторону квадрата разделить на N равных частей. Из каждой точки разбиения, включая вершины, как из центра, провести окружность радиусом, равным расстоянию от точки до центра квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, лежащую на стороне квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
Каждую сторону квадрата разделить на N равных частей. Каждую точку разбиения, включая вершины, соединить с центром квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
Каждую сторону квадрата разделить на N равных частей. Соединить симметричные точки разбиения, лежащие на противоположных сторонах квадрата. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
Каждую сторону квадрата разделить на N равных частей. Соединить точки разбиения, лежащие на смежных сторонах квадрата и имеющие одинаковые номера. Число разбиений N ввести с клавиатуры. Обеспечить контроль правильности ввода и возможность стирания символов, которые введены ошибочно. Центр квадрата и одну точку, являющейся вершиной квадрата, отметить нажатием левой кнопки мыши. Диалоговое окно использовать нельзя! В строке состояния вывести координаты центра квадрата и его площадь в точках и см2.
Отредактируйте файл mainwindow.cpp как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" #include
Пример 2: программа, которая рисует окружности с помощью мыши (окружность видима в процессе построения). Нарисованные окружности можно сохранить в файле и загрузить из файла.
Создайте проект на основе главного окна и задайте белый цвет фона в свойствах этого окна.
По аналогии с предыдущим примером мы будем запоминать нарисованные окружности в списке. Но для того, чтобы использовать такие списки нам нужно определить класс, описывающий окружности.
Щелкните в окне, описывающем структуру проекта (слева), по имени проекта правой кнопкой мыши и в появившемся контекстном меню выберите Add New...
В появившемся диалоговом окне выберите С++ | C++ Class. Задайте имя класса Circle и завершите создание класса. К проекту будут добавлены файлы circle.h и circle.cpp, содержащие описание нашего класса.
Для описания окружности мы будем использовать координаты центра, радиус и цвет окружности. Хранить в списках можно только такие объекты, для которых определены конструктор по умолчанию, конструктор копирования и оператор присваивания. Кроме того нам потребуется основной коструктор.
Отредактируйте файл circle.h как показано ниже:
#ifndef CIRCLE_H #define CIRCLE_H #include
Отредактируйте файл circle.cpp как показано ниже:
#include "circle.h" Circle::Circle() { p = QPoint(0,0); r = 0; color = Qt::darkCyan; } Circle::Circle(QPoint &_p, int _r, QColor col = Qt::darkCyan) { p = _p; r = _r; color = col; } Circle::Circle(const Circle & circle) { p = circle.p; r = circle.r; color = circle.color; } Circle& Circle::operator =(const Circle & circle) { p = circle.p; r = circle.r; color = circle.color; return *this; }
Перейдите к редактированию дизайна окна. Добавьте в меню команду Файл.
В выпадающее меню добавьте действия: Открыть (actionOpen), Сохранить (actionSave) и Выход (actionQuit). Определите акселераторы для этих действий. Свяжите нажатие кнопки «Выход» со слотом close() главного окна.
Добавьте в меню команду Редактирование. В выпадающее меню добавьте действия: Выбрать цвет (actionColor), Отменить (actionAnnul), Очистить (actionClear).
Отредактируйте файл mainwindow.h как показано ниже:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include
Отредактируйте файл mainwindow.cpp как показано ниже:
#include "mainwindow.h" #include "ui_mainwindow.h" /* Для того, чтобы можно было сохранить список окружностей, нужно научить программу сохранять каждый объект класса Circle: */ QDataStream& operator <<(QDataStream& ostream, const Circle& c) { ostream << c.p.x()<< c.p.y() << c.r << c.color ; return ostream; } // Описываем, как считывать из потока каждый объект класса circle: QDataStream& operator >> (QDataStream& istream, Circle& c) { int x, y; istream >> x >> y >> c.r >> c.color; c.p.setX(x); c.p.setY(y); return istream; } MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // связываем сигналы от команд меню с соответствующими слотами: connect(ui->actionAnnul, SIGNAL(triggered()), this, SLOT(Annul())); connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(Clear())); connect(ui->actionColor, SIGNAL(triggered()), this, SLOT(showDialog())); connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(save())); connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(open())); // инициализируем элементы данных класса MainWindow: drawMode = false; p[0] = p[1] = QPoint(0,0); r = 0; color = Qt::darkCyan; } MainWindow::