临时更改标签样式(模仿按钮)

change label style temporary (imitate button)

我 运行 没有想法,所以我需要向你们寻求建议。我正在处理可点击的标签。我已经完成了一些 "clickable label" class 并处理了鼠标悬停事件 - 当鼠标离开时,它会将标签边框和 returns 更改为正常状态。

现在我希望它在标签上具有自定义发光效果,但我希望它在点击后 return 恢复到正常状态,比如说 0.5 秒后。

我想要我的带有图像的标签来模仿按钮。 time.sleep 效果不佳,尤其是垃圾点击会冻结应用程序主线程。

希望我不是在重新发明轮子,但据我所知这是可行的方法。

这里是示例代码,欢迎回答。

from PySide2.QtWidgets import QLabel, QSizePolicy, QGraphicsDropShadowEffect
from PySide2.QtGui import QPixmap
from PySide2.QtCore import (Signal, QEvent, QObject, QRect)


class ClickableLabel(QLabel):
    def __init__(self, pic_path, width, height, border_color, click_function):
        super(ClickableLabel, self).__init__()

        # Setting the picture path and setting pixmap to label
        self.pic_path = pic_path
        self.pixmap = QPixmap(self.pic_path)
        self.setPixmap(self.pixmap)

        # Set the size
        self.setFixedSize(width, height)

        # Enable tracking and assign function
        self.setMouseTracking(True)
        self.click_function = click_function

        # Set default 
        if border_color is None:
            self.border_color = 'lightblue'
        else:
            self.border_color = border_color

    def mouseMoveEvent(self, event):
        # event.pos().x(), event.pos().y()
        self.setStyleSheet("border: 1px solid " + str(self.border_color) + ";")

    def leaveEvent(self, event):
        # event.pos().x(), event.pos().y()
        self.setStyleSheet("border: None")

    def mousePressEvent(self, event):
        self.click_function()

        effect = QGraphicsDropShadowEffect(self)
        effect.setOffset(0, 0)
        effect.setBlurRadius(20)
        effect.setColor(self.border_color)
        self.setGraphicsEffect(effect)

如果你想 运行 一段时间后的任务,你不应该使用 time.sleep() 因为它会阻止 GUI 导致它无法正常运行,最好的选择是使用 QTimer::singleShot().

另一方面,我看到您正在传递一个函数,以便它在单击时执行一个任务,这是不可扩展的,在 Qt 中正确的做法是创建一个信号,优点是您可以将同一个信号不耦合地连接到几个函数,即发出信号的那个必须事先不知道谁会收到信号。

我建议为参数的缺陷取值,我已经花时间改进你的代码:

from PySide2 import QtCore, QtGui, QtWidgets


class ClickableLabel(QtWidgets.QLabel):
    clicked = QtCore.Signal()

    def __init__(self, pic_path="", width=80, height=30, border_color=QtGui.QColor("lightblue"), parent=None):
        super(ClickableLabel, self).__init__(parent)
        self.setPixmap(QtGui.QPixmap(pic_path))
        self.setFixedSize(width, height)
        self.setMouseTracking(True)
        self.border_color = QtGui.QColor(border_color)
        self.effect = QtWidgets.QGraphicsDropShadowEffect(self,
            offset=QtCore.QPointF(0, 0),
            blurRadius=20,
            color=self.border_color)
        self.setGraphicsEffect(self.effect)
        self.disable_effect()

    def mouseMoveEvent(self, event):
        self.setStyleSheet("border: 1px solid {};".format(self.border_color.name()))
        super(ClickableLabel, self).mouseMoveEvent(event)

    def leaveEvent(self, event):
        self.setStyleSheet("border: None")
        super(ClickableLabel, self).leaveEvent(event)

    def mousePressEvent(self, event):
        self.clicked.emit()
        self.effect.setEnabled(True)
        QtCore.QTimer.singleShot(500, self.disable_effect)
        super(ClickableLabel, self).mousePressEvent(event)

    @QtCore.Slot()
    def disable_effect(self):
        self.effect.setEnabled(False)


if __name__ == '__main__':
    import sys

    app = QtWidgets.QApplication(sys.argv)

    def on_click():
        print("click")

    w = ClickableLabel(pic_path="heart.png")
    w.clicked.connect(on_click)
    w.show()
    sys.exit(app.exec_())