Малювання інтерфейсів, формування таблиць баз даних, робота з мережею - це все добре, але іноді хочеться просто щось намалювати, наприклад трикутник . А потім звичайно ж пожвавити цей об'єкт, щоб ним можна було керувати, і згодом перетворити цей проект на маленьку гру. Ну хто не хоче написати власну гру, навіть найпростішу?
Давайте тоді зробимо перший крок у бік простенької гри, а саме розберемося з малюванням об'єктів у Qt, спробувавши намалювати трикутник.
Програмний код був написаний QtCreator 3.3.1 на основі Qt 5.4.1.
Структура проекту "Трикутник"
Опишемо структуру проекту, в якому малюватимемо трикутник:
- Triangle.pro - профайл проекту, що створюється за замовчуванням і в даному проекті не вимагає коригування;
- main.cpp - файл, з якого стартує програма, в даному файлі викликається widget, в якому буде розташовуватися графічна сцена з трикутником;
- widget.h - заголовний файл, що викликається віджетом з графічною сценою;
- widget.cpp - файл вихідних кодів віджету;
- triangle.h - заголовний файл класу Трикутника , який успадкований від QGraphicsItem;
- triangle.cpp - файл вихідних кодів класу Трикутник.
mainwindow.ui
У дизайнері інтерфейсів просто закидаємо QGraphicsView у віджет. Більше нічого не потрібне.
віджет.h
У цьому файлі лише оголошуємо графічну сцену і об'єкт трикутника, з яким працюватимемо.
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QGraphicsScene> #include <triangle.h> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private: Ui::Widget *ui; QGraphicsScene *scene; // Объявляем графическую сцену Triangle *triangle; // и треугольник }; #endif // WIDGET_H
widget.cpp
У цьому файлі налаштовуються об'єкти QGraphicsView , QGraphicsScene, а також створюється та встановлюється на графічну сцену об'єкт трикутника.
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); this->resize(600,600); // Задаем размеры виджета, то есть окна this->setFixedSize(600,600); // Фиксируем размеры виджета scene = new QGraphicsScene(); // Инициализируем графическую сцену triangle = new Triangle(); // Инициализируем треугольник ui->graphicsView->setScene(scene); // Устанавливаем графическую сцену в graphicsView ui->graphicsView->setRenderHint(QPainter::Antialiasing); // Устанавливаем сглаживание ui->graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по вертикали ui->graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Отключаем скроллбар по горизонтали scene->setSceneRect(-250,-250,500,500); // Устанавливаем область графической сцены scene->addLine(-250,0,250,0,QPen(Qt::black)); // Добавляем горизонтальную линию через центр scene->addLine(0,-250,0,250,QPen(Qt::black)); // Добавляем вертикальную линию через центр scene->addItem(triangle); // Добавляем на сцену треугольник triangle->setPos(0,0); // Устанавливаем треугольник в центр сцены } Widget::~Widget() { delete ui; }
трикутник.h
А ось тепер настав час опрацювати сам клас, у якому створюється трикутник. У цьому випадку успадковуємося від QGraphicsItem .
#ifndef TRIANGLE_H #define TRIANGLE_H #include <QGraphicsItem> #include <QPainter> // Наследуемся от QGraphicsItem class Triangle : public QGraphicsItem { public: Triangle(); ~Triangle(); protected: QRectF boundingRect() const; /* Определяем виртуальный метод, * который возвращает область, в которой * находится треугольник * */ /* Определяем метод для отрисовки треугольника * */ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; #endif // TRIANGLE_H
triangle.cpp
А тепер малюємо трикутник у нашому класі. Тут є один важливий момент. Координатна система об'єкта QGraphicsItem - це поняття відмінне від координатної системи графічної сцени. Тобто кожен об'єкт QGraphicsItem або успадкований від даного класу має власну систему координат, яка транслюється в систему координат QGraphicsScene . Коли ми задаємо позицію, де буде об'єкт на графічній сцені, то ми вказуємо, де буде знаходиться точка графічного об'єкта, яка має координати 0 по осі X і 0 по осі Y, в координатній системі об'єкта, тому важливо, щоб дана точка була в центр графічного об'єкта. Це спростить подальшу роботу, якщо звичайно ви свідомо не припускаєте іншого варіанту.
#include "triangle.h" Triangle::Triangle() : QGraphicsItem() { } Triangle::~Triangle() { } QRectF Triangle::boundingRect() const { return QRectF(-25,-40,50,80); // Ограничиваем область, в которой лежит треугольник } void Triangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QPolygon polygon; // Используем класс полигона, чтобы отрисовать треугольник // Помещаем координаты точек в полигональную модель polygon << QPoint(0,-40) << QPoint(25,40) << QPoint(-25,40); painter->setBrush(Qt::red); // Устанавливаем кисть, которой будем отрисовывать объект painter->drawPolygon(polygon); // Рисуем треугольник по полигональной модели Q_UNUSED(option); Q_UNUSED(widget); }
Підсумок
В результаті у Вас має вийде програма, яка виводить на екран червоний трикутник у центрі графічної сцени на перетині двох ліній, як показано на малюнку.
Також рекомендую ознайомитись з відеоуроком, у якому докладніше розглянуто момент із встановленням координат графічного об'єкта.
Евгений, здравствуйте!
Решил поэкспериментировать немного с кодом из этого урока, нарисовать вместо треугольника квадрат и разобраться с координатами. В итоге, запутался. И ни документация, ни доп.литература не помогла.
Проблема, собственно, в следующем. Когда я делаю графическую форму, компоную графические слои и виджеты, я получаю размеры.
Дальше берём сам код:
в первой строке мы задаём размеры виджета, но если их поменять, то сам его размер не изменяется, а изменения происходят, если поменять нижнюю строчку. Почему так?
Получается вот так:
Далее вот эти строчки:
Изменяя размеры в scene->setSceneRect(), визуально ничего не меняется. Почему?
Это и есть установка размеров области нашего QGraphicsView? Если да- то что за размеры остаются в ui-файле при этом?
Далее, я пытаюсь отрисовать квадрат в классе Map, но он не появляется на сцене, хотя когда я делал на координатах вашего урока, он был. Но как только я начал изменять их, он исчез. И тут я задумался собственно. Я хотел нарисовать квадрат ровно в левом углу сцены, которая имеет координаты (-250,-250), но квадрат так и не появлялся. Только когда я ставил координаты где-то ориенитирочно(-130,-130), то он вставал как раз в левый угол
Еще, я так и не понял что делает функция
Что именно она ограничивает? Думал, что за границы, которые определяет этот метод, нельзя "выйти", т.е, отрисовать квадрат "ЗА" установленными этим методом координатами, но это не так!
В итоге решил поиграться с координатами в графическом файлу ui и квадрат после этого совсем исчез.
Подскажите, что я делаю не так? В чём моя основная ошибка? Может где-то можно об этом почитать поподробнее? Я помню ваши слова, что координаты QGraphicsScene и QGraphicsItem разные, но я всё равно не понимаю как автоматически управлять этими вещами. Например, если я хочу нарисовать сцену и отрисовать на ней квадраты с помощью цикла (к примеру, как в игре "Морской бой"). Мы же должна хорошо понимать и знать координаты сцены и самого объекта отрисовки. Особенно, координаты углов самого объекта.
Заранее благодарю за ответ, Евгений!