如何创建QT标签悬停效应



我必须在QT标签上使用Hover事件,但是我找不到有关此的信息。我尝试使用诸如ui->label->setText("<a>ads</a>")onLinkHovered之类的东西,但它不正确。

我必须更改悬停的文本。

最灵活的解决方案是创建自己的窗口小部件,该小部件从qlabel继承。这样,您可以覆盖 enterevent wellevent @jeremy和@moe正在撰写有关受保护的内容。作为实施这些方法的一部分,您可以相应地更改文本或装饰。例如:

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; }");
    }
};

另一种方法,但灵活的方法是设置您在标签文本中指定的链接标签的HREF属性。这样,文本将被视为实际链接,您可以使用链接的信号连接到。例如:

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
});

但是,请表示这样一来,您只能对悬停事件进行修改。因此,如果您需要将标签重新带回原始状态,第一个选择是要走的路。

使用QLabelenterEventleaveEvent

例如,创建一个QLabel的子类,例如:

class MyLabel : public QLabel
{
public:
    MyLabel();
    MyLabel(char* text, MainWindow* w) : QLabel(text, w) { }
    void enterEvent(QEvent *event);
    void leaveEvent(QEvent *event);
};

和覆盖enterEventleaveEvent类似:

void MyLabel::enterEvent(QEvent *event) {
    qDebug() << "Entered!";
    // Change your text here
}
void MyLabel::leaveEvent(QEvent *event) {
    qDebug() << "Left!";
}

您现在可以创建此类的实例:

MainWindow w;
MyLabel myLabel("A Test Label", &w);

如果要确定鼠标是否悬停在Qlabel内部的文本上,则可以使用

void mouseMoveEvent(QMouseEvent* event);

并检查鼠标光标是否在文本的矩形中。

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);
}

打开鼠标跟踪,以使您的小部件在不按按下鼠标按钮时也会发生mouseMoveEvent

setMouseTracking(true);

,最后是完成文本边界矩形的函数。下面的代码也考虑到一些意外情况。我尝试了QT 5.9.1

为计算否定案例中有效缩进,请参阅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;
}

意外情况:

(1)缩进&lt;0和边距> 0有效缩进为0,而不是宽度('x')/2,因为它旨在用于负凹痕。

(2)缩进&lt;0和Margin&LT;0真正的边距为0,而不是总结以偏移。

我发现您也可以通过样式表实现此目标。

self.label = QtWidgets.QLabel("Toast")
self.label.setStyleSheet("QLabel{color: white;} QLabel:hover {color: blue;}")

最新更新