Сколько раз больше всего я могу изменить фон кнопки? - PullRequest
1 голос
/ 26 июня 2019

Итак, я пытаюсь моргнуть кнопкой с цветом, который я передаю, и между белым.И только кажется, что он мигает так много раз после того, как этот код потерпит крах.Я попытался реализовать мигание с разной частотой мигания, и оно все равно прервалось бы через некоторое время.

  • в 'a' У меня есть строка типа "Background-color: rgb (255,0, 0)».
  • в «таймингах» у меня есть список, подобный [208, 280], или это может быть [48,32,48,32,100,280], это представляет время включения и выключения, «нулевой индекс» представляет «включен» и «индекс»1 'представляет время выключения и следует шаблону и т. Д.
while True:
    i = 0
    while i < len(timings):
        if self.p[2] == 1:
            self.b.setStyleSheet("{}".format(a))
            self.b.update()
            time.sleep(timings[i]/1000)
            self.b.setStyleSheet("Background-color: rgb(255,255,255)")
            self.b.update()
            time.sleep(timings[i+1]/1000)
            i = i + 2

self.head1, self.head2, self.head3 все имеют список с чем-то вроде этого ["Background-color: rgb(255,0,0) ", список шаблонов включения и выключения, номер головы #]

, сейчас я работаю с тремя головами.

def flash(self):
    obj1 = threads(self.head1, self.head1_pb)
    obj2 = threads(self.head2, self.head2_pb)
    obj3 = threads(self.head3, self.head3_pb)
    obj1.start()
    time.sleep(.02)
    obj2.start()
    time.sleep(.02)
    obj3.start()

class threads(Thread):

    def __init__(self, a, pb):
         Thread.__init__(self)
         self.p = a
         self.b = pb

    def run(self):

       a = self.p[0]
       timings = self.p[1]
       print(timings[0])
       while True:
           i = 0
           while i < len(timings):
                if self.p[2] == 1:
                   self.b.setStyleSheet("{}".format(a))
                   self.b.update()
                   time.sleep(timings[i]/1000)
                   self.b.setStyleSheet("Background-color: rgb(255,255,255)")
                   self.b.update()
                   time.sleep(timings[i+1]/1000)
                   i = i + 2
               elif self.p[2] == 2:
                   self.b.setStyleSheet("{}".format(a))
                   self.b.update()
                   time.sleep(timings[i]/1000)
                   self.b.setStyleSheet("Background-color: rgb(255,255,255)")
                   self.b.update()
                   time.sleep(timings[i+1]/1000)
                   i = i + 2
              else:
                   self.b.setStyleSheet("{}".format(a))
                   self.b.update()
                   time.sleep(timings[i]/1000)
                   self.b.setStyleSheet("Background-color: rgb(255,255,255)")
                   self.b.update()
                   time.sleep(timings[i+1]/1000)
                   i = i + 2

1 Ответ

0 голосов
/ 26 июня 2019

Вы можете менять цвет столько раз, сколько хотите, проблема в том, что вам не следует использовать цикл, занимающий много времени, или использовать time.sleep (), потому что они блокируют цикл события, генерирующий графический интерфейс для остановки. Вместо этого используйте QTimer для вызова задачи, которая часто меняет цвет.

В следующем примере создайте пользовательскую кнопку, которая реализует то, что вы хотите:

from PySide2 import QtCore, QtGui, QtWidgets


class PushButton(QtWidgets.QPushButton):
    def __init__(self, *args, **kwargs):
        super(PushButton, self).__init__(*args, **kwargs)
        self._color = QtGui.QColor("white")
        timer_on = QtCore.QTimer(singleShot=True, timeout=self.on_timeout)
        timer_off = QtCore.QTimer(singleShot=True, timeout=self.on_timeout)
        self._timers = (timer_on, timer_off)
        for timer, function in zip(self._timers, (self.on, self.off)):
            timer.timeout.connect(function)

    def setTime(self, on_time, off_time):
        for t, timer in zip((on_time, off_time), self._timers):
            timer.setInterval(t)

    @QtCore.Slot()
    def on_timeout(self):
        timer = self.sender()
        if timer not in self._timers:
            return
        timer_on, timer_off = self._timers
        another_timer = timer_off if timer is timer_on else timer_on
        another_timer.start()

    def start(self):
        timer_on, _ = self._timers
        timer_on.start()

    def stop(self):
        for timer in self._timers:
            timer.stop()
        self.off()

    def color(self):
        return self._color

    def setColor(self, color):
        if self.color() == color:
            return
        self._color = color

    def on(self):
        self.setStyleSheet(
            """PushButton{ background-color: %s}""" % (self.color().name(),)
        )

    def off(self):
        self.setStyleSheet(
            """PushButton{ background-color: rgb(255,255,255)}"""
        )


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        button = PushButton()
        button.setColor(QtGui.QColor("salmon"))
        button.setTime(208, 280)
        button.start()

        # stop blink in 30 seconds
        # QtCore.QTimer.singleShot(30 * 1000, button.stop)

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(button)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("fusion")
    w = Widget()
    w.show()
    sys.exit(app.exec_())

Plus:

Поскольку вы заметили, что у вас много данных, лучше всего создать итератор для экономии памяти. Учитывая вышеизложенное, я создал QPushButton, который получает данные от итератора.

import random
from functools import partial
from PySide2 import QtCore, QtGui, QtWidgets


def generate_data():
    i = 0
    while i < 1000000:
        color_on = random.randint(10, 500)
        color_off = random.randint(10, 500)
        color = QtGui.QColor(*random.sample(range(255), 3))
        yield color_on, color_off, color
        i += 1


class PushButton(QtWidgets.QPushButton):
    def __init__(self, *args, **kwargs):
        super(PushButton, self).__init__(*args, **kwargs)
        self._color = QtGui.QColor("white")
        self._generator = None

        self.m_timer = QtCore.QTimer(
            self, timeout=self.on_timeout, singleShot=True
        )

    def setGenerator(self, generator):
        self._generator = generator

    def start(self):
        self.on_timeout()

    @QtCore.Slot()
    def on_timeout(self):
        try:
            time_on, time_off, color = next(self._generator)
            self.setColor(color)
            self.m_timer.start(time_on + time_off)
            QtCore.QTimer.singleShot(
                time_on, partial(self.setColor, QtGui.QColor("white"))
            )
        except StopIteration:
            self.m_timer.stop()

    def setColor(self, color):
        self.setStyleSheet(
            """PushButton{ background-color: %s}""" % (color.name(),)
        )


class Widget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

        lay = QtWidgets.QVBoxLayout(self)
        for _ in range(6):
            button = PushButton()
            button.setGenerator(generate_data())
            button.start()
            lay.addWidget(button)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    app.setStyle("fusion")
    w = Widget()
    w.resize(320, 240)
    w.show()
    sys.exit(app.exec_())
...