How many times the most I can change the background of the pushButton?

浪尽此生 提交于 2020-02-16 05:47:10

问题


So , I am trying to blink the push button with the color that I pass and between white. And it only seems to blink it so many times after that code would crash. I have tried it to implement the blinking with different blink rates and it would it still break at some time.

  • in 'a' I have the string like "Background-color: rgb(255,0,0)".
  • in 'timings' i have a list like[208, 280]or it could be [48,32,48,32,100,280], this represents the on and off timings 'zeroth index' represents on and 'index 1' represents off time and follows the pattern so on.
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 all have list with some thing like this ["Background-color:rgb(255,0,0)",list of on and off patterns, head number#]

right now, I am working with three heads.

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:


You can change the color as many times as you want, the problem is that you should not use a time consuming loop or use time.sleep() because they block the eventloop generating the GUI to freeze. Instead, use a QTimer to call the task that changes color every so often.

In the following example, create a custom button that implements what you want:

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:

As you note that you have a lot of data, it is best to create an iterator to save memory. Considering the above I have created a QPushButton that obtains the data from the iterator.

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_())


来源:https://stackoverflow.com/questions/56774100/how-many-times-the-most-i-can-change-the-background-of-the-pushbutton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!