Interfaces zeichnen, Datenbanktabellen bilden, mit dem Netzwerk arbeiten ist alles gut, aber manchmal möchte man einfach nur etwas zeichnen, zum Beispiel ein Dreieck . Und dann natürlich dieses Objekt animieren, damit es gesteuert werden kann, und dieses Projekt anschließend in ein kleines Spiel verwandeln. Wer möchte nicht sein eigenes Spiel schreiben, selbst das einfachste?
Machen wir dann den ersten Schritt zu einem einfachen Spiel, nämlich das Zeichnen von Objekten in Qt, indem wir versuchen, ein Dreieck zu zeichnen.
Der Programmcode wurde in QtCreator 3.3.1 basierend auf Qt 5.4.1 geschrieben.
Die Struktur des Projekts "Triangle"
Beschreiben wir die Struktur des Projekts, in dem wir ein Dreieck zeichnen:
- Triangle.pro - Projektprofil, standardmäßig erstellt und erfordert keine Anpassungen in diesem Projekt;
- main.cpp - die Datei, aus der die Anwendung startet, in dieser Datei wird das Widget aufgerufen, in dem sich die grafische Szene mit dem Dreieck befindet;
- widget.h - Header-Datei des aufgerufenen Widgets mit einer grafischen Szene;
- widget.cpp - Quellcodedatei des Widgets;
- Triangle.h - Header-Datei der Klasse Triangle , die von QGraphicsItem geerbt wird;
- Triangle.cpp - Quellcodedatei für die Klasse Triangle.
mainwindow.ui
Werfen Sie im Interface-Designer einfach QGraphicsView in das Widget. Nichts anderes ist erforderlich.
widget.h
In dieser Datei deklarieren wir nur die Grafikszene und das Dreiecksobjekt, mit dem wir arbeiten werden.
#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
In dieser Datei werden QGraphicsView , QGraphicsScene, Objekte konfiguriert und auch ein Dreiecksobjekt erstellt und in der Grafikszene installiert.
#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; }
dreieck.h
Aber jetzt ist es an der Zeit, an der Klasse selbst zu arbeiten, in der das Dreieck erstellt wird. In diesem Fall erben wir von 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
Dreieck.cpp
Jetzt zeichnen wir in unserer Klasse ein Dreieck. Hier gibt es einen wichtigen Punkt. Das Koordinatensystem des QGraphicsItem -Objekts ist ein anderes Konzept als das Koordinatensystem der Grafikszene. Das heißt, jedes Objekt QGraphicsItem oder von dieser Klasse geerbt hat sein eigenes Koordinatensystem, das in das QGraphicsScene Koordinatensystem übersetzt wird. Wenn wir die Position festlegen, an der sich das Objekt in der Grafikszene befinden wird, geben wir an, wo sich der Punkt des Grafikobjekts befindet, der die Koordinaten 0 auf der X-Achse und 0 auf der Y-Achse im Koordinatensystem des Objekts hat. Daher ist es wichtig, dass dieser Punkt in der Mitte der Grafik liegt. Dies erleichtert die weitere Arbeit, sofern Sie natürlich nicht bewusst etwas anderes annehmen.
#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); }
Ergebnis
Als Ergebnis sollten Sie eine Anwendung haben, die ein rotes Dreieck in der Mitte der Grafikszene am Schnittpunkt zweier Linien anzeigt, wie in der Abbildung gezeigt.
Ich empfehle Ihnen auch, sich mit dem Video-Tutorial vertraut zu machen, in dem der Moment beim Einstellen der Koordinaten eines Grafikobjekts genauer betrachtet wird.
Евгений, здравствуйте!
Решил поэкспериментировать немного с кодом из этого урока, нарисовать вместо треугольника квадрат и разобраться с координатами. В итоге, запутался. И ни документация, ни доп.литература не помогла.
Проблема, собственно, в следующем. Когда я делаю графическую форму, компоную графические слои и виджеты, я получаю размеры.
Дальше берём сам код:
в первой строке мы задаём размеры виджета, но если их поменять, то сам его размер не изменяется, а изменения происходят, если поменять нижнюю строчку. Почему так?
Получается вот так:
Далее вот эти строчки:
Изменяя размеры в scene->setSceneRect(), визуально ничего не меняется. Почему?
Это и есть установка размеров области нашего QGraphicsView? Если да- то что за размеры остаются в ui-файле при этом?
Далее, я пытаюсь отрисовать квадрат в классе Map, но он не появляется на сцене, хотя когда я делал на координатах вашего урока, он был. Но как только я начал изменять их, он исчез. И тут я задумался собственно. Я хотел нарисовать квадрат ровно в левом углу сцены, которая имеет координаты (-250,-250), но квадрат так и не появлялся. Только когда я ставил координаты где-то ориенитирочно(-130,-130), то он вставал как раз в левый угол
Еще, я так и не понял что делает функция
Что именно она ограничивает? Думал, что за границы, которые определяет этот метод, нельзя "выйти", т.е, отрисовать квадрат "ЗА" установленными этим методом координатами, но это не так!
В итоге решил поиграться с координатами в графическом файлу ui и квадрат после этого совсем исчез.
Подскажите, что я делаю не так? В чём моя основная ошибка? Может где-то можно об этом почитать поподробнее? Я помню ваши слова, что координаты QGraphicsScene и QGraphicsItem разные, но я всё равно не понимаю как автоматически управлять этими вещами. Например, если я хочу нарисовать сцену и отрисовать на ней квадраты с помощью цикла (к примеру, как в игре "Морской бой"). Мы же должна хорошо понимать и знать координаты сцены и самого объекта отрисовки. Особенно, координаты углов самого объекта.
Заранее благодарю за ответ, Евгений!