QLabel signals, linkActivated and linkHovered
-
can't you simply overwrite https://doc.qt.io/qt-5/qwidget.html#enterEvent and https://doc.qt.io/qt-5/qwidget.html#leaveEvent to make your own hovered signal?
-
@J-Hilk , if I was aware of they're existence I would have done so, but the fact that they exist, shouldn't QLabel be correct?
@SPlatten QWidget is the base class of QLabel and its where they are declared
IIRC you also have to set https://doc.qt.io/qt-5/qwidget.html#mouseTracking-prop
to true, to receive the enter and exit events -
@SPlatten QWidget is the base class of QLabel and its where they are declared
IIRC you also have to set https://doc.qt.io/qt-5/qwidget.html#mouseTracking-prop
to true, to receive the enter and exit events -
@SPlatten said in QLabel signals, linkActivated and linkHovered:
<a href="http://google.com" style="color:#000000;text-decoration:none;">Google</a>
I've tested a QLabel with above content in Windows / Qt5.12.7 (without setting mouseTracking prop).
When I move the mouse to "Google", I get the firstlinkHovered("http://google.com")
.
Then I move the mouse out of "Google", there is alinkHovered("")
.
So when I move the mouse back to "Google" again, there is anotherlinkHovered("http://google.com")
.
Everything seems fine to me. -
@SPlatten said in QLabel signals, linkActivated and linkHovered:
<a href="http://google.com" style="color:#000000;text-decoration:none;">Google</a>
I've tested a QLabel with above content in Windows / Qt5.12.7 (without setting mouseTracking prop).
When I move the mouse to "Google", I get the firstlinkHovered("http://google.com")
.
Then I move the mouse out of "Google", there is alinkHovered("")
.
So when I move the mouse back to "Google" again, there is anotherlinkHovered("http://google.com")
.
Everything seems fine to me. -
@Bonnie , can you please post a snippet of your code than I can compare, as I really haven't done anything other than create the label and set-up the connection.
I'm using Qt 5.14.2
@SPlatten Sure, here is my main.cpp
#include <QApplication> #include <QMainWindow> #include <QLabel> #include <QDebug> int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow w; w.resize(320, 240); QLabel* label = new QLabel(&w); QObject::connect(label, &QLabel::linkHovered, [=](const QString& link){ qDebug() << "linkHovered"<<link; }); label->setFrameShape(QFrame::StyledPanel); label->setText("<a href=\"http://google.com\" style=\"color:#000000;text-decoration:none;\">Google</a>"); w.show(); return a.exec(); }
While moving my mouse I get:
linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered ""
-
@SPlatten Sure, here is my main.cpp
#include <QApplication> #include <QMainWindow> #include <QLabel> #include <QDebug> int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow w; w.resize(320, 240); QLabel* label = new QLabel(&w); QObject::connect(label, &QLabel::linkHovered, [=](const QString& link){ qDebug() << "linkHovered"<<link; }); label->setFrameShape(QFrame::StyledPanel); label->setText("<a href=\"http://google.com\" style=\"color:#000000;text-decoration:none;\">Google</a>"); w.show(); return a.exec(); }
While moving my mouse I get:
linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered ""
-
@Bonnie , Thank you, can you try a conventional connect with a slot in C++ as thats what I've been using. Also add a connect for linkActivated too. You should also call:
label->setOpenExternalLinks(true);
@SPlatten
I actually do test in a slot of a subclassed QMainWindow.
Above code is just to make it looks more simple in a single cpp file.
And I also triedsetOpenExternalLinks(true)
, still the same.Here are all the files:
main.cpp:#include <QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.h:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void label_linkHovered(const QString &link); void label_linkActivated(const QString &link); }; #endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h" #include <QLabel> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { resize(320, 240); QLabel *label = new QLabel(this); connect(label, &QLabel::linkHovered, this, &MainWindow::label_linkHovered); connect(label, &QLabel::linkActivated, this, &MainWindow::label_linkActivated); label->setFrameShape(QFrame::StyledPanel); label->setText("<a href=\"http://google.com\" style=\"color:#000000;text-decoration:none;\">Google</a>"); label->setOpenExternalLinks(true); } void MainWindow::label_linkHovered(const QString &link) { qDebug() << "linkHovered" << link; } void MainWindow::label_linkActivated(const QString &link) { qDebug() << "linkActivated" << link; }
Output still:
linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered ""
-
@SPlatten
I actually do test in a slot of a subclassed QMainWindow.
Above code is just to make it looks more simple in a single cpp file.
And I also triedsetOpenExternalLinks(true)
, still the same.Here are all the files:
main.cpp:#include <QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.h:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void label_linkHovered(const QString &link); void label_linkActivated(const QString &link); }; #endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h" #include <QLabel> #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { resize(320, 240); QLabel *label = new QLabel(this); connect(label, &QLabel::linkHovered, this, &MainWindow::label_linkHovered); connect(label, &QLabel::linkActivated, this, &MainWindow::label_linkActivated); label->setFrameShape(QFrame::StyledPanel); label->setText("<a href=\"http://google.com\" style=\"color:#000000;text-decoration:none;\">Google</a>"); label->setOpenExternalLinks(true); } void MainWindow::label_linkHovered(const QString &link) { qDebug() << "linkHovered" << link; } void MainWindow::label_linkActivated(const QString &link) { qDebug() << "linkActivated" << link; }
Output still:
linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered "" linkHovered "http://google.com" linkHovered ""
-
@Bonnie , please add:
connect(label, &QLabel::linkActivated, this, &MainWindow::label_linkActivated);
Just because I have that too, your version of Qt is also quite a lot older than I'm using...apart from that there is no difference.
-
@SPlatten
Fine, I've updated the testing code in the above.
But the output is still the same.
My current project started from 5.12, so I have only 5.12 installed. -
@SPlatten QWidget is the base class of QLabel and its where they are declared
IIRC you also have to set https://doc.qt.io/qt-5/qwidget.html#mouseTracking-prop
to true, to receive the enter and exit events@J-Hilk , I've tried:
cnSignal = QObject::connect(this, &clsQtLabel::enterEvent ,this, &clsQtLabel::rptrEnterEvent);
clsQtLabel is the name of my derived class. The slot:
void clsQtLabel::rptrEnterEvent(QEvent* pEvent) { const QString cstrSignal("enterEvent"); QJsonObject objJSON; if ( mpobjNode->blnCheckSubscribers(cstrSignal, &objJSON) == true ) { QJsonObject objParam; //objParam["event"] = strLink; objJSON[clsXMLnode::mscszAttrParameters] = objParam; emit mpobjNode->commonRptdSignal(objJSON); } }
Something is wrong because the connect returns null and does not connect. This is from:
```
QMetaObject::Connection clsQtLabel::connect(clsSignal* pobjSignal) {
QMetaObject::Connection cnSignal;
if ( pobjSignal == nullptr ) {
//Cannot proceed without signal or subscriber, abort!
return cnSignal;
}
QString strSignal = pobjSignal->strGetSignal();
if ( strSignal.compare(clsQtLabel::mscszQtSignalEnterEvent) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::enterEvent
,this, &clsQtLabel::rptrEnterEvent);
} else if ( strSignal.compare(clsQtLabel::mscszQtSignalLinkActivated) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::linkActivated
,this, &clsQtLabel::rptrLinkActivated);
} else if ( strSignal.compare(clsQtLabel::mscszQtSignalLinkHovered) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::linkHovered
,this, &clsQtLabel::rptrLinkHovered);
}
return cnSignal;
} -
@J-Hilk , I've tried:
cnSignal = QObject::connect(this, &clsQtLabel::enterEvent ,this, &clsQtLabel::rptrEnterEvent);
clsQtLabel is the name of my derived class. The slot:
void clsQtLabel::rptrEnterEvent(QEvent* pEvent) { const QString cstrSignal("enterEvent"); QJsonObject objJSON; if ( mpobjNode->blnCheckSubscribers(cstrSignal, &objJSON) == true ) { QJsonObject objParam; //objParam["event"] = strLink; objJSON[clsXMLnode::mscszAttrParameters] = objParam; emit mpobjNode->commonRptdSignal(objJSON); } }
Something is wrong because the connect returns null and does not connect. This is from:
```
QMetaObject::Connection clsQtLabel::connect(clsSignal* pobjSignal) {
QMetaObject::Connection cnSignal;
if ( pobjSignal == nullptr ) {
//Cannot proceed without signal or subscriber, abort!
return cnSignal;
}
QString strSignal = pobjSignal->strGetSignal();
if ( strSignal.compare(clsQtLabel::mscszQtSignalEnterEvent) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::enterEvent
,this, &clsQtLabel::rptrEnterEvent);
} else if ( strSignal.compare(clsQtLabel::mscszQtSignalLinkActivated) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::linkActivated
,this, &clsQtLabel::rptrLinkActivated);
} else if ( strSignal.compare(clsQtLabel::mscszQtSignalLinkHovered) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::linkHovered
,this, &clsQtLabel::rptrLinkHovered);
}
return cnSignal;
} -
@J-Hilk , I've tried:
cnSignal = QObject::connect(this, &clsQtLabel::enterEvent ,this, &clsQtLabel::rptrEnterEvent);
clsQtLabel is the name of my derived class. The slot:
void clsQtLabel::rptrEnterEvent(QEvent* pEvent) { const QString cstrSignal("enterEvent"); QJsonObject objJSON; if ( mpobjNode->blnCheckSubscribers(cstrSignal, &objJSON) == true ) { QJsonObject objParam; //objParam["event"] = strLink; objJSON[clsXMLnode::mscszAttrParameters] = objParam; emit mpobjNode->commonRptdSignal(objJSON); } }
Something is wrong because the connect returns null and does not connect. This is from:
```
QMetaObject::Connection clsQtLabel::connect(clsSignal* pobjSignal) {
QMetaObject::Connection cnSignal;
if ( pobjSignal == nullptr ) {
//Cannot proceed without signal or subscriber, abort!
return cnSignal;
}
QString strSignal = pobjSignal->strGetSignal();
if ( strSignal.compare(clsQtLabel::mscszQtSignalEnterEvent) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::enterEvent
,this, &clsQtLabel::rptrEnterEvent);
} else if ( strSignal.compare(clsQtLabel::mscszQtSignalLinkActivated) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::linkActivated
,this, &clsQtLabel::rptrLinkActivated);
} else if ( strSignal.compare(clsQtLabel::mscszQtSignalLinkHovered) == 0 ) {
cnSignal = QObject::connect(this, &clsQtLabel::linkHovered
,this, &clsQtLabel::rptrLinkHovered);
}
return cnSignal;
} -
@SPlatten
Hi
enter and leave events are virtual functions and not signals.
hehe ninjaed by @J-Hilk :) -
@SPlatten
That is just normal OOP.
Also, one can subclass and emit a signal in those event handlers to have it as signals also.
But default its not signals :) -
@mrjj , what I meant was why do it a different way when signals and slots are used for so much of everything else already?
@SPlatten
well one reason is that signal and slot cannot return values as such.
So it wont be useful for normal OOP where you overwrite virtual functions to alter logic.
Its not easy to do with signals alone. Also very, very often you want to call base class version of the function you overrride as you only want to extend it and keep old logic too and in this case a signal system would be very clunky.btw. in your use case if you want hover events but dont feel like subclassing. you could use eventfilter and cheat that way.
-
@SPlatten
well one reason is that signal and slot cannot return values as such.
So it wont be useful for normal OOP where you overwrite virtual functions to alter logic.
Its not easy to do with signals alone. Also very, very often you want to call base class version of the function you overrride as you only want to extend it and keep old logic too and in this case a signal system would be very clunky.btw. in your use case if you want hover events but dont feel like subclassing. you could use eventfilter and cheat that way.
-
@mrjj , thanks, I'm no newb when it comes to coding, but in this case I fail to see why enterEvent couldn't be a signal, its perfect for it.