Евгений Легоцкой17 сентября 2015 г. 10:22

Qt/C++ - Урок 019. Рисуем треугольник в Qt5. Позиционирование в QGraphicsScene

Рисование интерфейсов, формирование таблиц баз данных, работа с сетью - это всё хорошо, но иногда хочется просто, что-нибудь нарисовать, например треугольник . А потом конечно же оживить этот объект, чтобы им можно было управлять, и в последствии превратить этот проект в маленькую игру. Ну кто не хочет написать собственную игру, даже самую простую?

Давайте тогда сделаем первый шаг в сторону простенькой игры, а именно разберемся с рисованием объектов в 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 в виджет. Больше ничего не требуется.

widget.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;
}

triangle.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);
}

Итог

В результате у Вас должно получится приложение, которое выводит на экран красный треугольник в центре графической сцены на пересечении двух линий, как показано на рисунке.

Также рекомендую ознакомиться с видеоуроком, в котором подробнее рассмотрен момент с установкой координат графического объекта.

Архив с проектом

Видеоурок

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
Поддержать автора Donate

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Timeweb

Позвольте мне порекомендовать вам отличный хостинг, на котором расположен EVILEG.

В течение многих лет Timeweb доказывает свою стабильность.

Для проектов на Django рекомендую VDS хостинг

Посмотреть Хостинг
VD

C++ - Тест 001. Первая программа и типы данных

  • Результат:73баллов,
  • Очки рейтинга1
Ds

C++ - Тест 003. Условия и циклы

  • Результат:64баллов,
  • Очки рейтинга-1
o

C++ - Тест 001. Первая программа и типы данных

  • Результат:86баллов,
  • Очки рейтинга6
Последние комментарии
RK
РГ

QML - Урок 016. База данных SQLite и работа с ней в QML Qt

Добрый день! можно как то обойтись без метода updateModel()? После вызова этого метода происходит перерисовка страницы(если я правильно понимаю), и все элементы, например, CheckBox перерисовываю…
D:

QML - Урок 016. База данных SQLite и работа с ней в QML Qt

Добрый день, пытаюсь разобраться и подргнать пример под себя. Есть бд с огромным количеством полей. В приложении на виджетах при использовании QTableView все работает и путем простого sql запрос…

Django - Урок 039. Добавление личных сообщений и чатов на сайте - Часть 2 (Счётчик диалогов и чатов с непрочитанными сообщениями)

Добавляйте поле файла в модель сообщения. И в форме сообщения указывайте, что поле с файлом.
Сейчас обсуждают на форуме
ДК

Уйти от gtk

ошибка: Gtk-Message: 15:56:06.190: Failed to load module "atk-bridge" Привет. Начало истории здесь Кратко: на АЛЬТ линукс при запуске в консоли приложения по…
ДК

применяется некорректное разрешение для стилей под обычным пользователем

Привет. Такая проблема на ALT Linux: если запускать приложение от руута, то со стилями и размером шрифта всё в полном порядке. Если же мы запускаем приложение под обычным пользователем, то …

Наследование QWidget

Это утверждение ничего не значит. Наличие методов и т.д. не делает обязательным наследование в том виде, в котором вы его изначально попытались сделать. Тем более, если у вас будет два видж…
  • BlinCT
  • 7 августа 2020 г. 9:05

Динамическое заполнение StackLayout в qml

Всем привет. Пытаюсь решить такую задачку, есть TabBar и его кнопки. StackLayout{ currentIndex: tabBar.currentIndex A {id: tabA} B {id: tabB} C {id: tabC} D {id: ta…
М

QML: изменение стиля при наведении и при нажатии на кнопку

enabled = false перестанет быть активной и не будет ни на что реагировать) Хм.. по-моему пробовал такое. Проверю ещё раз после работы. Ура, спасибо большо…
О нас
Услуги
© EVILEG 2015-2020
Рекомендует хостинг TIMEWEB