首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将动态小部件对象传递给QVariantAnimation valueChanged信号处理程序

将动态小部件对象传递给QVariantAnimation valueChanged信号处理程序
EN

Stack Overflow用户
提问于 2021-10-05 03:40:32
回答 1查看 140关注 0票数 1

我在试着制作一个无效的动画工具。我有一个按钮,当按下,动画一个字段的背景颜色从红色到“正常”字段的颜色。这很好,但是现在我想传递任何任意 PyQt小部件对象(可以是QLineEditQComboBox等等)。下面是我的动画处理程序的样子:

代码语言:javascript
复制
@QtCore.pyqtSlot(QtGui.QColor)
def invalid_animation_handler(color: QtGui.QColor) -> None:
    field.setStyleSheet(f"background-color: {QtGui.QColor(color).name()}")

目前,它要求在调用函数以更改背景之前已经命名了field对象。我希望能够动态传递一个widget,并通过传入一个参数来动态地设置样式表,如下所示:

代码语言:javascript
复制
@QtCore.pyqtSlot(QtGui.QColor)
def invalid_animation_handler(widget, color: QtGui.QColor) -> None:
    widget.setStyleSheet(f"background-color: {QtGui.QColor(color).name()}")

当我尝试这样做时,小部件就可以被传递了,但是不变的颜色从WARNING_COLOR变为NORMAL_COLOR已经不能工作了。我也不想把它放到类中,因为它必须是动态的。我的目标是能够调用一个函数从任何地方启动动画,而不必按下按钮。所期望的目标如下:

代码语言:javascript
复制
class VariantAnimation(QtCore.QVariantAnimation):
    """VariantAnimation: Implement method for QVariantAnimation to fix pure virtual method in PyQt5 -> PyQt4"""
    def updateCurrentValue(self, value):
        pass

@QtCore.pyqtSlot(QtGui.QColor)
def invalid_animation_handler(widget, color: QtGui.QColor) -> None:
    widget.setStyleSheet(f"background-color: {QtGui.QColor(color).name()}")

def invalid_animation(widget):
    return VariantAnimation(startValue=ERROR_COLOR, endValue=NORMAL_COLOR, duration=ANIMATION_DURATION, valueChanged=lambda: invalid_animation_handler(widget))

def start_invalid_animation(animation_handler) -> None:
    if animation_handler.state() == QtCore.QAbstractAnimation.Running:
        animation_handler.stop()
    animation_handler.start()

field = QtGui.QLineEdit()
field_animation_handler = invalid_animation(field)

# Goal is to make a generic handler to start the animation
start_invalid_animation(field_animation_handler)

最小工作实例

代码语言:javascript
复制
import sys
from PyQt4 import QtCore, QtGui

class VariantAnimation(QtCore.QVariantAnimation):
    """VariantAnimation: Implement method for QVariantAnimation to fix pure virtual method in PyQt5 -> PyQt4"""
    def updateCurrentValue(self, value):
        pass

@QtCore.pyqtSlot(QtGui.QColor)
def invalid_animation_handler(color: QtGui.QColor) -> None:
    field.setStyleSheet(f"background-color: {QtGui.QColor(color).name()}")

def start_field_invalid_animation() -> None:
    if field_invalid_animation.state() == QtCore.QAbstractAnimation.Running:
        field_invalid_animation.stop()
    field_invalid_animation.start()
    
NORMAL_COLOR = QtGui.QColor(25,35,45)
SUCCESSFUL_COLOR = QtGui.QColor(95,186,125)
WARNING_COLOR = QtGui.QColor(251,188,5)
ERROR_COLOR = QtGui.QColor(247,131,128)
ANIMATION_DURATION = 1500

if __name__== '__main__':
    app = QtGui.QApplication(sys.argv)
    button = QtGui.QPushButton('Animate field background')
    button.clicked.connect(start_field_invalid_animation)
    field = QtGui.QLineEdit()
    field_invalid_animation = VariantAnimation(startValue=ERROR_COLOR, endValue=NORMAL_COLOR, duration=ANIMATION_DURATION, valueChanged=invalid_animation_handler)

    mw = QtGui.QMainWindow()
    layout = QtGui.QHBoxLayout()
    layout.addWidget(button)
    layout.addWidget(field)
    window = QtGui.QWidget()
    window.setLayout(layout)
    mw.setCentralWidget(window)
    mw.show()
    sys.exit(app.exec_())
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-05 04:24:11

我不明白你为什么不想上课,但海事组织是最合适的解决办法。逻辑是存储允许更改属性并在updateCurrentValue中调用该属性的可调用性。

目前我还没有安装PyQt4,所以我用PyQt5实现了这个逻辑,但我认为更改导入并不困难。

代码语言:javascript
复制
import sys
from dataclasses import dataclass
from functools import partial
from typing import Callable

from PyQt5.QtCore import QAbstractAnimation, QObject, QVariant, QVariantAnimation
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QLineEdit,
    QMainWindow,
    QPushButton,
    QWidget,
)


@dataclass
class VariantAnimation(QVariantAnimation):
    widget: QWidget
    callback: Callable[[QWidget, QVariant], None]
    start_value: QVariant
    end_value: QVariant
    duration: int
    parent: QObject = None

    def __post_init__(self) -> None:
        super().__init__()
        self.setStartValue(self.start_value)
        self.setEndValue(self.end_value)
        self.setDuration(self.duration)
        self.setParent(self.parent)

    def updateCurrentValue(self, value):
        if isinstance(self.widget, QWidget) and callable(self.callback):
            self.callback(self.widget, value)


def invalid_animation_handler(widget: QWidget, color: QColor) -> None:
    widget.setStyleSheet(f"background-color: {QColor(color).name()}")


def start_field_invalid_animation(animation: QAbstractAnimation) -> None:
    if animation.state() == QAbstractAnimation.Running:
        animation.stop()
    animation.start()


NORMAL_COLOR = QColor(25, 35, 45)
SUCCESSFUL_COLOR = QColor(95, 186, 125)
WARNING_COLOR = QColor(251, 188, 5)
ERROR_COLOR = QColor(247, 131, 128)
ANIMATION_DURATION = 1500

if __name__ == "__main__":
    app = QApplication(sys.argv)
    button = QPushButton("Animate field background")

    field = QLineEdit()
    animation = VariantAnimation(
        widget=field,
        callback=invalid_animation_handler,
        start_value=ERROR_COLOR,
        end_value=NORMAL_COLOR,
        duration=ANIMATION_DURATION,
    )

    button.clicked.connect(partial(start_field_invalid_animation, animation))

    mw = QMainWindow()
    layout = QHBoxLayout()
    layout.addWidget(button)
    layout.addWidget(field)
    window = QWidget()
    window.setLayout(layout)
    mw.setCentralWidget(window)
    mw.show()
    sys.exit(app.exec_())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69444655

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档