Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels
-
wrote on 21 Mar 2023, 17:43 last edited by
I am working on a Qt application that contains multiple labels, and upon clicking on a label, its background color should change to a previously selected color. However, I am facing two issues:
When I click on a label, the mouse pointer becomes stuck on that label, and I am unable to click on other nearby labels.
The labels surrounding the clicked label do not change their background color, only the clicked label changes its color.
The code is based on the HandLabel class, which inherits from QLabel. The mousePressEvent() method is responsible for changing the color of the label upon clicking it, and the onbgColorChanged() method is called to change the color when a new color is selected. Additionally, the enterEvent() and leaveEvent() methods enable and disable mouse tracking, and the mouseMoveEvent() method is for debugging purposes only.
I would appreciate any help in resolving these issues.
#include "HandLabel.h" HandLabel::HandLabel(const QString &text, QWidget *parent, Qt::WindowFlags f) : QLabel(text, parent, f) { connect(parent, SIGNAL(bgColorChanged(QColor)), this, SLOT(onbgColorChanged(QColor))); setAlignment(Qt::AlignCenter); setFrameStyle(QFrame::Panel | QFrame::Sunken); setAutoFillBackground(true); } void HandLabel::onbgColorChanged(QColor newColor) { setBgColor(newColor); } void HandLabel::mousePressEvent(QMouseEvent *event) { Q_UNUSED(event); QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor == selectedColor) { pal.setColor(QPalette::Window, Qt::transparent); } else { pal.setColor(QPalette::Window, m_bgColor); } setPalette(pal); } void HandLabel::mouseMoveEvent(QMouseEvent *event) { qDebug() << event; } void HandLabel::enterEvent(QEnterEvent *event) { QLabel::enterEvent(event); // chama o enterEvent da classe base setMouseTracking(true); // habilita o rastreamento do mouse if (event->buttons() & Qt::LeftButton) { QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor != selectedColor) { pal.setColor(QPalette::Window, m_bgColor); setPalette(pal); } } } void HandLabel::leaveEvent(QEvent *event) { QLabel::leaveEvent(event); // chama o leaveEvent da classe base setMouseTracking(false); // desabilita o rastreamento do mouse } QColor HandLabel::bgColor() const { return m_bgColor; } void HandLabel::setBgColor(const QColor &newBgColor) { m_bgColor = newBgColor; }
-
void HandLabel::dragEnterEvent(QDragEnterEvent *event) { qDebug() << event; QLabel::dragEnterEvent(event); } void HandLabel::dragMoveEvent(QDragMoveEvent *event) { qDebug() << event; QLabel::dragMoveEvent(event); }
Thanks for your help, but it doesn't appear in the debug when I add the two functions :(
I managed to do something similar in React + JS but I put the lstenner in the parent layout which is not possible here since the parent layout is a grid and has no mouse properties
wrote on 22 Mar 2023, 10:35 last edited by mpergand@Collaxd
Seems to work:class Label : public QLabel { public: Label(const QString& text, QWidget* parent=nullptr) : QLabel(text,parent) { setFrameStyle(QFrame::Panel | QFrame::Sunken); setAcceptDrops(true); } void mousePressEvent(QMouseEvent *ev) override { qDebug()<<Q_FUNC_INFO; QLabel::mousePressEvent(ev); } void mouseMoveEvent(QMouseEvent *ev) override { qDebug()<<Q_FUNC_INFO; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setText(""); drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::MoveAction); if( dropAction == Qt::IgnoreAction ) { qDebug()<<"end drag"; drag->deleteLater(); } } void dragEnterEvent(QDragEnterEvent* ev ) override { qDebug()<<Q_FUNC_INFO; ev->acceptProposedAction(); } void dragMoveEvent(QDragMoveEvent* ev ) override { qDebug()<<Q_FUNC_INFO<<ev->source()<<this; } };
Each Label receives dragMoveEvent when the mouse is over.
Looks promising, have a look at the doc about drag&drop:
https://doc.qt.io/qt-5/dnd.html -
I am working on a Qt application that contains multiple labels, and upon clicking on a label, its background color should change to a previously selected color. However, I am facing two issues:
When I click on a label, the mouse pointer becomes stuck on that label, and I am unable to click on other nearby labels.
The labels surrounding the clicked label do not change their background color, only the clicked label changes its color.
The code is based on the HandLabel class, which inherits from QLabel. The mousePressEvent() method is responsible for changing the color of the label upon clicking it, and the onbgColorChanged() method is called to change the color when a new color is selected. Additionally, the enterEvent() and leaveEvent() methods enable and disable mouse tracking, and the mouseMoveEvent() method is for debugging purposes only.
I would appreciate any help in resolving these issues.
#include "HandLabel.h" HandLabel::HandLabel(const QString &text, QWidget *parent, Qt::WindowFlags f) : QLabel(text, parent, f) { connect(parent, SIGNAL(bgColorChanged(QColor)), this, SLOT(onbgColorChanged(QColor))); setAlignment(Qt::AlignCenter); setFrameStyle(QFrame::Panel | QFrame::Sunken); setAutoFillBackground(true); } void HandLabel::onbgColorChanged(QColor newColor) { setBgColor(newColor); } void HandLabel::mousePressEvent(QMouseEvent *event) { Q_UNUSED(event); QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor == selectedColor) { pal.setColor(QPalette::Window, Qt::transparent); } else { pal.setColor(QPalette::Window, m_bgColor); } setPalette(pal); } void HandLabel::mouseMoveEvent(QMouseEvent *event) { qDebug() << event; } void HandLabel::enterEvent(QEnterEvent *event) { QLabel::enterEvent(event); // chama o enterEvent da classe base setMouseTracking(true); // habilita o rastreamento do mouse if (event->buttons() & Qt::LeftButton) { QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor != selectedColor) { pal.setColor(QPalette::Window, m_bgColor); setPalette(pal); } } } void HandLabel::leaveEvent(QEvent *event) { QLabel::leaveEvent(event); // chama o leaveEvent da classe base setMouseTracking(false); // desabilita o rastreamento do mouse } QColor HandLabel::bgColor() const { return m_bgColor; } void HandLabel::setBgColor(const QColor &newBgColor) { m_bgColor = newBgColor; }
wrote on 21 Mar 2023, 18:34 last edited by@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
When I click on a label, the mouse pointer becomes stuck on that label, and I am unable to click on other nearby labels.
Maybe because you do not call the base class implementation for your
mouse...Event()
overrides?
Separately I don't know whetherqDebug()
output on every mouse move makes it sluggish. -
@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
When I click on a label, the mouse pointer becomes stuck on that label, and I am unable to click on other nearby labels.
Maybe because you do not call the base class implementation for your
mouse...Event()
overrides?
Separately I don't know whetherqDebug()
output on every mouse move makes it sluggish.wrote on 21 Mar 2023, 19:56 last edited byprotected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void enterEvent(QEnterEvent *event) override; void leaveEvent(QEvent *event) override;
thanks for your answer yes and it does everything just using override, any suggestions?
-
protected: void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void enterEvent(QEnterEvent *event) override; void leaveEvent(QEvent *event) override;
thanks for your answer yes and it does everything just using override, any suggestions?
Hi,
@JonB was not talking about the declaration of the functions but calling the base class implementation in your reimplementation.
On an unrelated note, your use of parent to do the connection in the constructor is bad. That connection should happen in the parent. A child widget should know nothing about its parent.
-
Hi,
@JonB was not talking about the declaration of the functions but calling the base class implementation in your reimplementation.
On an unrelated note, your use of parent to do the connection in the constructor is bad. That connection should happen in the parent. A child widget should know nothing about its parent.
wrote on 21 Mar 2023, 20:07 last edited by Collaxd@SGaist
thanks for your answer. I understand better now, I'm learning and I don't know how the best declaration was, so I chose to do it inside the child, but now I've implemented it in the creation of the labels
but the problem persistsSorry but I still can't understand the implementation part, I'm a little new to cpp sorry
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_hands (readHands()) { ui->setupUi(this); int row=0; int col=0; foreach (QString hand, m_hands) { m_label = new HandLabel(hand, this); connect(this, SIGNAL(bgColorChanged(QColor)), m_label, SLOT(onbgColorChanged(QColor))); ui->handsContainer->addWidget(m_label, row, col); if (col < 12) col++; else { col=0; row++; } } emit bgColorChanged(Qt::yellow); }```
-
@SGaist
thanks for your answer. I understand better now, I'm learning and I don't know how the best declaration was, so I chose to do it inside the child, but now I've implemented it in the creation of the labels
but the problem persistsSorry but I still can't understand the implementation part, I'm a little new to cpp sorry
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) , m_hands (readHands()) { ui->setupUi(this); int row=0; int col=0; foreach (QString hand, m_hands) { m_label = new HandLabel(hand, this); connect(this, SIGNAL(bgColorChanged(QColor)), m_label, SLOT(onbgColorChanged(QColor))); ui->handsContainer->addWidget(m_label, row, col); if (col < 12) col++; else { col=0; row++; } } emit bgColorChanged(Qt::yellow); }```
-
wrote on 21 Mar 2023, 20:17 last edited by
@SGaist said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
For your issue: do you know what "calling the base class implementation" means ? That's key to answer @JonB's question.
no, i even asked gpt chat and tried to learn but i don't understand what jon is getting at, could you simplify the question so i can improve my example?
-
@SGaist said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
For your issue: do you know what "calling the base class implementation" means ? That's key to answer @JonB's question.
no, i even asked gpt chat and tried to learn but i don't understand what jon is getting at, could you simplify the question so i can improve my example?
@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
no, i even asked gpt chat
I really wonder where such stuff will end... very staggering.
When you don't want to read a good c++ book then you can ask google for 'calling the base class implementation'.
-
@SGaist said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
For your issue: do you know what "calling the base class implementation" means ? That's key to answer @JonB's question.
no, i even asked gpt chat and tried to learn but i don't understand what jon is getting at, could you simplify the question so i can improve my example?
wrote on 21 Mar 2023, 20:22 last edited byvoid HandLabel::mousePressEvent(QMouseEvent *event) { Q_UNUSED(event); QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor == selectedColor) { pal.setColor(QPalette::Window, Qt::transparent); } else { pal.setColor(QPalette::Window, m_bgColor); } setPalette(pal); /* something like this */ QLabel::mousePressEvent( event ); }
-
@SGaist said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
For your issue: do you know what "calling the base class implementation" means ? That's key to answer @JonB's question.
no, i even asked gpt chat and tried to learn but i don't understand what jon is getting at, could you simplify the question so i can improve my example?
@Collaxd you better go with a good old fashioned cpp tutorial about that very subject.
-
@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
no, i even asked gpt chat
I really wonder where such stuff will end... very staggering.
When you don't want to read a good c++ book then you can ask google for 'calling the base class implementation'.
wrote on 21 Mar 2023, 20:30 last edited by Collaxd@Christian-Ehrlicher
Thank you, friends. I really didn't mean to offend when I mentioned the chat. In fact, I'm just a veterinarian enthusiast in programming trying to learn some things. I'll do more research. -
@Christian-Ehrlicher
Thank you, friends. I really didn't mean to offend when I mentioned the chat. In fact, I'm just a veterinarian enthusiast in programming trying to learn some things. I'll do more research.wrote on 21 Mar 2023, 21:27 last edited by JonB@Collaxd
No offence taken.In, say, your
HandLabel::enterEvent()
overridden method you callQLabel::enterEvent(event); // chama o enterEvent da classe base
Same for
leaveEvent()
. It allows whatever the class you derive from to see these events and act on them, as well as your own code.I would guess you need to do the same for your
HandLabel::mousePressEvent()
. I would let it callQLabel::mousePressEvent(event)
, as well as your code. Maybe also formouseMoveEvent()
. Does that help with yourWhen I click on a label, the mouse pointer becomes stuck on that label, and I am unable to click on other nearby labels.
?
-
@Collaxd
No offence taken.In, say, your
HandLabel::enterEvent()
overridden method you callQLabel::enterEvent(event); // chama o enterEvent da classe base
Same for
leaveEvent()
. It allows whatever the class you derive from to see these events and act on them, as well as your own code.I would guess you need to do the same for your
HandLabel::mousePressEvent()
. I would let it callQLabel::mousePressEvent(event)
, as well as your code. Maybe also formouseMoveEvent()
. Does that help with yourWhen I click on a label, the mouse pointer becomes stuck on that label, and I am unable to click on other nearby labels.
?
wrote on 21 Mar 2023, 22:14 last edited by Collaxd@JonB
Perfect, thanks for your understanding and help, but even when calling the base event, the mouse is still 'stuck' on the initial click label, I can do something just with enter, it also serves my purpose, but it doesn't work in the same wayHere's an example of how my code is and an app I want to 'imitate' with it working
#include "HandLabel.h" #include <qapplication.h> HandLabel::HandLabel(const QString &text, QWidget *parent, Qt::WindowFlags f) : QLabel(text, parent, f) { setAlignment(Qt::AlignCenter); setFrameStyle(QFrame::Panel | QFrame::Sunken); setAutoFillBackground(true); } void HandLabel::onbgColorChanged(QColor newColor) { setBgColor(newColor); } void HandLabel::mousePressEvent(QMouseEvent *event) { QLabel::mousePressEvent(event); // chama o mousePressEvent da classe base if (event->buttons() & Qt::LeftButton) updateBackground(); } void HandLabel::mouseMoveEvent(QMouseEvent *event) { QLabel::mouseMoveEvent(event); qDebug() << event; // updateBackground(); } void HandLabel::enterEvent(QEnterEvent *event) { QLabel::enterEvent(event); // chama o enterEvent da classe base updateBackground(); setMouseTracking(true); } void HandLabel::leaveEvent(QEvent *event) { QLabel::leaveEvent(event); // chama o leaveEvent da classe base // emite um evento mouseReleaseEvent setMouseTracking(false); } void HandLabel::updateBackground() { QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor == selectedColor) pal.setColor(QPalette::Window, Qt::transparent); else pal.setColor(QPalette::Window, m_bgColor); setPalette(pal); } QColor HandLabel::bgColor() const { return m_bgColor; } void HandLabel::setBgColor(const QColor &newBgColor) { m_bgColor = newBgColor; }
-
@JonB
Perfect, thanks for your understanding and help, but even when calling the base event, the mouse is still 'stuck' on the initial click label, I can do something just with enter, it also serves my purpose, but it doesn't work in the same wayHere's an example of how my code is and an app I want to 'imitate' with it working
#include "HandLabel.h" #include <qapplication.h> HandLabel::HandLabel(const QString &text, QWidget *parent, Qt::WindowFlags f) : QLabel(text, parent, f) { setAlignment(Qt::AlignCenter); setFrameStyle(QFrame::Panel | QFrame::Sunken); setAutoFillBackground(true); } void HandLabel::onbgColorChanged(QColor newColor) { setBgColor(newColor); } void HandLabel::mousePressEvent(QMouseEvent *event) { QLabel::mousePressEvent(event); // chama o mousePressEvent da classe base if (event->buttons() & Qt::LeftButton) updateBackground(); } void HandLabel::mouseMoveEvent(QMouseEvent *event) { QLabel::mouseMoveEvent(event); qDebug() << event; // updateBackground(); } void HandLabel::enterEvent(QEnterEvent *event) { QLabel::enterEvent(event); // chama o enterEvent da classe base updateBackground(); setMouseTracking(true); } void HandLabel::leaveEvent(QEvent *event) { QLabel::leaveEvent(event); // chama o leaveEvent da classe base // emite um evento mouseReleaseEvent setMouseTracking(false); } void HandLabel::updateBackground() { QPalette pal = palette(); QColor selectedColor = pal.color(QPalette::Window); if (m_bgColor == selectedColor) pal.setColor(QPalette::Window, Qt::transparent); else pal.setColor(QPalette::Window, m_bgColor); setPalette(pal); } QColor HandLabel::bgColor() const { return m_bgColor; } void HandLabel::setBgColor(const QColor &newBgColor) { m_bgColor = newBgColor; }
wrote on 21 Mar 2023, 22:41 last edited by mpergand@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
he mouse is still 'stuck' on the initial click label,
I think you should use dragEnterEvent & dragMoveEvent instead of enterEvent, if you want to select muti objects while mouse press.
-
@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
he mouse is still 'stuck' on the initial click label,
I think you should use dragEnterEvent & dragMoveEvent instead of enterEvent, if you want to select muti objects while mouse press.
wrote on 22 Mar 2023, 01:01 last edited by Collaxdvoid HandLabel::dragEnterEvent(QDragEnterEvent *event) { qDebug() << event; QLabel::dragEnterEvent(event); } void HandLabel::dragMoveEvent(QDragMoveEvent *event) { qDebug() << event; QLabel::dragMoveEvent(event); }
Thanks for your help, but it doesn't appear in the debug when I add the two functions :(
I managed to do something similar in React + JS but I put the lstenner in the parent layout which is not possible here since the parent layout is a grid and has no mouse properties
-
void HandLabel::dragEnterEvent(QDragEnterEvent *event) { qDebug() << event; QLabel::dragEnterEvent(event); } void HandLabel::dragMoveEvent(QDragMoveEvent *event) { qDebug() << event; QLabel::dragMoveEvent(event); }
Thanks for your help, but it doesn't appear in the debug when I add the two functions :(
I managed to do something similar in React + JS but I put the lstenner in the parent layout which is not possible here since the parent layout is a grid and has no mouse properties
wrote on 22 Mar 2023, 10:35 last edited by mpergand@Collaxd
Seems to work:class Label : public QLabel { public: Label(const QString& text, QWidget* parent=nullptr) : QLabel(text,parent) { setFrameStyle(QFrame::Panel | QFrame::Sunken); setAcceptDrops(true); } void mousePressEvent(QMouseEvent *ev) override { qDebug()<<Q_FUNC_INFO; QLabel::mousePressEvent(ev); } void mouseMoveEvent(QMouseEvent *ev) override { qDebug()<<Q_FUNC_INFO; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setText(""); drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::MoveAction); if( dropAction == Qt::IgnoreAction ) { qDebug()<<"end drag"; drag->deleteLater(); } } void dragEnterEvent(QDragEnterEvent* ev ) override { qDebug()<<Q_FUNC_INFO; ev->acceptProposedAction(); } void dragMoveEvent(QDragMoveEvent* ev ) override { qDebug()<<Q_FUNC_INFO<<ev->source()<<this; } };
Each Label receives dragMoveEvent when the mouse is over.
Looks promising, have a look at the doc about drag&drop:
https://doc.qt.io/qt-5/dnd.html -
@Collaxd
Seems to work:class Label : public QLabel { public: Label(const QString& text, QWidget* parent=nullptr) : QLabel(text,parent) { setFrameStyle(QFrame::Panel | QFrame::Sunken); setAcceptDrops(true); } void mousePressEvent(QMouseEvent *ev) override { qDebug()<<Q_FUNC_INFO; QLabel::mousePressEvent(ev); } void mouseMoveEvent(QMouseEvent *ev) override { qDebug()<<Q_FUNC_INFO; QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; mimeData->setText(""); drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::MoveAction); if( dropAction == Qt::IgnoreAction ) { qDebug()<<"end drag"; drag->deleteLater(); } } void dragEnterEvent(QDragEnterEvent* ev ) override { qDebug()<<Q_FUNC_INFO; ev->acceptProposedAction(); } void dragMoveEvent(QDragMoveEvent* ev ) override { qDebug()<<Q_FUNC_INFO<<ev->source()<<this; } };
Each Label receives dragMoveEvent when the mouse is over.
Looks promising, have a look at the doc about drag&drop:
https://doc.qt.io/qt-5/dnd.htmlwrote on 23 Mar 2023, 01:56 last edited by@mpergand
I would like to thank you very much for your solution, it was a success! I've been searching for days and couldn't find anything similar, which generated a lot of learning and made me realize that I still have a lot to study!For future readers, here is the solution:
void HandLabel::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event); QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::MoveAction); if( dropAction == Qt::IgnoreAction ) { drag->deleteLater(); } } void HandLabel::dragEnterEvent(QDragEnterEvent *event) { Q_UNUSED(event); updateColorScheme(); }
Despite the mouse having a 'block' symbol, the colors are working perfectly!
-
-
@mpergand
I would like to thank you very much for your solution, it was a success! I've been searching for days and couldn't find anything similar, which generated a lot of learning and made me realize that I still have a lot to study!For future readers, here is the solution:
void HandLabel::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event); QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; drag->setMimeData(mimeData); Qt::DropAction dropAction = drag->exec(Qt::MoveAction); if( dropAction == Qt::IgnoreAction ) { drag->deleteLater(); } } void HandLabel::dragEnterEvent(QDragEnterEvent *event) { Q_UNUSED(event); updateColorScheme(); }
Despite the mouse having a 'block' symbol, the colors are working perfectly!
wrote on 23 Mar 2023, 11:16 last edited by mpergand@Collaxd said in Mouse Pointer and Label Background Coloring in Qt Application with Multiple Labels:
void HandLabel::dragEnterEvent(QDragEnterEvent *event)
{
Q_UNUSED(event);
updateColorScheme();
}Oh, miss that drag enter is call for each label !
Even easier that I imagined.Despite the mouse having a 'block' symbol, the colors are working perfectly!
You need to call ev->acceptProposedAction();
for that symbol to not appear.
1/18