Qt: клик мышью по объекту.


Нередко возникают ситуации, когда нам необходимо узнать по какому объекту на экране кликнули мышью и после ожидать от этого объекта определенные действия. Но оригинальные объекты, созданные, например, с помощью класса QLabel, не имеют возможности реагировать на нажатия кнопок мышки. Как быть в такой ситуации и как определить по какому объекту кликнули? Это мы рассмотрим в данной статье.

Объект созданный на основе класса QLabel не испускает сигнала clicked(), соответственно не имеет возможности реагировать на нажатия кнопки мышки. Можно, конечно сделать объект на основе класса QPushButton, но тогда придется изрядно повозиться, чтобы сделать этот объект похожим на QLabel со всеми его методами и свойтвами.

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

Для наглядности напишем программу, где в окне расположим три текстовые метки QLabel разных цветов (синяя, красная и зеленая), а в четвертой метке, которая представляет собой простое текстовое поле будем выводить результат, по какому объекту кликнули мышью, при чем после клика выбранный объект будет уничтожаться.

Итак, создадим файл main.cpp.

 

main.cpp:

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

MainWindow w;

w.show();

return a.exec();

}

 

Теперь мы напишем свой класс-наследник QLabel, реагирующий на клики мышки.

 Пишем заголовочный файл:

mylabel.h:

#ifndef MYLABEL_H

#define MYLABEL_H

#include <QObject>

#include <QWidget>

#include <QLabel>

#include <QMouseEvent>

class MyLabel : public QLabel // Наследуемся от класса QLabel

{

Q_OBJECT

public:

explicit MyLabel(QWidget *parent = nullptr);

signals:

void clicked(QMouseEvent *); // Предусматриваем обработку сигнала clicked()

private:

protected:

void mousePressEvent (QMouseEvent *event);

};

endif // MYLABEL_H

 

Назовем наш класс — MyLabel и унаследуем его от класса QLabel. В файле mylabel.h предусматриваем обработку сигнала clicked(), а также обработку событий мыши mousePressEvent(QMouseEvent *event). Теперь напишем файл mylabel.cpp.

 

mylabel.cpp:

#include "mylabel.h"

MyLabel::MyLabel(QWidget *parent)

: QLabel{parent}

{}

void MyLabel::mousePressEvent(QMouseEvent *event)

{

emit clicked(event);

}

 

В файле mylabel.cpp мы написали обработчик событий мыши при нажатии клавиши mousePressEvent(QMouseEvent *event), который искусственно посылает сигнал clicked().

Вот, в принципе, и вся хитрость. Теперь попробуем всё это применить в нашей программе с кликом по меткам разных цветов. Напишем заголовочный файл mainwindow.h.

 

mainwindow.h:

#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#include "mylabel.h"

class MainWindow : public QMainWindow

{

Q_OBJECT

public:

MainWindow(QWidget *parent = nullptr);

~MainWindow();

private:

MyLabel *redLabel = nullptr; // Красная метка

MyLabel *greenLabel = nullptr; // Зеленая метка

MyLabel *blueLabel = nullptr; // Синяя метка

MyLabel *textLabel = nullptr; // Поле где будут выводится сообщения

};

#endif // MAINWINDOW_H

 

Теперь напишем файл mainwindow.cpp, где реализуем всё задуманное. По клику мышки по метке, она будет уничтожена, а в текстовом поле будет выведена информация о том метка какого цвета была уничтожена. Если кликнем по текстовому полю, то будет выведена соответствующая этому информация.

 

mainwindow.cpp:

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)

: QMainWindow(parent)

{

this->resize(640,480); // Изменяем размеры окна

// Создаем красную метку

redLabel = new MyLabel(this);

redLabel->resize(100,100);

redLabel->move(50,300);

redLabel->setStyleSheet("background-color: red;");

redLabel->show();

// Создаем зеленую метку

greenLabel = new MyLabel(this);

greenLabel->resize(100,100);

greenLabel->move(250,300);

greenLabel->setStyleSheet("background-color: green;");

greenLabel->show();

// Создаем синюю метку

blueLabel = new MyLabel(this);

blueLabel->resize(100,100);

blueLabel->move(450,300);

blueLabel->setStyleSheet("background-color: blue;");

blueLabel->show();

// Создаем текстовое поле для вывода информации

textLabel = new MyLabel(this);

textLabel->resize(400,60);

textLabel->move(120, 100);

textLabel->setStyleSheet("background-color: lightyellow; font-size: 16px;");

textLabel->show();

 // Обрабатываем сигналы clicked() испускаемые метками в лямбда функции

connect(redLabel, &MyLabel::clicked, this, [this]()

{

delete redLabel;

redLabel = nullptr;

textLabel->setText("Уничтожена красная метка !!!");

});

connect(greenLabel, &MyLabel::clicked, this, [this]()

{

delete greenLabel;

greenLabel = nullptr;

textLabel->setText("Уничтожена зеленая метка !!!");

});

connect(blueLabel, &MyLabel::clicked, this, [this]()

{

delete blueLabel;

blueLabel = nullptr;

textLabel->setText("Уничтожена синяя метка !!!");

});

connect(textLabel, &MyLabel::clicked, this, [this]()

{

textLabel->setText("Вы кликнули по текстовому полю !!!");

});

}

MainWindow::~MainWindow()

{

delete textLabel;

textLabel = nullptr;

delete blueLabel;

blueLabel = nullptr;

delete greenLabel;

greenLabel = nullptr;

delete redLabel;

redLabel = nullptr;

}

 

Вот и всё, ниже приводятся скрины результата работы программы:

Поочередно кликаем мышкой по зеленой метке, текстовому полю, красной метке, синей метке:

 

Окно программы:

Кликаем по зеленой метке:

Кликаем по текстовому полю:

Кликаем по красной метке:

Кликаем по синей метке:

 

 



Вернуться назад