Kivy - 线程,队列,时钟和Python套接字

时间:2014-05-09 20:45:52

标签: kivy

我是Kivy的新手,也是GUI的新手,但不是编程新手。

我完全错过了使用Kivy的船,独木舟和飞机。

在30年的编程中,从机器代码,汇编,Fortran,C,C ++,Java,Python,我从来没有尝试使用像Kivy这样的语言,这个文档很薄,因为它太新了。我知道它会变得更好,但我现在正试图使用​​它。

在我的代码中,我试图实现队列,以便我可以获得Python套接字数据。在普通的Python编程中,我会通过队列获得IPC - 将数据放入,获取数据。

我从Kivy了解到,主要来自我在各种论坛上阅读的内容,但不能说我已经在kivy.org的文档中找到了它,我无法理解执行以下操作:

  • Kivy需要参与其自己的主题。
  • Kivy什么都不应该睡觉。
  • Kivy中没有任何东西可以阻止IO。

经过大量的Google搜索,我实际上发现方法实用的唯一方法是informative note here on StackOverFlow。然而,虽然它几乎解决了我的问题,但答案假设我比Kivy更了解Kivy;我不知道如何纳入答案。

如果有人可以花时间整理一个使用该示例的COMPLETE简短演示,或者您自己独特的COMPLETE答案之一,我将非常感激!

这是我编写的一些简短代码,但它不起作用,因为它阻止了get()调用。

from Queue import Queue
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.clock import Clock
from threading import Thread

class ClockedQueue(BoxLayout):
    text1 = StringProperty("Start")

    def __init__(self):
        super(ClockedQueue,self).__init__()
        self.q = Queue()
        self.i=0
        Clock.schedule_interval(self.get, 2)

    def get(self,dt):
        print("get entry")

        val = self.q.get()
        print(self.i + val)
        self.i += 1

class ClockedQueueApp(App):

    def build(self):
        return ClockedQueue()

class SourceQueue(Queue):
    def __init__(self):
        q = Queue()
        for word in ['First','Second']:
            q.put(word)
        print("SourceQueue finished.")

def main():

    th = Thread(target=SourceQueue)
    th.start()

    ClockedQueueApp().run()
    return 0

if __name__ == '__main__':


    main()

谢谢!

2 个答案:

答案 0 :(得分:4)

  

这是我放在一起的一些简短代码,但它不起作用,因为它阻止了get()调用。

那么你真正想做的是以非阻塞方式从队列中获取项目?

有多种方法可以做到这一点。最简单的似乎是在获取队列之前检查队列是否有任何项目 - Queue有几种方法可以帮助解决这个问题,包括检查它是否为空或设置是否允许get阻塞(通过将其第一个参数设置为False)。如果你这样做而不是单独调用get,你就不会阻止等待队列有任何项目的东西 - 如果它是空的或你不能立即get任何东西,你只需要什么都不做。

我不知道你想对从队列中获得的项目做什么,但如果它是短时间的操作并不需要很长时间,那么你将不需要更多的东西。例如,您可以Clock.schedule_interval get方法每帧发生一次,如果队列为空则不执行任何操作,或者如果您收到某些内容则对数据进行操作。没有阻塞,也没有搞乱自己的线程。

可以创建自己的线程并在其中运行阻塞代码,这是处理阻塞问题的一般方法,尤其是不能分成短段的任务在帧之间执行。我不知道这个细节,但它应该只涉及正常使用python线程。您可以查看kivy UrlRequest的来源作为示例,这可以在后台线程中下载Web源。

编辑:你的SourceQueue也搞砸了(你重写它的__init__来创建一个你不存储的新队列),你的时钟调度有一个毫无意义的第三个参数false甚至没有定义。我不知道这里发生了什么,它可能影响到你想要做的事情,但对我上面的一般答案无关紧要。

答案 1 :(得分:3)

我终于能够创造出有用的东西了。

感谢大家的建议!

这里是代码(因为我是新的,Stackoverflow不会让我发布它来回答我自己的问题,直到凌晨5点)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#  threads_and_kivy.py
#  
'''threads_and_kivy.py
Trying to build up a foundation that satisfies the following:
    - has a thread that will implement code that:
        - simulates reads data from a Python socket
        - works on the data
        - puts the data onto a Python Queue
    - has a Kivy mainthread that:
        - via class ShowGUI
            - reads data from the Queue
            - updates a class variable of type StringProperty so it will
                update the label_text property.

'''

from threading import Thread
from Queue import Queue, Empty
import time


from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.lang import Builder
from kivy.clock import Clock


kv='''

<ShowGUI>:
    Label:
        text: str(root.label_text)
'''

Builder.load_string(kv)

q = Queue()    


class SimSocket():
    global q

    def __init__(self, queue):
        self.q = queue

    def put_on_queue(self):
        print("<-----..threaded..SimSocket.put_on_queue(): entry")
        for i in range(10):
            print(".....threaded.....SimSocket.put_on_queue(): Loop " + str(i))
            time.sleep(1)#just here to sim occassional data send
            self.some_data = ["SimSocket.put_on_queue(): Data Loop " + str(i)]
            self.q.put(self.some_data)
        print("..threaded..SimSocket.put_on_queue(): thread ends")

class ShowGUI(BoxLayout):
    label_text = StringProperty("Initial - not data")
    global q

    def __init__(self):
        super(ShowGUI, self).__init__()
        print("ShowGUI.__init__() entry")
        Clock.schedule_interval(self.get_from_queue, 1.0)

    def get_from_queue(self, dt):
        print("---------> ShowGUI.get_from_queue() entry")
        try:
            queue_data = q.get(timeout = 5)
            self.label_text = queue_data[0]
            for qd in queue_data:
                print("SimKivy.get_from_queue(): got data from queue: " + qd)
        except Empty:
            print("Error - no data received on queue.")
            print("Unschedule Clock's schedule")
            Clock.unschedule(self.get_from_queue)


class KivyGui(App):
    def build(self):
        return ShowGUI()



def main():

    global q
    ss = SimSocket(q)

    simSocket_thread = Thread(name="simSocket",target=ss.put_on_queue)
    simSocket_thread.start()

    print("Starting KivyGui().run()")

    KivyGui().run()


    return 0

if __name__ == '__main__':

    main()