Lassen Sie uns nun ein wenig über das Vererben von QGraphicsItem und die Verwendung des SIGNAL und SLOT s-Systems bei der Interaktion mit Grafikobjekten in der Grafikszene QGraphicsScene. Das Ziel dieser Lektion besteht darin, eine Anwendung zu erstellen, in der ein Objekt der Klasse QGraphicsItem in der Grafikszene angezeigt wird, indem auf das Dialogfeld QMessageBox erscheint und signalisiert das Ereignis des Klickens auf das Grafikobjekt ...
Der Programmcode wurde in QtCreator 3.3.1 basierend auf Qt 5.4.1 geschrieben.
Projektstruktur für die Arbeit mit QGraphicsItem
Die Struktur dieses Projekts umfasst:
- TestPoint.pro - Projektprofil;
- mainwindow.h - Header-Datei des Hauptanwendungsfensters;
- mainwindow.cpp - Quellcodedatei für das Hauptanwendungsfenster;
- mypoint.h - Header-Code der Klasse, die von QGraphicsItem geerbt wurde;
- mypoint.cpp - bzw. der Quellcode;
- main.cpp - die Hauptdatei, von der aus die Anwendung startet, wird in der Lektion nicht berücksichtigt, da sie standardmäßig erstellt wird;
- mainwindow.ui - Designdatei für das Hauptfenster.
mainwindow.ui
Die ganze Arbeit mit dieser Datei besteht darin, dass wir das Widget QGraphicsView in die Mitte des Hauptfensters werfen und es auf die Breite und Höhe des Fensters strecken.
mainwindow.h
Die Datei ist nur für die Deklaration der Grafikszene, unserer neuen Klasse MyPoint und dem SLOT für die Verarbeitung des SIGNALS von MyPoint bekannt.
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QGraphicsScene> #include <QMessageBox> #include <mypoint.h> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; /* Объявляем графическую сцену и Точку с которой будем работать */ QGraphicsScene *scene; MyPoint *point; private slots: /* Слот для обработки сигнала из точки */ void slotFromPoint(); }; #endif // MAINWINDOW_H
mainwindow.cpp
Hier ist es schon interessanter. In dieser Datei führen wir die Implementierung eines SLOTs aus und verbinden dieses SLOT auch mit einem Objekt der Klasse MyPoint. Und fügen dieses Objekt auch der Grafikszene hinzu.
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); /* Инициализируем графическую сцену с точку с которой будем работать */ scene = new QGraphicsScene(); point = new MyPoint(); /* Подключаем сигнал из точки к СЛОТу в главном классе */ connect(point,SIGNAL(signal1()),this, SLOT(slotFromPoint())); /* Устанавливаем графическую сцену в виджет */ ui->graphicsView->setScene(scene); scene->addItem(point); // И добавляем на сцену точку } MainWindow::~MainWindow() { delete ui; } void MainWindow::slotFromPoint() { QMessageBox::information(this, "Зафиксировано нажатие", "Вы нажали на точку!!!" "\n" "\n" "\n С Уважением, Ваш КЭП!!!"); }
mypoint.h
Der entscheidende Punkt in dieser Datei ist, dass diese Klasse Mehrfachvererbung verwendet, nämlich dass wir nicht nur von QGraphicsItem geerbt haben, sondern auch von QObject. Der Punkt ist, dass, wenn Sie nicht von QObject erben, dann funktionieren SINGALS und SLOTS nicht und das Projekt wird nicht kompiliert, wenn Sie die Funktion connect verwenden, um das SIGNAL von MyPoint, mit dem SLOT in MainWindow zu verbinden.
#ifndef MYPOINT_H #define MYPOINT_H #include <QObject> #include <QGraphicsItem> #include <QPainter> /* Чтобы работали СЛОТЫ и СИГНАЛЫ, наследуемся от QOBJECT, * */ class MyPoint : public QObject, public QGraphicsItem { Q_OBJECT public: explicit MyPoint(QObject *parent = 0); ~MyPoint(); signals: /* Сигнал, который будет посылаться в том случае, * если произошел клик мышью по объекту * */ void signal1(); protected: /* Перегружаем метод нажатия мышью, для его перехвата * */ void mousePressEvent(QGraphicsSceneMouseEvent *event); private: /* Данные методы виртуальные, поэтому их необходимо реализовать * в случае наследования от QGraphicsItem * */ QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); }; #endif // MYPOINT_H
mypoint.cpp
Das Wichtigste, was ich in dieser Klasse zu beachten empfehle, ist, dass wir die Methode überschreiben, um das Ereignis des Klickens auf das Grafikobjekt mit der rechten Maustaste aufzurufen. Und wir nennen das SIGNAL in dieser Methode.
#include "mypoint.h" MyPoint::MyPoint(QObject *parent) : QObject(parent), QGraphicsItem() { } MyPoint::~MyPoint() { } QRectF MyPoint::boundingRect() const { /* возвращаем координаты расположения точки * по ним будет определяться нажатие точки * */ return QRectF(0,0,100,100); } void MyPoint::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { // Устанавливаем кисть в QPainter и отрисовываем круг, то есть ТОЧКУ painter->setBrush(Qt::black); painter->drawEllipse(QRectF(0, 0, 100, 100)); Q_UNUSED(option); Q_UNUSED(widget); } /* Переопределив метод перехвата события нажатия кнопки мыши, * добавляем посылку СИГНАЛА от объекта * */ void MyPoint::mousePressEvent(QGraphicsSceneMouseEvent *event) { emit signal1(); // Вызываем родительскую функцию события нажатия кнопки мыши QGraphicsItem::mousePressEvent(event); }
Ergebnis
Als Ergebnis sollten Sie die folgende Anwendung erhalten, die einen schwarzen Kreis im Fenster anzeigt, wenn Sie darauf klicken, öffnet sich ein Dialogfeld. Sie können sich auch das Video-Tutorial zu diesem Artikel ansehen, das eine Demonstration der Anwendung zeigt und zusätzliche Erklärungen zum Programmcode bietet.
Здравствуйте. А где описание функции signal1()?
Добрый день. Вы имели ввиду реализацию? Для сигналов в Qt реализация не пишется, это всё генерируется в moc файлах под капотом Qt.
Спасибо за ответ) У меня компоновщик на нее ругался просто. Оказалось, просто забыл Q_OBJECT в начале класса указать.