简体   繁体   English

Kivy生产者/消费者队列更新

[英]Kivy Producer/Consumer Queue Updates

Looking to understand why this code is not updating. 希望了解为什么此代码未更新。 Any help is much appreciated. 任何帮助深表感谢。 TJ TJ

Here is my Main.py. 这是我的Main.py。 Here, I'm attempting to link up a queue that stores the state of a number producer process. 在这里,我试图链接一个存储数字生成器进程状态的队列。 This is to simulate some background process that will update the user interface over time. 这是为了模拟一些后台进程,该进程将随着时间的推移更新用户界面。

import Consumer
import Producer
import multiprocessing

if __name__ == '__main__':
   shared_queue = multiprocessing.Queue()

  producer = Producer.NumberGenerator(shared_queue)
   multiprocessing.Process(target=producer.generate_numbers).start()

  app = Consumer.TimerApp()
   app.set_queue(shared_queue)

  app.run()

Producer.py runs as a separate process that generates a new number once a second. Producer.py作为一个独立的进程运行,每秒生成一个新的数字。 It's just there to show that a background task is able to continually update the user interface. 它只是表明后台任务能够不断更新用户界面。

import time


class NumberGenerator(object):

   def __init__(self, q):
        self.q = q
        self.counter = 0

   def generate_numbers(self):
        while True:
            time.sleep(1)
            self.counter += 1
            # print self.counter
            self.q.put(self.counter)

Consumer.py is our Kivy app. Consumer.py是我们的Kivy应用程序。 It is meant to listen to the queue by popping items from it. 它旨在通过从队列中弹出项目来监听队列。 Then, update the UI to demonstrate things are working. 然后,更新UI以演示一切正常。

from kivy.app import App
from kivy.uix.label import Label
from kivy.properties import StringProperty
import multiprocessing


class YourWidget(Label):
   temp = StringProperty()

  def update_text(self, txt):
      self.temp = txt


class TimerApp(App):

  def build(self):
      self.widget = YourWidget()
      self.widget.update_text("Initial Text!")

     # Build registry here
      # Start queue reader here
      # How do I pass in a reference? Setter function??
      return self.widget

  def set_queue(self, q):
      self.q = q

  def consumer_process_queue(self):
      while True:
         value = str(self.q.get())
         print "Consumer: {}".format(value)
         self.widget.update_text(value)

  def on_start(self):
      # self.widget.update_text("Hello World!")
      multiprocessing.Process(target=self.consumer_process_queue).start()

timer.kv: timer.kv:

<YourWidget>:
    text: root.temp

When things are processing, I can see the numbers updating to STDOUT. 处理过程中,我可以看到数字更新为STDOUT。 This indicates that "self.widget.update_text(value)" is not doing what I want it to. 这表明“ self.widget.update_text(value)”没有按照我想要的去做。 Any ideas? 有任何想法吗?

Also, if I use the commented "self.widget.update_text("Hello World!")" code and comment out the "multiprocessing.Process(target=self.consumer_process_queue).start()", the widget updates the text. 另外,如果我使用注释的“ self.widget.update_text(“ Hello World!”)“代码并注释掉“ multiprocessing.Process(target = self.consumer_process_queue).start()”,则小部件将更新文本。

Problem 问题

def consumer_process_queue(self):
    while True:
        value = str(self.q.get())
        print("Consumer: {}".format(value))
        self.widget.update_text(value)

When you run this, the program will never exit your loop, preventing Kivy from doing all of the other things that need doing. 当您运行此命令时,该程序将永远不会退出循环,从而阻止Kivy执行所有其他需要做的事情。 As a result, all you'll see is a black window with "Initial Text!", which you won't be able to interact with. 结果,您将看到的是带有“初始文本!”的黑色窗口,您将无法与之交互。

Solution

Instead, you need to “schedule” your consumer_process_queue() function to be called repeatedly. 相反,您需要“计划” consumer_process_queue()函数,以使其反复调用。 Please refer to the example for details. 有关详细信息,请参阅示例。 No changes to Producer.py and main.py. 无需更改Producer.py和main.py。

Example

Consumer.py 消费者

from kivy.app import App
from kivy.uix.label import Label
from kivy.clock import Clock
import multiprocessing


class YourWidget(Label):

    def update_text(self, txt):
        self.text = txt


class TimerApp(App):

    def build(self):
        self.widget = YourWidget()
        self.widget.update_text("Initial Text!")
        Clock.schedule_interval(self.consumer_process_queue, 1)

        # Build registry here
        # Start queue reader here
        # How do I pass in a reference? Setter function??
        return self.widget

    def set_queue(self, q):
        self.q = q

    def consumer_process_queue(self, dt=0):
        value = str(self.q.get())
        print("Consumer: {}".format(value))
        self.widget.update_text(value)

    def on_start(self):
        # self.update_text("Hello World!")
        multiprocessing.Process(target=self.consumer_process_queue).start()

timer.kv 计时器

#:kivy 1.10.0

<YourWidget>:
    text: ""

Output 输出量

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM