Файл: Лабораторная работа 3 20 Тема Ипользование вспомогательных функций и вывод нескольких чисел c помощью одного элемента управления 20.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 18.03.2024

Просмотров: 54

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

СОДЕРЖАНИЕ

Тақырып: «Qt жасаушы ортасына кіріспе. Қарапайым диалогтық қолданбалар» 31-мысал: екі нақты санның бөлінуінен нақты қалдықты есептейтін бағдарлама 52-мысал: санның квадрат түбірін табатын бағдарлама. 93-мысал: стандартты сигналдар мен слоттарды қолдануды суреттейтін бағдарлама. 104-мысал: Арифметикалық өрнектің мәнін бағалайтын бағдарлама 12Өз бетінше орындауға арналған тапсырмалар 14№2 зертханалық жұмыс 14Тақырыбы: «Бағдарламаны жөндеу» 14Бағдарлама кезең-кезеңімен орындау 16Өз бетінше орындауға арналған тапсырмалар 17Лабораторная работа № 3 20Тема: «Ипользование вспомогательных функций и вывод нескольких чисел c помощью одного элемента управления» 20Пример 1: программа, которая находит заданное количество совершенных чисел, и выводит их на экран с помощью элемента textEdit 20Пример 2: программа, которая выводит значения функции на заданном отрезке с помощью списка listWidget 22Задания для самостоятельного выполнения 24Лабораторная работа № 4 27Тема: «Работа со строками» 27Пример 1: программа, которая переводит число из 16-ой системы в 10-ую. При вводе выполняется проверка вводимых символов. 27Пример 2: программа, которая считывает строку символов, состоящую из русских букв, запятых и пробелов и выводит на экран множество символов этой строки. 28Пример 3: программа, которая считывает текст из элемента tetxEdit и выводит в столбик числа, содержащиеся в тексте с помощью другого элемента типа textEdit. 29Задания для самостоятельного выполнения 30Лабораторная работа № 5 33Тема: «Главные окна. Меню. Работа с файлами» 33Пример 1: программа, которая считывает текст из файла и выводит его в главном окне; используется файл ресурсов. 33Пример 2: программа, которая считывает текст из файла и половину строк переписывает в другой файл; используются специальные окна для работы с файлами. 38Пример 3: программа, которая считывает текст из файла и подсчитывает количество видимых символов и количество русских букв. 40Пример 4: программа, которая считывает текст из файла и переписывает в другой файл строки, заменяя одну последовательность символов на другую; cимволы задают с помощью специального диалогового окна, появляющегося при нажатии кнопки на панели инструментов. 42Задания для самостоятельного выполнения 45Лабораторная работа № 6 48Тема: «Графические элементы и строки состояния» 48Пример 1: программа, которая вписывает N-угольник в окружность. При соединении вершин их можно проходить с шагом M, например через две или через три. Окружность задается двумя щелчками мыши (в центре и на окружности). Числа N и M считываются с клавиатуры в главном окне. 48Пример 2: программа, в которой используется область отсечения QRegion и котекстное меню для выбора способа заливки этой области. 53Задания для самостоятельного выполнения 58Лабораторная работа № 7 61Пример 1: программа, которая рисует траектории движения мыши при нажатой левой кнопке выбранным цветом и стирает рисунок при щелчке правой кнопкой мыши. 61Пример 2: программа, которая рисует окружности с помощью мыши (окружность видима в процессе построения). Нарисованные окружности можно сохранить в файле и загрузить из файла. 63Задания для самостоятельного выполнения 68Лабораторная работа № 8 72Тема: «Области отсечения» 72Пример 1: программа, которая рисует 6-угольник, цвет которого можно изменять с помощью немодального диалогового окна с наборными счетчиками (Spin). Диалоговое окно появляется при нажатии кнопки «Диалог». 72Пример 2: программа, которая расчерчивает окно правильными 6-угольниками («пчелиными сотами»); размер шестиугольника — 1 / 5 меньшей стороны окна (но не меньше 2); при щелчке мышью внутри шестиугольника, он закрашивается цветом, выбранным с помощью специального окна для выбора цвета. 76Задания для самостоятельного выполнения 81Лабораторная работа № 9 84Тема: «Работа с массивами с помощью класса QVector» 84Пример: программа считывает массив неотрицательных чисел из файла, выводит его на экран, используя полосы прокрутки, и рисует круговую диаграмму для 13 самых больших элементов, отображая остальные в сумме. 84Задания для самостоятельного выполнения 87 Тақырып: «Qt жасаушы ортасына кіріспе. Қарапайым диалогтық қолданбалар» Ubuntu ортасына өтіп, applications|Programming|Qt Creator мәзірінен таңдаңыз. Qt Creator бағдарламалау ортасының терезесі пайда болуы керек.Экранның орталық бөлігінде жобаны таңдау үшін «Qt Creator» терезесі пайда болады (жоба - бұл мәселені шешуге арналған бағдарламасы бар орындалатын файлды жасауға арналған файлдар жиынтығы). Бұл терезеде «жобаны жасау» түймесін басыңыз. «New Project» терезесі пайда болады (келесі бетті қараңыз). Бұл терезеде әдепкі параметрлерді қалдырыңыз және түймесін басыңыз Келесі «Qt Gui Application» терезесінде «Name» жолында жобаның атын көрсетіңіз, мысалы: ФИО жазу . Жобаның аты латын әріптерімен жазылуы керек. Зертханалық жұмыстың тапсырмасын орындау үшін жоба құратын студенттер жобаның атауына өздерінің фамилияларын (латын әріптерімен жазылған) қамтуы керек. < Next > түймесін басыңыз.Base class тізіміндегі келесі «Class Information» терезесінде QDialog таңдаңыз, қалған қондырғыларды әдепкі бойынша қалдыруға болады, содан кейін Dialog класы бағдарламаның негізгі терезесін сипаттайды. <Next> түймесін басыңыз. Келесі терезеде жоба жасалған каталог және жобаны құрайтын файлдардың тізімі берілген. батырмасын басыңыз.Бағдарлама терезесінің көрінісін жобалау үшін редактор терезесі пайда болады. . Орталық бөлігінде терезе бос, сол жақта — басқару элементтерінің панелі, оң жақта-панельге қосылған элементтер тізімі және таңдалған элементтің қасиеттері терезесі1-мысал: екі нақты санның бөлінуінен нақты қалдықты есептейтін бағдарлама Суретте көрсетілген бағдарлама терезесін жасаңыз. Жазулар жасау үшін «Display Widgets» бөліміндегі басқару элементтері тақтасында орналасқан белгі (белгі) элементін жіберіңіз. Басқару элементтерінің тізімі ұзақ, сондықтан қалаған бөлімді табу үшін айналдыру жолағын пайдаланыңыз. Қажетті элементті табуды жеңілдету үшін басқару элементтері панелінің жоғарғы жағында орналасқан «Filter» жолын пайдалануға болады; осы жолға «Lab» теріңіз және label элементін табу оңайырақ болады. Басқару элементтері тышқанмен тілқатысу тақтасына сүйретіп қою (сол жақ батырманы басу арқылы). Жапсырманы тілқатысу тақтасына үш рет сүйреп апарыңыз және оларды сол жақта бағанға орналастырыңыз. Жазба жасау үшін қажетті элементті екі рет нұқыңыз. Суретте көрсетілгендей жазулар жасаңыз. Бастапқы деректерді енгізу және нәтижелерді шығару үшін біз бір жолды мәтіндік редактормен байланысқан элементтерді қолданамыз: «Line Edit». Әр жазудың оң жағында осы элементтерді орналастырыңыз Қажетті әрекеттерді орындау үшін екі түймені басыңыз. Оларды тілқатысу тақтасының оң жағына орналастырыңыз. Суретте көрсетілгендей оларға жазулар жасаңыз. Экранның оң жағында орналасқан сипаттар терезесінде басқару элементі үшін мәтінді туралаудың қажетті әдісін орнатуға болады. Тінтуірдің көмегімен барлық элементтерді таңдаңыз LineEdit және alignment бөліміндегі қасиеттер терезесінде Horizontal жолында AlignHCenter таңдаңыз (Көлденең туралау: ортасында). Барлық басқару элементтерін бір-біріне қатысты туралау үшін Layout деп аталатын элементтер қолданылады. Vertical — баған түрінде туралау үшін, Horizontal — жол түрінде, Grid — кесте түрінде, Form — екі бағаннан тұратын кесте түрінде. Барлық элементтерді бөлектеңіз ( + ) және көлденең құралдар тақтасында (негізгі мәзірдің астында) түймесін басыңыз < Lay Out in a Grid > (батырманың атауын тінтуір меңзерін ұстап тұрғанда көруге болады). Элементтер қызыл жақтаумен белгіленген торға қатысты тураланады. Бағдарлама мәтінін көру үшін бағдарламалау ортасының сол жақ жиегіндегі Edit түймесін басыңыз. Бөлім атауының сол жағында орналасқан үшбұрыштарды басу арқылы бөлім мазмұнын кеңейтіңіз (үшбұрыштар төменге бағытталуы керек). Файлды ашу үшін жасаңыз, қос түймешігін тінтуірмен атауын басыңыз. Dialog.cpp файлын ашыңыз. Төменде көрсетілгендей adjustSize() функциясын конструкторға қосыңыз. Бұл функция терезе өлшемін ең аз қажет етеді #include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); } Dialog::Dialog() { delete ui; } Бағдарлама қажетті әрекеттерді орындауы үшін бағдарламаға белгілі бір оқиғаларды өңдейтін функцияларды қосу керек. Мұндай функциялар слоттар (slot) деп аталады. Диалог тақтасы түрінің редакторына dialog.ui атауын екі рет басу арқылы Forms бөліміне оралыңыз. Тілқатысу тақтасындағы «Выход» түймесін тінтуірдің оң жақ түймесімен нұқыңыз және пайда болған контекстік мәзірден «go to slot» таңдаңыз. Пайда болған терезеде әдепкі параметрлерді қалдырыңыз және түймесін басыңыз. Функция clicked() сигналы пайда болған кезде шақырылады (осы батырманы басыңыз). Басқару элементтерінің атаулары автоматты түрде жасалады, ал элемент нөмірі диалог жолағына қандай ретпен қосылғанына байланысты болады. «Выход» батырмасын екінші рет қосылды деп болжанады, сәйкесінше оның идентификаторы pushButton_2 болады және осы батырманы басатын ұяшық on_pushButton_2_clicked () деп аталады. Төменде көрсетілгендей close() функциясын шақыру ұясының ішіне қосыңыз #include "dialog.h" #include "ui_dialog.h" #include Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); } Dialog::Dialog() { delete ui; } void Dialog::on_pushButton_2_clicked() { close(); } Орындалатын файлды жасаңыз (+) және бағдарламаны іске қосыңыз (+ ). Терезені <шығу > батырмасымен жабыңыз. Әрине, кез-келген терезені осы батырмасыз терезе тақырыбындағы крестті басу немесе пернетақтадағы + басу арқылы жабуға болады. «Қалдық» батырмасы үшін слот қосыңыз. Fmod () функциясы арқылы бөлінудің нақты қалдығын есептейміз. Бұл басқа математикалық функциялар math.h файлын қосуды қажет етеді (жоғарыдағы dialog.cpp файлының мәтінін қараңыз). Біздің бағдарламамыз тапсырманы шешуі үшін екі санды оқып, бөлудің қалған бөлігін есептеп, нәтижені көрсету керек. LineEdit элементтері таңбалар жолдарымен жұмыс істейді (мәтінмен), бірақ мәтінді арнайы функциялар арқылы санға және керісінше түрлендіруге болады. Нөмірді оқу үшін пернетақтада ui нысанының атын теріп, пернетақтадағы «нүкте» ('.') пернесін басу керек. Элемент идентификаторын таңдау керек тізім пайда болады (qlineedit). Тағы да нүктені нұқыңыз және мәтінді таңдаңыз. Осылайша, пайдаланушы терезеде терген мәтін жолын аламыз. Әрі қарай, нүктені қайтадан басып, жолды санға түрлендіру функциясын таңдау керек. Нәтижені көрсету үшін саннан Qstring класындағы number функциясын пайдаланып таңбалар жолын жасап, осы жолды үшінші терезеде көрсету керек. Нәтижесінде, біз төменде берілген функцияны алуымыз керек: void Dialog::on_pushButton_clicked() { double a = ui->lineEdit->text().toDouble(); double b = ui->lineEdit_2->text().toDouble(); double c = fmod(a, b); ui->lineEdit_3->setText(QString::number(c)); } Бағдарламаны іске қосыңыз және оның жұмысын тексеріңіз. Бірінші нөмірді енгізу терезесі бағдарламаны іске қосқан кезде бірден белсенді болуы керек. Ол үшін оның номері 1 болуы керек. Дұрыс номерлеуді орнату үшін терезені өңдеу режиміне өтіп, құралдар тақтасындағы түймесін басыңыз. Элементтер нөмірлерін нұқыңыз, суретте көрсетілгендей нөмірлеуді орнатыңыз. Деректерді енгізу кезінде нөмірлеуге сәйкес пернесін басқан кезде келесі терезеге өту жүзеге асырылуы тиіс. Нәтижені көрсету үшін терезеде теруге тыйым салынады, ол үшін Сипаттар терезесінде focusPolicy жолында NoFocus тізімінен таңдаңыз. Нөмірлеу режимінен шығу үшін құралдар тақтасындағы батырмасын басыңыз.Бағдарламаның жұмысын тағы бір рет тексеріп, жобаны жабыңыз (File | Close all projects).2-мысал: санның квадрат түбірін табатын бағдарлама. Б ағдарлама нақты санның теріс емес түбірін табады. Квадрат түбірді түбір өрнегі теріс емес болған жағдайда ғана есептеуге болады, сондықтан жарамсыз енгізілген мәнмен бағдарлама қате туралы хабарлама шығарады. Қате туралы хабарлама жеткілікті кең болуы мүмкін, сондықтан нәтижені шығару үшін мәтінді басқа жолға автоматты түрде жіберетін мәтін өңдеу элементін қолданамыз. Суретте көрсетілгендей тілқатысу терезесін жасаңыз. Сіз қосу керек элементтер: Label, Line Edit, Push Button және Text Edit. Жоғарғы үш элементті бөлектеу және Vertically түймесін басу арқылы туралаңыз. TextEdit оның өлшемдерін өзгерту үшін Layout-қа қоспаңыз.«Түбір» батырмасы үшін ұяшық жасаңыз және төменде көрсетілген кодты жазыңыз.#include "dialog.h" #include "ui_dialog.h" #include #include Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); // делаем размеры окна минимально-необходимыми } Dialog::Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); // 2 строчки, приведенные выше, позволяют выводить текст на русском языке double x = ui->lineEdit->text().toDouble(); // считываем число double y; if (x>=0) { y=sqrt(x); // извлекаем квадратный корень ui->textEdit->setText(QString::number(y,'f',5)); // выводим число с точностью 5 цифр после точки } else ui->textEdit->setText("Число должно быть >= 0"); // выводим сообщение об ошибке }Бағдарламаны іске қосыңыз және оның жұмысын жарамды және жарамсыз бастапқы деректер үшін тексеріңіз. Егер хабарлама мәтіні бір жолға сәйкес келсе, мәтінді басқа жолға қалай ауыстырылғанын көру үшін TextEdit терезесін жасаңыз. 3-мысал: стандартты сигналдар мен слоттарды қолдануды суреттейтін бағдарлама. Мысал ретінде енгізілген бүтінондық санды екілік немесе сегіздік немесе ондық немесе он алтылық түрінде көрсететін бағдарлама жасаймыз. Бұл сандарды сұйық кристалды экран ретінде көрсетуге арналған LCD Number элементімен оңай жасалады. QWidget класына негізделген жоба жасаңыз. Элементтерді қолдана отырып, суретте көрсетілгендей терезені жобалаңыз: Label, Line Edit, 4 Push Buttons, LCD Number.В свойствах LCD Number установите : segment Style : Flat, digitCount : 20 (количество сегментов экрана, т.е. максимальное количество отображаемых цифр). Чем больше задать количество цифр, тем они будут мельче).Задавать число мы будем с помощью элемента Line Edit. При изменениии числа в окне Line Edit должно изменяться значение в LCD Number. Для обеспечения этой связи можно использовать окно, которое располагается под проектом вида окна. Перейдите на вкладку Signals & Slots Editor и нажмите +. В список связей будет добавлена новая строка. Сделайте двойной щелчок в появившейся строке в первом поле . В появившемся списке выберите элемент lineEdit. Повторите эти действия в других полях так, чтобы связь была задана как показано на рисунке.Біз нөмірді Line Edit элементі арқылы орнатамыз. Line Edit терезесіндегі нөмірді өзгерткен кезде, LCD Number мән өзгеруі керек. Бұл қосылымды қамтамасыз ету үшін терезе көрінісі жобасының астында орналасқан терезені пайдалануға болады. Signals & Slots Editor қойындысына өтіп, + түймесін басыңыз. Сілтемелер тізіміне жаңа жол қосылады. Бірінші < sender > өрісінде пайда болатын жолды екі рет басыңыз. Пайда болған тізімде lineEdit элементін таңдаңыз. Қатынас суретте көрсетілгендей орнатылуы үшін осы қадамдарды басқа өрістерде қайталаңыз. Нәтижесінде, Line Edit элементінің мазмұны өзгерген кезде, LCD Number элементінің мазмұны автоматты түрде өзгереді. түймесі үшін ұяшықты қосыңыз және оған төменде көрсетілгендей кодты жазыңыз. Басқа түймелер үшін осы қадамдарды қайталаңыз.void Widget::on_pushButton_clicked() { ui->lcdNumber->setMode(QLCDNumber::Bin); // двоичное представление ui->lineEdit->setFocus(); } void Widget::on_pushButton_2_clicked() { ui->lcdNumber->setMode(QLCDNumber::Oct); // восьмеричное представление ui->lineEdit->setFocus(); } void Widget::on_pushButton_3_clicked() { ui->lcdNumber->setMode(QLCDNumber::Dec); // десятичное представление ui->lineEdit->setFocus(); } void Widget::on_pushButton_4_clicked() { ui->lcdNumber->setMode(QLCDNumber::Hex); // 16-е представление ui->lineEdit->setFocus(); } Бағдарламаны іске қосыңыз және қолданбаны тексеріңіз. Енді терезенің тақырып жолында «терезені кішірейту» түймесі бар екеніне назар аударыңыз (ол диалогтық терезеде болмаған), бірақ енді терезе экранның бұрышында пайда болады. main.cpp файлын ашыңыз және оны төмендегідей өңдеңіз. #include #include "widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.move(400,300); // перемещаем окно в центр экрана w.show(); return a.exec(); } Бағдарламаны іске қосыңыз.Жобаны жабыңыз. 4-мысал: Арифметикалық өрнектің мәнін бағалайтын бағдарлама Бұл бағдарлама бір басқару элементінен бірнеше кірісті қалай ағынмен жіберуге болатынын көрсетеді. Сонымен қатар, бағдарлама таңбаларды тексеру үшін switch операторын пайдалануды суреттейді. Суретте көрсетілгендей диалогтық терезені құрастырыңыз. Label, Line Edit, Push Button, Label и Text Edit қолдану.Белгі мәтінінің басқа жолға оралуы үшін wordWrap жолындағы Белгі сипаттарында құсбелгіні қойыңыз.Түйме ұясын жасаңыз және төменде кодты жазыңыз#include "dialog.h" #include "ui_dialog.h" #include // обеспечивает математические и многие другие функции #include // обеспечивает возможность использования кириллицы Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); } Dialog::Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); // обеспечили возможность вывода текста на русском языке double a, b; char op; QString str = ui->lineEdit->text(); // прочитали выражение QTextStream in(&str, QIODevice::ReadOnly); // преобразовали строку в поток символов in in >> a; // прочитали первое число do { in >> op; } while (op == ' '); // пропустили пробелы и прочитали знак операции in >> b; // прочитали второе число QString message; bool flag = true; double c=0; switch (op) // проверяем знак операции { case '+': c = a + b; break; case '-': c = a - b; break; case '*': c = a * b; break; case '/': if (b) c = a / b; else { flag = false; message = "Второе число должно быть не равно 0";} break; case '%': c = int(a) % int(b); break; case '^': if (finite(c = pow(a, b))); // проверяем возможность выполнения операции else {flag = false; message = "Первое число должно быть неотрицательным";} break; default: flag = false; message = "Неверный знак операции"; } if (flag) ui->textEdit->setText(QString::number(c)); else ui->textEdit->setText(message); } Өз бетінше орындауға арналған тапсырмалар 1. QDialog класы негізінде кез келген a, b, c үшін түріндегі квадрат теңдеуді шешетін бағдарламаны жазыңыз (программада 6 тармақ болуы керек).2.QWidget класы негізінде екі сызықтық теңдеулер жүйесін шешетін программа жазыңыз.Көрсеткіш: қараңыз: Касаткин С., Раткевич И., Травова Н.Н. «Microsoft Visual Studio 2005 бағдарламасындағы «Алгоритмдеу негіздері» курсы бойынша зертханалық практикум» №2 зертханалық жұмыс Тақырыбы: «Бағдарламаны жөндеу» Бағдарламада логикалық қатені табу үшін жөндеу туралы хабарламалардың шығысын пайдалануға болады, мысалы, аралық есептеулердің нәтижелерін көрсету.Мысал ретінде санның екінің дәрежесі екенін тексеретін программа құрайық. Аралық есептеулердің нәтижелерін көрсету үшін qDebug() ағынын шығару операторын қолданамыз. Бұл операторды пайдалану ағынды шығару cout пайдалануына ұқсас Диалогтық терезе негізінде жоба құрыңыз және оны суретте көрсетілгендей құрастырыңыз.Бірінші терезеде әдепкі бойынша идентификатор бар lineEdit, екінші — lineEdit_2.«Тексеру» түймесі үшін слот жасаңыз және төменде көрсетілгендей кодты жазыңыз.#include "dialog.h" #include "ui_dialog.h" #include // Обеспечивает работу qDebug() #include // Обеспечивает спользование кириллицы #include // Обеспечивает работу математических функций #include // Обеспечивает использование окна сообщений Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); // } Dialog::

Тема: «Ипользование вспомогательных функций и вывод нескольких чисел c помощью одного элемента управления» Пример 1: программа, которая находит заданное количество совершенных чисел, и выводит их на экран с помощью элемента textEdit Совершенными называются числа, которые равны сумме всех своих делителей, не включая само число, например: 6 = 1+2+3.Для решения задачи будем проверять все натуральные числа, начиная с 1 (но 1 не считается совершенным числом). Совершенных чисел совсем не много, поэтому, чтобы не ждать слишком долго окончания выполнения программы, ограничим поиск числом 104.С оздайте проект на базе класса QDialog.Спроектируйте окно программы как показано на рисунке. В качестве элемента для вывода результата используем элемент textEdit.Для проверки одного числа добавим в класс, описывающий окно программы, объявление функции IsPerfect(). Передите в режим редактирования программы (Edit) и откройте файл dialog.h. Вставьте в класс Dialog объявление функции:bool IsPerfect(int); Откройте файл dialog.cpp и напишите определение функции. Файл должен выглядеть так, как показано ниже. #include "dialog.h" #include "ui_dialog.h" #include Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); adjustSize(); } Dialog::Dialog() { delete ui; } bool Dialog::IsPerfect(int n) { int sum = 0; // проверяем все возможные делители: for (int del = 1; del <= n/2; ++del ) if (n % del == 0) sum += del; // если проверяемое число делится на очередной делитель, добавляем его к сумме if (n == sum) return true; return false; } Добавьте слот для кнопки «Найти » и напишите код, показанный ниже. void Dialog::on_pushButton_clicked() { QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); int kol = ui->lineEdit->text().toInt(); // считали нужное количество int counter = 0; // количество уже найденных чисел int m = 1; // проверяемое число QString text= "Совершенные числа:\n"; while (counter < kol) // пока не найдено нужное количество чисел { if (IsPerfect(m)) // если очередное число - совершенное { text += QString::number(m)+'\n'; /* выполняем преобразование числа в строку и добавляем к тексту (и символперехода на новую строку) */ counter++; // увеличиваем счетчик } m++; // берем следующее число if (m > 1e4) // если число стало слишком большим { text += "Поиск закончен"; break; } } ui->textEdit->setText(text); // выводим текст в окно } Пример 2: программа, которая выводит значения функции на заданном отрезке с помощью списка listWidget С проектируйте окно как показано на рисунке. Нижний элемент — listWidget.Перейдите в режим Edit.Откройте файл dialog.h и напишите в классе Dialog объявление функции:double f(double);Откройте файл dialog.cpp и напишите определение функции как показано ниже:#include "dialog.h" #include "ui_dialog.h" #include #include Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); } Dialog::

Лабораторная работа № 4

Тема: «Работа со строками» П ример 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::

Тема: «Главные окна. Меню. Работа с файлами» Пример 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::

Тема: «Графические элементы и строки состояния» Пример 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::

Тема: «Области отсечения» Пример 1: программа, которая рисует 6-угольник, цвет которого можно изменять с помощью немодального диалогового окна с наборными счетчиками (Spin). Диалоговое окно появляется при нажатии кнопки «Диалог». Создайте проект на базе главного окна.Д обавьте дочернее диалоговое окно, описываемое классом Dialog (выберите в меню Файл | Новый файл или проект... , в появившемся диалоговом окне выберите Qt | Класс формы Qt Designer).Спроектируйте окно как показано на рисунке, добавив элемент spinBox.В файл main.cpp добавьте подчеркнутую строку:int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.move(400, 250); // перемещает окно к центру экрана w.show(); return a.exec(); }В файлe dialog.h в описание класса добавьте подчеркнутые строки:#ifndef DIALOG_H #define DIALOG_H #include namespace Ui { class Dialog; } class MainWindow; // С помощью этого класса объявим указатель на родительское окно class Dialog : public QDialog { Q_OBJECT public: // Измените тип указателя на MainWindow explicit Dialog(MainWindow *parent = 0); Dialog(); MainWindow* Parent; /* С помощью этого указателя диалоговое окно будет передавать новое значение цвета главному окну */ // объявление слота, который будет передавать новое значение цвета главному окну: publicslots: voidsetN(int); private: Ui::Dialog *ui; }; #endif // DIALOG_HВ файл dialog.cpp добавьте подчеркнутые строки:#include "dialog.h" #include "ui_dialog.h" #include "mainwindow.h" // обеспечивает возможность использования класса MainWindow Dialog::Dialog(MainWindow*parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); ui->spinBox->setRange(0, 255); // Задаем диапазон изменнения значений наборного счетчика ui->spinBox->setSingleStep(5); // при щелчке по стрелочке значение счетчика будет изменяться на 5 Parent = parent; // Указатель, объявленный в классе, становится равным значению локального указателя ui->spinBox->setValue(Parent->n); /* Устанавливаем начальное значение счетчика так, чтобы оно было равно начальному значению цвета, установленного в конструкторе главного окна */ connect(ui->spinBox, SIGNAL(valueChanged(int)), this, SLOT(setN(int))); /* связываем сигнал об изменении значения счетчика со слотом, который передает новое значение цвета главному окну */ } Dialog::Dialog() { delete ui; } void Dialog::setN(int n) /* значение n автоматически передается слоту от наборного счетчика с помощью сигнала valueChanged(int) { Parent->n = n; // передаем значение цвета переменной, объявленной в классе гланого окна Parent->update(); // посылаем сигнал «перерисовать окно» }Добавьте в файл mainwindow.h подчеркнутые строки:#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include "dialog.h" // Обеспечивает возможность использования класса Dialog #include // обеспечивает возможность использования графических функций namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); MainWindow(); void paintEvent(QPaintEvent *); // функция, которая автоматически вызывается при перерисовывании окна Dialog* dlg; // объект, описывающий диалоговое окно int n; // значение яркости цвета private: Ui::MainWindow *ui; private slots: void on_actionDialog_triggered(); }; #endif // MAINWINDOW_HВ режиме проектирования формы с помощью редактора действий добавьте действие actionDialog с текстом «Диалог» (это будет командой меню, которая вызывает вспомогательное диалоговое окно).В файл mainwindow.cpp добавьте код, показанный ниже:#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); n = 100; // начальное значение цвета dlg = new Dialog(this); // создаем объект класса Dialog ui->menuBar->addAction(ui->actionDialog); // В меню создаем кнопку, соответствующую команде «Диалог» (без выпадающего меню) } MainWindow::MainWindow() { delete ui; } // В режиме проектирования формы добавьте слот для действия actionDialg: void MainWindow::on_actionDialog_triggered() { dlg->move(400+width(), 250); // размещаем диалоговое окно на правой границе главного окна dlg->show(); // рисуем окно на экране dlg->activateWindow(); // делаем диалоговое окно активным } // Описываем, что нужно нарисовать в окне void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this);// Объект для рисования QString str = QString::number(n);/* Строка, с помощью которой на экране будет отображаться текущая яркость цвета */ painter.drawText(20,70, str);// Отображаем на экране значение яркости цвета QBrush brush(QColor(n,0,0));/* объявляем кисть, число n в данном случае будет опреелять яркость красного цвета */ painter.setBrush(brush);// побключаем кисть QPolygonF polygon; // Объявляем многоугольник qreal r = 100; // радиус окружности, в которую будет вписан многоугольник qreal x0 = 200, y0 = 150; // центр окружности qreal dfi = M_PI / 3; // угол между вершинами 6-угольника for (int i = 0; i< 6; ++i) // рисуем 6-угольник { qreal fi = dfi * i; // угол, соответствующий очередной вершине // определяем координаты вершины qreal x = x0 + r*cos(fi); qreal y = y0 + r*sin(fi); polygon << QPointF(x,y);// добавляем координаты вершины к полигону } painter.drawPolygon(polygon);// рисуем многоугольник (6-угольник) } Пример 2: программа, которая расчерчивает окно правильными 6-угольниками («пчелиными сотами»); размер шестиугольника — 1 / 5 меньшей стороны окна (но не меньше 2); при щелчке мышью внутри шестиугольника, он закрашивается цветом, выбранным с помощью специального окна для выбора цвета. Создайте приложение на базе главного окна. В файле mainwindow.h добавьте объявления как показано ниже.#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #define maxR 500 // максимальное количество строк #define maxC 700 // максимальное количество столбцов namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); MainWindow(); void paintEvent(QPaintEvent *); // автоматически вызывается при перерисовке окна void createMatrices(); // функция, размещающая в памяти матрицы полигонов и регионов void createNet(); // формирование сетки в рабочей области окна void createPolygon(int, int); // создание одной ячейки с заданными номерами void mousePressEvent(QMouseEvent *); // автоматически вызыватся при щелчке мышью void resizeEvent(QResizeEvent *); // автоматически вызывается при создании окни и при изменении его размеров QPolygon** Polygon; // Указатель на матрицу полигонов QRegion** Region; // Указатель на матрицу областей QColor Color[maxR][maxC]; /* матрица для хранения цвета в каждой ячейке, она должна быть максимальных размеров, поскольку мы заранее не знаем размеры окна */ int previousRows, rows, columns; /* количество строк для предыдущего состояния окна, текущее количество строк, количество столбцов */ double w, h; // размеры рабочего поля double size, x0, y0, r; // размер одной ячейки, центр и радиус окружности, в которую вписан многоугольник QBrush brush; // кисть private: Ui::MainWindow *ui; private slots: void on_actionOpen_triggered(); void on_actionSave_triggered(); }; #endif // MAINWINDOW_HВ файле mainwindow.cpp напишите код, показанный ниже:#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); for (int i = 0; i < maxR; ++i) for (int j = 0; jMainWindow() { delete ui; } // Виртуальная функция, которая вызывается при изменении размеров окна void MainWindow::resizeEvent(QResizeEvent * ) { w = width(); // ширина рабочего поля y0 = centralWidget()->y(); // Верхняя граница клиентской области h = height() - y0; // высота рабочего поля size = qMin(w, h) / 5; // размер одной ячейки (расстояние между двумя противоположными вершинами) if (size<2) size = 2; // размер не может оказаться равным нулю, чтобы не произошло деление на ноль // qDebug() << "size = " << size; r = size/2; // радиус окружности, в которую вписана ячейка x0 = r * sqrt(3)/2; // расстояние от левой границы окна до центра первого 6-угольника (красная линия на рисунке) /* длина стороны правильного 6-угольника = r, а расстояние между ценрами ячеек (вертикальный катет светлого треугольника) = r+r/2 = 3*r / 2 */ rows = int(2*h/(3*r)) +2; // количество полных рядов равно частному от деления высоты рабочей области на расстояние между центрами ячеек; к этому количеству нужно добавить 2 — неполные ряды на верхней и нижней границах окна if (rows>maxR) rows = maxR; // но количество рядов не может превышать задданый максимум // qDebug() << "rows = " << rows; columns = int(w / (r*sqrt(3)))+2; /* расстояние между центрами окружностей по горизонтали = (r*sqrt(3)/2) * 2 = r*sqrt(3), количество столбцов равно частному от деления ширины окна на расстояние между рядами + 2 неполных ряда на левой и правой границе */ if (columns>maxC) columns = maxC; // количество столбцов неможет превышать заданный максимум // qDebug() << "columns = " < void MainWindow::paintEvent(QPaintEvent * ) { QPainter painter(this); // рисуем многоугольники цветом, который записан в матрице цветов: for (int i = 0; i < rows; ++i) for (int j = 0; j < columns; ++j) { painter.setBrush(QBrush(Color[i][j])); painter.drawPolygon(Polygon[i][j]); } } // размещаем матрицы в памяти: void MainWindow::createMatrices() { if (previousRows) // удаляем предидущие матрицы из памяти, если они ненулевого размера { for (int i = 0; i < previousRows; ++i) // освобождаем память по строкам { delete[] Polygon[i]; // освобождаем память, выделенную для данных delete[] Region[i]; } delete Polygon; // удаляем массивы указателей delete Region; } previousRows = rows; // запоминаем текущее количество строк // создаем массивы указателей на строки данных: Polygon = new QPolygon* [rows]; Region = new QRegion* [rows]; // захватываем память для строк данных: for (int i = 0; i < rows; ++i) { Polygon[i] = new QPolygon[columns]; // для координат 6-угольников Region[i] = new QRegion[columns]; // для областей } } void MainWindow::createNet() // заполняем матрицы данными { double dx = r*sqrt(3); // расстояние между центрами ячеек по горизонтали double dy = r*3 / 2; // расстояние между центрами ячеек по вертикали for (int i = 0; i pos(); // координаты курсора мыши // проверяем, в какой регион (в какой 6-угольник) попадает курсор мыши for (int i = 0; i> Color[i][j]; // считываем цвет ячейки file.close(); } /* Главное окно приложения автоматически перерисовывается при закрытии окна для выбора файла */ } Задания для самостоятельного выполнения Создать приложение, которое расчерчивает окно правильными шестиугольниками (размер – 1/20 высоты окна) и при щелчке мышью в шестиугольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой ячейке пользователь щелкнул мышью, выполнять с помощью областей QRegion! 2. Создать приложение, которое расчерчивает окно косой сеткой (линиями под углом 45 градусов, расстояние между линиями – 1/20 высоты окна) и при щелчке мышью в ромбе закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой ячейке пользователь щелкнул мышью, выполнять с помощью областей QRegion!3. Создать приложение, которое расчерчивает окно прямоугольной сеткой (линиями, параллельными сторонам окна, расстояние между линиями – 1/20 меньшей стороны окна) и при щелчке мышью в прямоугольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой ячейке пользователь щелкнул мышью, выполнять с помощью областей QRegion!4. Создать приложение, которое заполняет окно несколькими рядами окружностей (радиус окружности – 1/20 меньшей стороны окна) и при щелчке мышью в окружности закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой окружности пользователь щелкнул мышью, выполнять с помощью областей QRegion!5. Создать приложение, которое заполняет окно несколькими рядами равносторонних треугольников (высота треугольника - 1/10 высоты окна) и при щелчке мышью в треугольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в каком треугольнике пользователь щелкнул мышью, выполнять с помощью областей QRegion!6. Создать приложение, которое заполняет окно несколькими рядами вертикально стоящих ромбов (высота ромба в 2 раза больше ширины) и при щелчке мышью в ромбе закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в каком ромбе пользователь щелкнул мышью, выполнять с помощью областей QRegion!7. Создать приложение, которое заполняет окно несколькими рядами правильных 5-угольников (выпуклых) и при щелчке мышью в 5-угольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в каком 5-угольнике пользователь щелкнул мышью, выполнять с помощью областей QRegion!8. Создать приложение, которое заполняет окно несколькими рядами пятиконечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!9. Создать приложение, которое заполняет окно несколькими рядами 6-конечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!10. Создать приложение, которое заполняет окно несколькими рядами 7-конечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!11. Создать приложение, которое заполняет окно несколькими рядами 8-конечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion! Лабораторная работа № 9 1   2   3   4   5   6   7

Тема: «Работа с массивами с помощью класса QVector» Пример: программа считывает массив неотрицательных чисел из файла, выводит его на экран, используя полосы прокрутки, и рисует круговую диаграмму для 13 самых больших элементов, отображая остальные в сумме. Создайте проект на базе главного окна. Добавьте класс Pole, производный от QWidget. В главном окне создадим область прокрутки и поместим в эту область поле, на котором выведем массив и отображающую его круговую диаграмму.В меню главного окна добавьте меню File и действие Open.В файл mainwindow.cpp добавьте показанный ниже код.#include "mainwindow.h" #include "ui_mainwindow.h" #include "pole.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); QScrollArea* scroll = new QScrollArea(this); // создаем область прокрутки Pole* pole = new Pole(scroll); // создаем новый виджет scroll->setWidget(pole); // размещаем виджет в области прокрутки setCentralWidget(scroll); // делаем область прокрутки рабочей областью окна connect(ui->actionOpen, SIGNAL(triggered()), pole, SLOT(fileOpen())); // связываем вызов команды File|Open со слотом, который мы создадим в классе Pole } MainWindow::

::const_iterator it = DrawBuffer.begin(); // итератор для прохода по списку do { Circle c = *it++; painter.setPen(c.color); painter.drawEllipse(c.p, c.r, c.r); } while (it!= DrawBuffer.end()); // рисуем окружности, пока список не закончится } /* рисуем текущую окружность: окружность изменяется в зависимости от движения мыши, поэтому мы ее будем рисовать отдельно в объекте pixmap и накладывать этот объект на окно, тогда не нужно стирать предыдущий вид этой окружности */ if (drawMode) // если прижата левая кнопка мыши { // определяем размеры области рисования: int w = width(); int h = height()-(ui->statusBar->height()); QPixmap pixmap(w, h); // создаем область, в которой мы будем рисовать текущую окружность pixmap.fill(Qt::transparent); // делаем фон прозрачным QPainter pntPixmap(&pixmap); // создаем объект для рисования pntPixmap.setRenderHint(QPainter::Antialiasing); // сглаживание pntPixmap.setPen(color); /* устанавливаем цвет пера (который мы можем выбрать с помощью специального окна) */ pntPixmap.drawEllipse(p[0],r,r); // рисуем текущую окружность в области pixmap painter.drawPixmap(0, 0, w, h, pixmap); // накладываем текущую окружность на ранее нарисованные } } // Слот для кнопки «Выбор цвета»: void MainWindow::showDialog() { color = QColorDialog::getColor(); // выводим на экран специальное окно и считываем цвет } // Слот для кнопки «Отменить»: void MainWindow::Annul() { DrawBuffer.removeLast(); // удаляем последний элемент из списка update(); } // Слот для кнопки «Очистить»: void MainWindow::Clear() { DrawBuffer.clear(); // Очищаем список update(); } // Слот для кнопки «Открыть» void MainWindow::open() { QFile file("picture.dat"); file.open(QIODevice::ReadOnly); // Создаем файл для чтения QDataStream in(&file); // Создаем поток на основе файла in>>DrawBuffer; // считываем список окружностей из потока update(); // отображаем окружности в окне } // Слот для кнопки «Сохранить» void MainWindow::save() { QFile file("picture.dat"); // создаем файл для записи file.open(QIODevice::WriteOnly); QDataStream out(&file); // создаем поток на основе файла: out << DrawBuffer; // записываем окружности в файл file.close(); // обязательно закрываемфайл }

Запустите программу, нарисуйте несколько окружностей разного цвета и проверьте работу команд меню.

Задания для самостоятельного выполнения


  1. Создайте приложение, которое позволяет рисовать отрезки прямых линий с помощью мыши. Создаваемая линия должна быть видима в процессе построения. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  2. Создайте приложение, которое позволяет рисовать закрашенные прямоугольники с помощью мыши. Создаваемый прямоугольник должен быть видим в процессе построения. Цвет прямоугольников должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  3. Создайте приложение, которое позволяет рисовать закрашенные треугольники, задаваемые тремя щелчками мыши в вершинах. Цвет треугольников должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  4. Создайте приложение, которое позволяет рисовать закрашенные круги с помощью мыши. Создаваемая окружность должна быть видима в процессе построения. Цвет окружностей должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  5. Создайте приложение, которое рисует закрашенные пятиконечные звезды (вписанную в воображаемую окружность; центр окружности и одна точка на окружности задаются щелчками мыши). Цвет каждой звездочки должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  6. Создайте приложение, которое рисует закрашенные квадраты с помощью мыши так, что мышь проходит по диагонали квадрата от одной вершины к другой. Квадрат должен быть виден в процессе построения. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  7. Создайте приложение, которое рисует дуги с помощью мыши так, что мышь определяет начало и конец дуги. Дуга должен быть видима в процессе построения. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  8. Создайте приложение, которое рисует правильные треугольники с помощью мыши так, что указатель мыши находится в одной из вершин треугольника. Треугольник должен быть видим в процессе построения и может поворачиваться. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. При отпускании мыши треугольник закрашивается. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  9. Создайте приложение, которое рисует правильные 8-конечные звездочки с помощью мыши так, что указатель мыши находится в одной из вершин звездочки. Звездочка должна быть видима в процессе построения и может поворачиваться. При отпускании мыши звездочка закрашивается. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  10. Создайте однодокументное приложение, которое рисует правильные 5-конечные звездочки с помощью мыши так, что указатель мыши находится в одной из вершин звездочки. Звездочка должна быть видима в процессе построения и может поворачиваться. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

  11. Создайте однодокументное приложение, которое рисует правильные шестиугольники с помощью мыши так, что указатель мыши находится в одной из вершин шестиугольника. Шестиугольник должен быть видим в процессе построения и может поворачиваться. Цвет линий должен определяться с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла..

Лабораторная работа № 8


Тема: «Области отсечения»

Пример 1: программа, которая рисует 6-угольник, цвет которого можно изменять с помощью немодального диалогового окна с наборными счетчиками (Spin). Диалоговое окно появляется при нажатии кнопки «Диалог».
Создайте проект на базе главного окна.

Д обавьте дочернее диалоговое окно, описываемое классом Dialog (выберите в меню Файл | Новый файл или проект... , в появившемся диалоговом окне выберите Qt | Класс формы Qt Designer).

Спроектируйте окно как показано на рисунке, добавив элемент spinBox.

В файл main.cpp добавьте подчеркнутую строку:

int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.move(400, 250); // перемещает окно к центру экрана w.show(); return a.exec(); }

В файлe dialog.h в описание класса добавьте подчеркнутые строки:

#ifndef DIALOG_H #define DIALOG_H #include namespace Ui { class Dialog; } class MainWindow; // С помощью этого класса объявим указатель на родительское окно class Dialog : public QDialog { Q_OBJECT public: // Измените тип указателя на MainWindow explicit Dialog(MainWindow *parent = 0); Dialog(); MainWindow* Parent; /* С помощью этого указателя диалоговое окно будет передавать новое значение цвета главному окну */ // объявление слота, который будет передавать новое значение цвета главному окну: publicslots: voidsetN(int); private: Ui::Dialog *ui; }; #endif // DIALOG_H

В файл dialog.cpp добавьте подчеркнутые строки:
#include "dialog.h" #include "ui_dialog.h" #include "mainwindow.h" // обеспечивает возможность использования класса MainWindow Dialog::Dialog(MainWindow*parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); ui->spinBox->setRange(0, 255); // Задаем диапазон изменнения значений наборного счетчика ui->spinBox->setSingleStep(5); // при щелчке по стрелочке значение счетчика будет изменяться на 5 Parent = parent; // Указатель, объявленный в классе, становится равным значению локального указателя ui->spinBox->setValue(Parent->n); /* Устанавливаем начальное значение счетчика так, чтобы оно было равно начальному значению цвета, установленного в конструкторе главного окна */ connect(ui->spinBox, SIGNAL(valueChanged(int)),
this, SLOT(setN(int)));
/* связываем сигнал об изменении значения счетчика со слотом, который передает новое значение цвета главному окну */ } Dialog::Dialog() { delete ui; } void Dialog::setN(int n) /* значение n автоматически передается слоту от наборного счетчика с помощью сигнала valueChanged(int) { Parent->n = n; // передаем значение цвета переменной, объявленной в классе гланого окна Parent->update(); // посылаем сигнал «перерисовать окно» }

Добавьте в файл mainwindow.h подчеркнутые строки:

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include "dialog.h" // Обеспечивает возможность использования класса Dialog #include // обеспечивает возможность использования графических функций namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); MainWindow(); void paintEvent(QPaintEvent *); // функция, которая автоматически вызывается при перерисовывании окна Dialog* dlg; // объект, описывающий диалоговое окно int n; // значение яркости цвета private: Ui::MainWindow *ui; private slots: void on_actionDialog_triggered(); }; #endif // MAINWINDOW_H

В режиме проектирования формы с помощью редактора действий добавьте действие actionDialog с текстом «Диалог» (это будет командой меню, которая вызывает вспомогательное диалоговое окно).

В файл mainwindow.cpp добавьте код, показанный ниже:

#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); n = 100; // начальное значение цвета dlg = new Dialog(this); // создаем объект класса Dialog ui->menuBar->addAction(ui->actionDialog); // В меню создаем кнопку, соответствующую команде «Диалог» (без выпадающего меню) } MainWindow::MainWindow() { delete ui; } // В режиме проектирования формы добавьте слот для действия actionDialg: void MainWindow::on_actionDialog_triggered() { dlg->move(400+width(), 250); // размещаем диалоговое окно на правой границе главного окна dlg->show(); // рисуем окно на экране dlg->activateWindow(); // делаем диалоговое окно активным } // Описываем, что нужно нарисовать в окне void MainWindow::paintEvent(QPaintEvent *) { QPainter painter(this);// Объект для рисования QString str = QString::number(n);/* Строка, с помощью которой на экране будет отображаться текущая яркость цвета */ painter.drawText(20,70, str);// Отображаем на экране значение яркости цвета QBrush brush(QColor(n,0,0));/* объявляем кисть, число n в данном случае будет опреелять яркость красного цвета */ painter.setBrush(brush);// побключаем кисть QPolygonF polygon; // Объявляем многоугольник qreal r = 100; // радиус окружности, в которую будет вписан многоугольник qreal x0 = 200, y0 = 150; // центр окружности qreal dfi = M_PI / 3; // угол между вершинами 6-угольника for (int i = 0; i< 6; ++i) // рисуем 6-угольник { qreal fi = dfi * i; // угол, соответствующий очередной вершине // определяем координаты вершины qreal x = x0 + r*cos(fi); qreal y = y0 + r*sin(fi); polygon << QPointF(x,y);// добавляем координаты вершины к полигону } painter.drawPolygon(polygon);// рисуем многоугольник (6-угольник) }
Пример 2: программа, которая расчерчивает окно правильными 6-угольниками («пчелиными сотами»); размер шестиугольника — 1 / 5 меньшей стороны окна (но не меньше 2); при щелчке мышью внутри шестиугольника, он закрашивается цветом, выбранным с помощью специального окна для выбора цвета.
Создайте приложение на базе главного окна. В файле mainwindow.h добавьте объявления как показано ниже.

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #define maxR 500 // максимальное количество строк #define maxC 700 // максимальное количество столбцов namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); MainWindow(); void paintEvent(QPaintEvent *); // автоматически вызывается при перерисовке окна void createMatrices(); // функция, размещающая в памяти матрицы полигонов и регионов void createNet(); // формирование сетки в рабочей области окна void createPolygon(int, int); // создание одной ячейки с заданными номерами void mousePressEvent(QMouseEvent *); // автоматически вызыватся при щелчке мышью void resizeEvent(QResizeEvent *); // автоматически вызывается при создании окни и при изменении его размеров QPolygon** Polygon; // Указатель на матрицу полигонов QRegion** Region; // Указатель на матрицу областей QColor Color[maxR][maxC]; /* матрица для хранения цвета в каждой ячейке, она должна быть максимальных размеров, поскольку мы заранее не знаем размеры окна */ int previousRows, rows, columns; /* количество строк для предыдущего состояния окна, текущее количество строк, количество столбцов */ double w, h; // размеры рабочего поля double size, x0, y0, r; // размер одной ячейки, центр и радиус окружности, в которую вписан многоугольник QBrush brush; // кисть private: Ui::MainWindow *ui; private slots: void on_actionOpen_triggered(); void on_actionSave_triggered(); }; #endif // MAINWINDOW_H

В файле mainwindow.cpp напишите код, показанный ниже:

#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); for (int i = 0; i < maxR; ++i) for (int j = 0; jMainWindow() { delete ui; } // Виртуальная функция, которая вызывается при изменении размеров окна void MainWindow::resizeEvent(QResizeEvent * ) { w = width(); // ширина рабочего поля y0 = centralWidget()->y(); // Верхняя граница клиентской области h = height() - y0; // высота рабочего поля size = qMin(w, h) / 5; // размер одной ячейки (расстояние между двумя противоположными вершинами) if (size<2) size = 2; // размер не может оказаться равным нулю, чтобы не произошло деление на ноль // qDebug() << "size = " << size; r = size/2; // радиус окружности, в которую вписана ячейка x0 = r * sqrt(3)/2; // расстояние от левой границы окна до центра первого 6-угольника (красная линия на рисунке) /* длина стороны правильного 6-угольника = r, а расстояние между ценрами ячеек (вертикальный катет светлого треугольника) = r+r/2 = 3*r / 2 */ rows = int(2*h/(3*r)) +2; // количество полных рядов равно частному от деления высоты рабочей области на расстояние между центрами ячеек; к этому количеству нужно добавить 2 — неполные ряды на верхней и нижней границах окна if (rows>maxR) rows = maxR; // но количество рядов не может превышать задданый максимум // qDebug() << "rows = " << rows; columns = int(w / (r*sqrt(3)))+2; /* расстояние между центрами окружностей по горизонтали = (r*sqrt(3)/2) * 2 = r*sqrt(3), количество столбцов равно частному от деления ширины окна на расстояние между рядами + 2 неполных ряда на левой и правой границе */ if (columns>maxC) columns = maxC; // количество столбцов неможет превышать заданный максимум // qDebug() << "columns = " < void MainWindow::paintEvent(QPaintEvent * ) { QPainter painter(this); // рисуем многоугольники цветом, который записан в матрице цветов: for (int i = 0; i < rows; ++i) for (int j = 0; j < columns; ++j) { painter.setBrush(QBrush(Color[i][j])); painter.drawPolygon(Polygon[i][j]); } } // размещаем матрицы в памяти: void MainWindow::createMatrices() { if (previousRows) // удаляем предидущие матрицы из памяти, если они ненулевого размера { for (int i = 0; i < previousRows; ++i) // освобождаем память по строкам { delete[] Polygon[i]; // освобождаем память, выделенную для данных delete[] Region[i]; } delete Polygon; // удаляем массивы указателей delete Region; } previousRows = rows; // запоминаем текущее количество строк // создаем массивы указателей на строки данных: Polygon = new QPolygon* [rows]; Region = new QRegion* [rows]; // захватываем память для строк данных: for (int i = 0; i < rows; ++i) { Polygon[i] = new QPolygon[columns]; // для координат 6-угольников Region[i] = new QRegion[columns]; // для областей } } void MainWindow::createNet() // заполняем матрицы данными { double dx = r*sqrt(3); // расстояние между центрами ячеек по горизонтали double dy = r*3 / 2; // расстояние между центрами ячеек по вертикали for (int i = 0; i pos(); // координаты курсора мыши // проверяем, в какой регион (в какой 6-угольник) попадает курсор мыши for (int i = 0; i> Color[i][j]; // считываем цвет ячейки file.close(); } /* Главное окно приложения автоматически перерисовывается при закрытии окна для выбора файла */ }

Задания для самостоятельного выполнения


  1. Создать приложение, которое расчерчивает окно правильными шестиугольниками (размер – 1/20 высоты окна) и при щелчке мышью в шестиугольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.
    Проверку, в какой ячейке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

2. Создать приложение, которое расчерчивает окно косой сеткой (линиями под углом 45 градусов, расстояние между линиями – 1/20 высоты окна) и при щелчке мышью в ромбе закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.
Проверку, в какой ячейке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

3. Создать приложение, которое расчерчивает окно прямоугольной сеткой (линиями, параллельными сторонам окна, расстояние между линиями – 1/20 меньшей стороны окна) и при щелчке мышью в прямоугольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.
Проверку, в какой ячейке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

4. Создать приложение, которое заполняет окно несколькими рядами окружностей (радиус окружности – 1/20 меньшей стороны окна) и при щелчке мышью в окружности закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.
Проверку, в какой окружности пользователь щелкнул мышью, выполнять с помощью областей QRegion!

5. Создать приложение, которое заполняет окно несколькими рядами равносторонних треугольников (высота треугольника - 1/10 высоты окна) и при щелчке мышью в треугольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

Проверку, в каком треугольнике пользователь щелкнул мышью, выполнять с помощью областей QRegion!

6. Создать приложение, которое заполняет окно несколькими рядами вертикально стоящих ромбов (высота ромба в 2 раза больше ширины) и при щелчке мышью в ромбе закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.
Проверку, в каком ромбе пользователь щелкнул мышью, выполнять с помощью областей QRegion!

7. Создать приложение, которое заполняет окно несколькими рядами правильных 5-угольников (выпуклых) и при щелчке мышью в 5-угольнике закрашивает его цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

Проверку, в каком 5-угольнике пользователь щелкнул мышью, выполнять с помощью областей QRegion!

8. Создать приложение, которое заполняет окно несколькими рядами пятиконечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

9. Создать приложение, которое заполняет окно несколькими рядами 6-конечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

10. Создать приложение, которое заполняет окно несколькими рядами 7-конечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

11. Создать приложение, которое заполняет окно несколькими рядами 8-конечных звездочек и при щелчке мышью в звездочке закрашивает ее цветом, выбираемым с помощью немодального диалогового окна с наборными счетчиками (Spin), которые позволяют установить интенсивности красной, зеленой и синей составляющих цвета. Предоставьте возможность сохранять изображение в файле и считывать его из файла.

Проверку, в какой звездочке пользователь щелкнул мышью, выполнять с помощью областей QRegion!

Лабораторная работа № 9

1   2   3   4   5   6   7

Тема: «Работа с массивами с помощью класса QVector»

Пример: программа считывает массив неотрицательных чисел из файла, выводит его на экран, используя полосы прокрутки, и рисует круговую диаграмму для 13 самых больших элементов, отображая остальные в сумме.
Создайте проект на базе главного окна. Добавьте класс Pole, производный от QWidget. В главном окне создадим область прокрутки и поместим в эту область поле, на котором выведем массив и отображающую его круговую диаграмму.

В меню главного окна добавьте меню File и действие Open.

В файл mainwindow.cpp добавьте показанный ниже код.

#include "mainwindow.h" #include "ui_mainwindow.h" #include "pole.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QTextCodec* codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(codec); QScrollArea* scroll = new QScrollArea(this); // создаем область прокрутки Pole* pole = new Pole(scroll); // создаем новый виджет scroll->setWidget(pole); // размещаем виджет в области прокрутки setCentralWidget(scroll); // делаем область прокрутки рабочей областью окна connect(ui->actionOpen, SIGNAL(triggered()), pole, SLOT(fileOpen())); // связываем вызов команды File|Open со слотом, который мы создадим в классе Pole } MainWindow::MainWindow() { delete ui; }

В файл pole.h добавьте показанный ниже код.

#ifndef POLE_H #define POLE_H #include #include class Pole : public QWidget { Q_OBJECT public: explicit Pole(QScrollArea* parent = 0); // измените тип указателя на родительское окно QScrollArea* Parent; // указатель на область прокрутки void paintEvent(QPaintEvent *); // перерисовывает содержимое окна QFile file; // файл, содержащий массив QString fileName; // имя файла QVector v; // массив QVector copyV; // копия массива QFont font; // шрифт int dy; // расстояние между элементами массива при выводе на экран int k; // количество элементов массива void Pie(QPainter&, QRect&, int, int, int); // рисует один кусок диаграммы signals: public slots: void fileOpen(); // слот, считывающий массив из файла }; #endif // POLE_H

В файл pole.cpp добавьте показанный ниже код.

#include "pole.h" #include "mainwindow.h" Pole::Pole(QScrollArea* parent) : // измените тип указателя на родительское окно QWidget(parent) { Parent = parent; // запоминаем значение указателя } void Pole::paintEvent(QPaintEvent *) // отображаем массив на экране: { QPainter painter(this); int y = 20; // уровень, с которого начинается вывод массива на экран painter.setFont(font); // устанавливаем шрифт // Вывод массива: double sum = 0; // сумма элементтов массива k = v.size(); // размер массива for (int i = 0; i < k; ++i) // проходим по массиву { painter.drawText(10, y, QString::number(v[i])); // выводим очередной элемент массива на экран y += dy; // переходим на другую строку sum += v[i]; // добавляем элемент к сумме } copyV = v; // копируем массив, чтобы исходный массив отображался на экране без изменений qSort(copyV.begin(), copyV.end(), qGreater()); // сортируем копию массива по убыванию, чтобы построить диаграмму // Диаграмма: QRect rectBase = Parent->rect(); // прямоугольник, соответствующий видимой части области прокрутки QRect rect = rectBase; // прямоугольник, в котором мы будем рисовать диаграмму int h = rectBase.height()-25; // несколько уменьшим высоту прямоугольника rect.setSize(QSize(h,h)); // задаем квадрат высотой h rect.moveRight(rectBase.width()-25); // перемещаем квадрат к правой границе окна double startAngle = 0; // начальный угол для первого фрагмента диаграммы double spanAngle = 0; // угол, for (int i = 0; i < qMin(13, k); ++i) // { spanAngle = 360 * 16.* copyV[i] / sum ; // Угол между радиусами Pie(painter, rect, startAngle, spanAngle, i); // рисуем сектор с помощью функции, определенной ниже startAngle += spanAngle; // переходим к следующему сектору } if (k > 13) // отображаем остальные элементы массива в сумме: { spanAngle = 360*16 - startAngle; // определяем размер соответствующего угла Pie(painter, rect, startAngle, spanAngle, 13); // рисуем оставшуюся часть диаграммы } } void Pole::fileOpen() { if (file.isOpen()) file.close(); v.clear(); // удаляем ранее считанный массив copyV.clear(); // и его копию fileName = QFileDialog::getOpenFileName(this, "Открыть файл", QString(), QString("Текстовые файлы (*.txt);;Все файлы (*.*)")); // считываем имя файла с помощью специального окна if (!fileName.isEmpty()) // если имя файла выбрано { file.setFileName(fileName); // связываем объект файл с физическим файлом на диске file.open(QIODevice::ReadOnly); // открываем файл QTextStream in(&file); // создаем поток для работы с файлами double x; // одно число из файла while (true) // как бы бесконечный цикл для чтения данных из файла { in >> x; // считываем одно число if (x < 0) // если число недопустимо { QMessageBox::critical(this, "Ошибка в данных", "Все числа должны быть больше 0"); return; } if (!in.atEnd()) // если файл не закончен v << x; // записываем число else break; // } font = QFont("Serif", 12); // QFontMetrics fm(font); // dy = fm.height(); // k = v.size(); // int height = qMax(1500, 20 + k*dy); // this->resize(1500, height); // } } void Pole::Pie(QPainter & painter,QRect& rect, int startAngle, int spanAngle, int i) { // int c = i+1; // int I, R,G,B; // B = c % 2; c /= 2; // G = c % 2; c /= 2; // R = c % 2; c /= 2; // I = c % 2; // painter.setBrush(QBrush(QColor(I*100+R*155,I*100+G*155,I*100+B*155))); // painter.drawPie(rect, startAngle, spanAngle); // }

Задания для самостоятельного выполнения


  1. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран в столбик.
    Значения элементов массива могут повторяться. Вывести на экран (перед массивом) наиболее часто повторяющийся элемент и количество его повторений. Если все элементы разные, вывести соответствующий текст.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  2. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести массив на экран в столбик.
    Значения элементов массива могут повторяться. Вывести на экран самую длинную последовательность неповторяющихся элементов.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  3. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран.
    Удалить один максимальный элемент и один минимальный. После этого найти среднее арифметическое оставшихся элементов и вывести его на экран.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  4. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран.
    Если в массиве максимальный элемент повторяется, удалить из массива такие повторения, оставив только один максимальный элемент.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  5. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран.
    Удалить из массива элементы, равные нулю. Вывести полученный массив на экран и среднее арифметическое оставшихся элементов.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  6. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран в столбик.
    Поменять местами первый элемент с минимальным и вывести полученный массив на экран.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  7. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран в столбик.
    Поменять местами последний элемент с максимальным и вывести массив на экран.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  8. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива могут иметь дробную часть и должны быть неотрицательными. Вывести исходный массив на экран.
    Подсчитать количество целых четных элементов (вывести на экран).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  9. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран.
    Найти первый элемент и его номер, такой что он отличается от максимального не более чем на 20%, но не равен ему.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  10. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран.
    Найти элементы, значения которых больше среднего (вывести на экран эти элементы и их количество).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  11. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива могут иметь дробную часть и должны быть неотрицательными. Вывести исходный массив на экран.
    Найти первый элемент, который является целым и степенью 10 (вывести на экран значение элемента и его номер).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  12. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива могут иметь дробную часть и должны быть неотрицательными. Вывести исходный массив на экран.
    Найти последний элемент, который является целым и степенью двойки (вывести на экран значение и его номер).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  13. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть целыми и неотрицательными. Вывести исходный массив на экран.
    Найти количество цифр максимального элемента (вывести на экран максимальный элемент и количество цифр).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  14. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть неотрицательными. Вывести исходный массив на экран.
    Найти первый элемент, который является квадратом натурального числа (вывести на экран его значение и номер).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  15. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть целыми и неотрицательными. Вывести исходный массив на экран.
    Найти первый элемент, содержащий цифру 7 (вывести на экран элемент и его номер).
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  16. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть целыми и неотрицательными. Вывести исходный массив на экран.
    Определить, кратен ли максимальный элемент на минимальному.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  17. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть целыми и неотрицательными. Вывести исходный массив на экран.
    Определить, кратна ли сумма элементов максимальному элементу массива.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  18. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть целыми и неотрицательными. Вывести исходный массив на экран.
    Вывести на экран те элементы массива, которые являются простыми числами.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.

  19. Создать приложение на основе главного окна с прокруткой, которое считывает массив типа QVector из файла. Элементы массива должны быть целыми и неотрицательными. Вывести исходный массив на экран.
    Вывести на экран те элементы массива, которые являются числами Фибоначчи.
    Затем отсортировать массив по убыванию, построить круговую диаграмму по первым 13 элементам, представив остальные в сумме. Отсортированный массив записать в файл.