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

Создайте проект на основе главного окна и задайте белый цвет фона в свойс­твах этого окна.

По аналогии с предыдущим примером мы будем запоминать нарисованные окружности в списке. Но для того, чтобы использовать такие списки нам нужно определить класс, описывающий окружности.

Щелкните в окне, описывающем структуру проекта (слева), по имени про­екта правой кнопкой мыши и в появившемся контекстном меню выберите Add New...

В появившемся диалоговом окне выберите С++ | C++ Class. Задайте имя класса Circle и завершите создание класса. К проекту будут добавлены файлы circle.h и circle.cpp, содержащие описание нашего класса.

Для описания окружности мы будем использовать координаты центра, ради­ус и цвет окружности. Хранить в списках можно только такие объекты, для кото­рых определены конструктор по умолчанию, конструктор копирования и оператор присваивания. Кроме того нам потребуется основной коструктор.

Отредактируйте файл circle.h как показано ниже:

#ifndef CIRCLE_H

#define CIRCLE_H

#include <QtGui>  // обеспечивает графическую систему

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), Очистить (action­Clear).

Отредактируйте файл mainwindow.h как показано ниже:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#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 <Circle> DrawBuffer;

// список окружностей (ради этой строчки мы создали класс Circle)

QColor color; // цвет текущей окружности

void mousePressEvent(QMouseEvent *); // обрабатывает нажатие кнопки мыши

void mouseMoveEvent(QMouseEvent *); // обрабатывает движение мыши

void mouseReleaseEvent(QMouseEvent *);

// обрабатывает отпускание кнопки мыши

void paintEvent(QPaintEvent *); // описывает, что нужно нарисовать в окне

public slots:

void Annul(); // для кнопки «Отменить»

void Clear(); // для кнопки «Очистить»

void showDialog(); // для кнопки «Выбрать цвет»

void save(); // для кнопки «Сохранить»

void open(); // для кнопки «Открыть»

private:

Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

Отредактируйте файл mainwindow.cpp как показано ниже:

#include "mainwindow.h"

#include "ui_mainwindow.h"

/* Для того, чтобы можно было сохранить список окружностей, нужно научить программу сохранять каждый объект класса Circle: */

QDataStream& operator <<(QDataStream& ostream, const Circle& c)

{

ostream << c.p.x()<< c.p.y() << c.r << c.color;

return ostream;

}

 

 //  Описываем, как считывать из потока каждый объект класса circle:

QDataStream& operator >> (QDataStream& istream, Circle& c)

{

int x, y;

istream >> x >> y >> c.r >> c.color;

c.p.setX(x);

c.p.setY(y);

return istream;

}

MainWindow::MainWindow(QWidget *parent):

QMainWindow(parent),

ui(new Ui::MainWindow)

{

ui->setupUi(this);

 // связываем сигналы от команд меню с соответствующими слотами:   

connect(ui->actionAnnul, SIGNAL(triggered()), this, SLOT(Annul()));

connect(ui->actionClear, SIGNAL(triggered()), this, SLOT(Clear()));

connect(ui->actionColor, SIGNAL(triggered()), this, SLOT(showDialog()));

connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(save()));

connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(open()));

 // инициализируем элементы данных класса MainWindow:

drawMode = false;

p[0] = p[1] = QPoint(0,0);

r = 0;

color = Qt::darkCyan;

}

MainWindow::~MainWindow()

{

delete ui;

}

 // Обрабатываем нажатие кнопки мыши:

void MainWindow::mousePressEvent(QMouseEvent * e)

{

if (e->button() ==Qt::LeftButton) // если нажата левая кнопка

{

   drawMode = true; // разрешаем рисование

   p[0] = e->pos(); // запоминаем центр окружности

}

}

// Обрабатываем движение мыши:

void MainWindow::mouseMoveEvent(QMouseEvent * e)

{

if (drawMode) // если прижата левая кнопка 

{

   p[1] = e->pos(); // запоминаем текущую точку на окружности

   r = sqrt(pow(p[1].x()-p[0].x(),2) + pow(p[1].y()-p[0].y(),2));

// вычисляем радиус окружности

   update(); // перерисовываем окно

}

}

// Обрабатываем отпускание кнопки мыши:

void MainWindow::mouseReleaseEvent(QMouseEvent *)

{

drawMode = false; // запрещаем рисование

int r = sqrt(pow(p[1].x()-p[0].x(),2) + pow(p[1].y()-p[0].y(),2));

// вычисляем текущий радиус

DrawBuffer.append(Circle(p[0], r, color)); // добавляем окружность в список

update(); // перерисовываем окно

}

// Описываем, что нужно нарисовать в окне

void MainWindow::paintEvent(QPaintEvent *)

{

QPainter painter(this);

int size = DrawBuffer.size();

if (size) // Если список не пуст:

{

 // рисуем окружности, сохраненные в списке:      

QList<Circle>::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(); // обязательно закрываемфайл

}

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

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: