Reputation:
I must use hover event on Qt label, but I can't found no information about that.
I try use something like ui->label->setText("<a>ads</a>")
and onLinkHovered
but it's not work correct.
I must change text on hover.
Upvotes: 3
Views: 11414
Reputation: 397
I have found that you can also achieve this through the style sheet.
self.label = QtWidgets.QLabel("Toast")
self.label.setStyleSheet("QLabel{color: white;} QLabel:hover {color: blue;}")
Upvotes: 0
Reputation: 329
If you want to determine whether mouse hovers over text inside the QLabel you can use
void mouseMoveEvent(QMouseEvent* event);
and check inside it whether mouse cursor is in bounding rectangle of text.
void PressLabel::mouseMoveEvent(QMouseEvent* event) {
QRect bRect = getTextComponentRectangle();
m_mouseCoord = event->pos();
if(bRect.contains(event->pos())) {
// Mouse pointer over text.
} else {
// Mouse pointer outside text.
}
QLabel::mouseMoveEvent(event);
}
Turn on mouse tracking for your widget to make mouseMoveEvent
occur also when mouse button is not pressed.
setMouseTracking(true);
And finally the function that does the calculation of text bounding rectangle. Code below take into account some unexpected cases, too. I tried it with Qt 5.9.1.
For calculation of effective indent in negative case refer to http://doc.qt.io/archives/qt-4.8/qlabel.html#indent-prop .
QRect PressLabel::getTextComponentRectangle() const {
if(frameWidth() < 0) {
throw std::runtime_error("Negative frame width.");
}
int effectiveIndent = indent();
int trueMargin = margin();
if(effectiveIndent < 0) {
if(frameWidth() == 0 || margin() > 0) { // (1)
effectiveIndent = 0;
} else if(frameWidth() > 0) {
QFontMetrics fm(font());
effectiveIndent = fm.width(QChar('x')) / 2;
}
if(frameWidth() > 0 && margin() < 0) { // (2)
trueMargin = 0;
}
}
QFontMetrics fm(font());
QRect bRect = fm.boundingRect(text());
bRect.setWidth(fm.width(text()));
int indentOffset = effectiveIndent + trueMargin + frameWidth();
int offsetX = 0;
int offsetY = 0;
if(alignment() & Qt::AlignHCenter) {
offsetX = rect().width() / 2 - bRect.width() / 2;
} else if(alignment() & Qt::AlignRight) {
offsetX = rect().width() - bRect.width() - indentOffset;
} else if(alignment() & Qt::AlignJustify) {
offsetX = trueMargin + frameWidth();
} else if(alignment() & Qt::AlignLeft) {
offsetX = indentOffset;
}
if(alignment() & Qt::AlignVCenter) {
offsetY = rect().height() / 2 - bRect.height() / 2;
} else if(alignment() & Qt::AlignBottom) {
offsetY = rect().height() - bRect.height() - indentOffset;
} else if(alignment() & Qt::AlignTop) {
offsetY = indentOffset;
}
bRect.moveTopLeft(rect().topLeft());
bRect.setX(bRect.x() + offsetX);
bRect.setWidth(bRect.width() + offsetX);
bRect.setY(bRect.y() + offsetY);
bRect.setHeight(bRect.height() + offsetY);
return bRect;
}
Unexpected cases:
(1) For indent < 0 and margin > 0 effective indent is 0, not width('x')/2 as it is intended to be for negative indent.
(2) For indent < 0 and margin < 0 true margin is 0 and isn't summed to make offset.
Upvotes: 0
Reputation: 1536
The most flexible solution would be to create your own widget which inherits from QLabel. This way, you could override the enterEvent and leaveEvent @Jeremy and @Moe are writing about which are protected. As a part of these methods implementation you could change the text or decoration accordingly. For example:
class CustomLabel : public QLabel
{
Q_OBJECT
public:
CustomLabel(QWidget* parent = nullptr) : QLabel(parent){ }
protected:
void enterEvent(QEvent *ev) override
{
setStyleSheet("QLabel { background-color : blue; }");
}
void leaveEvent(QEvent *ev) override
{
setStyleSheet("QLabel { background-color : green; }");
}
};
Another approach, but a lot less flexible would be to set the href attribute for the link tag you have specified in label text. This way text would be treated as actual link and you could use the linkHovered signal to connect to. For example:
ui->label->setText("<a href='www.google.com'>link</a>");
connect(ui->label, &QLabel::linkHovered, this, [this](const QString&)
{
// do smth with the widget/text
});
However, please denote that this way you could only make a modification on the hover event. So if you need to bring the label back to its original state, the first option is the way to go.
Upvotes: 5
Reputation: 6110
Make use of enterEvent
and leaveEvent
of QLabel
.
Create a subclass of QLabel
like this for example:
class MyLabel : public QLabel
{
public:
MyLabel();
MyLabel(char* text, MainWindow* w) : QLabel(text, w) { }
void enterEvent(QEvent *event);
void leaveEvent(QEvent *event);
};
and override enterEvent
and leaveEvent
like this:
void MyLabel::enterEvent(QEvent *event) {
qDebug() << "Entered!";
// Change your text here
}
void MyLabel::leaveEvent(QEvent *event) {
qDebug() << "Left!";
}
You can create instances of this class now like this:
MainWindow w;
MyLabel myLabel("A Test Label", &w);
Upvotes: 0