Kivy弹出窗口在单独的线程

时间:2017-07-05 21:55:47

标签: python multithreading kivy

我在Kivy中填充树视图需要一些时间,具体取决于它的大小。

如果树很大并需要一段时间,我想在填充时显示一个弹出窗口,这样用户就知道程序没有冻结,并在填充树的逻辑完成时关闭此弹出窗口。

以下是我通过对该主题的一些研究得出的结论,但是一旦树完成填充,弹出窗口似乎才会出现:

def show(self, *args):
        self.error_popup.open()

def populate_tree(self, model):
        #Clock.schedule_once(self.error_popup.open())
        popup_thread = threading.Thread(target=self.show())
        popup_thread.start()

        # order the dictionary for better user experience 
        ordered_data = collections.OrderedDict(sorted(model.items()))

        # logic to populate tree
        for county, value in ordered_data.items():

            if county != "model_name":
                # set initial county dropdowns in tree
                county_label = self.treeview.add_node(TreeViewButton(text=str(county), on_press=self.edit_node))
                i = 0 # keep count of rules

                # add rules children to county
                for rule_obj, rule_list in value.items():
                    for rule in rule_list:
                        i += 1
                        # set rule number in tree
                        rule_label = self.treeview.add_node(TreeViewButton(text='Rule ' + str(i), on_press=self.edit_node), county_label)
                        # add conditions children to rule
                        for condition in rule:
                           self.treeview.add_node(TreeViewButton(text=condition, on_press=self.edit_node), rule_label)

        #Clock.schedule_once(self.error_popup.dismiss())
        #somehow close popup_thread

我包含了一个kivy Clock尝试,以防更多地在我正在寻找的正确轨道上,但是目前它只是打开弹出窗口并且从不填充树。我是GUI编程和事件回调的新手,所以非常感谢任何帮助。

我尝试保持代码简短,如果需要更多代码请告诉我。

2 个答案:

答案 0 :(得分:0)

我构建了一个应用程序,该应用程序的功能类似于您正在执行的操作(不同的计算,但是正如您所说的,这很耗时,并且您希望通过线程弹出式窗口显示该应用程序没有崩溃-它是只是增加数字)。最终对我有用的是设置一个按钮来执行虚拟功能,该功能可以同时切换弹出窗口和计算。首先运行弹出窗口,然后通过“ from threading import Thread”模块对计算进行线程化,以在单独的线程上执行计算。

这是一个可行的例子。它只是睡眠了5秒钟,但是您可以将计算坚持到该函数中,并且应该可以正常工作。它的作用是在计算之前打开弹出窗口,并在计算完成后关闭弹出窗口。另外,您可以将“ Loading.gif”文件粘贴到该文件夹​​中,如果要使用除kivy以外的其他东西(它实际上是用于加载Loading.gif的加载gif),它将把它作为加载gif导入。正在加载,因为它不存在...哈哈)。如果用户厌倦了等待,还添加了“取消”按钮。

最后,作为一个补充说明,我很难将.kv文件构建到pyinstaller应用程序Bundeler中,因此,请注意,使用builder.load_string(KV)函数是一个很好的选择

from threading import Thread
from sys import exit
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.lang import Builder

KV = '''
<Pop>:
    id:pop
    title: ''
    auto_dismiss: False
    padding: 10
    spacing: 10

    BoxLayout:
        BoxLayout:
            padding: 10
            spacing: 10
            orientation: 'vertical'
            Label:
                font_size: 22
                size_hint_y: None
                text_size: self.width, None
                height: self.texture_size[1]
                text: "Process is currently running."
            Label:
                id: error_msg
                size_hint_x: 0.3
                text: ''

            BoxLayout:
                orientation: 'vertical'
                Button:
                    background_color: (1,0,0,1)
                    text: "ABORT"
                    on_press: root.sysex()

        AsyncImage:
            source: 'Loading.gif'

<MetaLevel>:
    rows: 1
    cols: 1
    Button:
        text: 'RUN'
        on_release: root.dummy()

'''

Builder.load_string(KV)

class MetaLevel(GridLayout):

    def dummy(self, *args):
        App.get_running_app().pop.open()
        Thread(target=self.calculate, args=(args,), daemon=True).start()

    def calculate(self, *args):
        import time
        time.sleep(5)
        App.get_running_app().pop.dismiss()


class Pop(Popup):
    def sysex(self):
        exit()


class Cruncher(App):
    def build(self):
        self.pop = Pop()
        return MetaLevel()


if __name__ == "__main__":
    Cruncher().run()

答案 1 :(得分:-1)

你能够对它进行排序吗?

我认为如果您使用线程填充树而不是使用它来显示弹出窗口,它会起作用。填充树后,在同一个线程中,您可以使用Popup.dismiss()

关闭弹出窗口

main.py文件

from kivy.app import App
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
import time, threading

class popupTestApp(App):
    def waitSec(self):
        time.sleep(5)
        self.p.dismiss()

    def popUpFunc(self):
        self.p = Popup(title='Test Popup', content=Label(text='This is a test'), size_hint=(None,None), size=(400,400))
        self.p.open()
        popUpThread = threading.Thread(target=self.waitSec)
        popUpThread.start()

if __name__ == '__main__':
    popupTestApp().run()

popuptest.kv文件

BoxLayout:
    BoxLayout:
        id:LeftPane
        Button:
            id:MyButton
            text:'Pop it up!'
            on_release:app.popUpFunc()
    BoxLayout:
        id:RightPane
        Label:
            text: 'Another Pane'

请查看以下链接,以便对此进行解释。

Building a simple progress bar or loading animation in Kivy