2015-08-03 3 views
2

Я просто хочу, чтобы некоторые элементы внутри QDialog мигали (изменяя цвет фона).Мигающий виджет с PyQt

Теперь желательно, чтобы я мог использовать что-то, что уже существует, и инкапсулирует мигающее состояние, то есть мигает с помощью css3, или возможно с QPropertyAnimation?

Поскольку я не нашел хорошую информацию об этой опции я попытался менее оптимальное решение:

отрывок из Диалоги __init__:

self.timer = QTimer() 
self.timer.timeout.connect(self.update_blinking) 
self.timer.start(250) 
self.last_blinked = None 

и

def update_blinking(self): 
    self.frame.setStyleSheet(
     self.STYLE_BLINK_ON if self.blink else self.STYLE_BLINK_OFF) 
    self.blink = not self.blink 

где STYLE_BLINK_ON и STYLE_BLINK_OFF - некоторые css, определяющие цвета фона. Это работает, но

  1. Я считаю, это очень некрасиво, он чувствует, как код из 90-х годов
  2. Это не может использоваться как частый стиль, обновление прерывает кнопку щелчки.

Пояснение к 2: Предположим, что виджет, который должен мигать, является рамкой. Когда кнопка внутри этого кадра нажата, сигнал clicked не выдается, если обновление стиля кадра происходит до отпускания кнопки мыши.

Совершенно другое решение, которое инкапсулирует вещи и не требует, чтобы я вручную запускал таймер, было бы, конечно, предпочтительным. Но я был бы признателен, если бы кто-то хотя бы придумал решение, которое решает точку 2.

ответ

4

Один из способов - использовать QPropertyAnimation. QPropertyAnimation interpolates over Qt properties - этот факт вызывает трудности:

1) Измените внешний вид через таблицу стилей - анимация не может работать со строками, потому что они не являются взаимозаменяемыми.

2) Манипулирование фоном напрямую - цвет фона хранится глубоко внутри QWidget.palette, это не QProperty. Возможное решение преобразовать цвет фона в собственность виджета:

class AnimatedWidget(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 

     color1 = QtGui.QColor(255, 0, 0) 
     color2 = QtGui.QColor(0, 255, 0) 

     self.color_anim = QtCore.QPropertyAnimation(self, 'backColor') 
     self.color_anim.setStartValue(color1) 
     self.color_anim.setKeyValueAt(0.5, color2) 
     self.color_anim.setEndValue(color1) 
     self.color_anim.setDuration(1000) 
     self.color_anim.setLoopCount(-1) 
     self.color_anim.start() 

    def getBackColor(self): 
     return self.palette().color(QtGui.QPalette.Background) 

    def setBackColor(self, color): 
     pal = self.palette() 
     pal.setColor(QtGui.QPalette.Background, color) 
     self.setPalette(pal) 

    backColor = QtCore.pyqtProperty(QtGui.QColor, getBackColor, setBackColor) 

Другой подход имеет дело с QStateMachine с. Они могут манипулировать любыми свойствами, а не только интерполируемыми:

class StateWidget(QtGui.QWidget): 
    def __init__(self): 
     QtGui.QWidget.__init__(self) 

     style1 = "background-color: yellow" 
     style2 = "background-color: black" 

     # animation doesn't work for strings but provides an appropriate delay 
     animation = QtCore.QPropertyAnimation(self, 'styleSheet') 
     animation.setDuration(150) 

     state1 = QtCore.QState() 
     state2 = QtCore.QState() 
     state1.assignProperty(self, 'styleSheet', style1) 
     state2.assignProperty(self, 'styleSheet', style2) 
     #    change a state after an animation has played 
     #        v 
     state1.addTransition(state1.propertiesAssigned, state2) 
     state2.addTransition(state2.propertiesAssigned, state1) 

     self.machine = QtCore.QStateMachine() 
     self.machine.addDefaultAnimation(animation) 
     self.machine.addState(state1) 
     self.machine.addState(state2) 
     self.machine.setInitialState(state1) 
     self.machine.start() 
+0

Эти варианты выглядят намного лучше! Я знаю, что я не был конкретным в своем Вопросе об этом, но мне бы хотелось, если бы ответ также предоставил способ применить анимацию к существующему Виджету, чтобы его можно было включить/выключить – IARI

Смежные вопросы