我在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编程和事件回调的新手,所以非常感谢任何帮助。
我尝试保持代码简短,如果需要更多代码请告诉我。
答案 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'
请查看以下链接,以便对此进行解释。