Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Laboratornyy_praktikum_po_programmirovaniyu_v_s...docx
Скачиваний:
0
Добавлен:
11.12.2019
Размер:
130.48 Кб
Скачать
    1. Пример 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), Очистить (actionClear).

Отредактируйте файл 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(); // обязательно закрываемфайл
}

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]