如何在线程中制作 Kivy 应用程序 运行?
How to make Kivy app run inside a thread?
我有一个非常简单的 Kivy 应用程序,可以像这样完美运行:
def run_form():
rules_form().run()
if __name__ == '__main__':
run_form()
但我希望程序在 rules_form window 打开时继续。我尝试了以下方法:
def run_form():
rules_form().run()
if __name__ == '__main__':
t = Thread(target=run_form)
t.start()
print("Hi")
当我这样做时,程序会打印“hi”,但打开的 Kivy window 是白色的,没有响应。
我怎样才能让它发挥作用?
我最近一直在使用 Kivy 处理线程,并且按照 Inclement 的建议完成了。那就是在主线程中有 Kivy 运行,然后将其他任务分派给另一个线程。
这是我创建的使用线程的应用示例:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.label import Label
import webbrowser
from wiki_recommendations import WikiSearcher
class SearchBar(TextInput):
articles = ListProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(text=self.on_text)
self.bind(articles=self.on_articles)
def on_text(self, *args):
WikiSearcher().get_search_results(self.text, self)
def on_articles(self, *args):
self.parent.ids['recommendations'].update_recommendations(self.articles)
class SearchItem(ButtonBehavior, Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.url = ''
def on_release(self):
webbrowser.open(self.url)
class Recommendations(BoxLayout):
def update_recommendations(self, recommendations: list):
for (search_item, recommendation) in zip(self.children, recommendations):
search_item.text = recommendation
search_item.url = 'https://en.wikipedia.org/wiki/' + recommendation
kv = """
<SearchItem>:
canvas.before:
Color:
rgba: [0.8, 0.8, 0.8, 1] if self.state == 'normal' else [30/255, 139/255, 195/255, 1]
Rectangle:
size: self.size
pos: self.pos
Color:
rgba: 0, 0, 0, 1
Line:
rectangle: self.x, self.y, self.width, self.height
color: 0, 0, 0, 1
BoxLayout:
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size
pos: self.pos
orientation: 'vertical'
padding: self.width * 0.1
spacing: self.height * 0.1
SearchBar:
size_hint: 1, 0.2
multiline: False
font_size: self.height*0.8
Recommendations:
id: recommendations
orientation: 'vertical'
SearchItem
SearchItem
SearchItem
SearchItem
SearchItem
"""
class SearchApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
SearchApp().run()
此应用让用户在搜索栏中输入内容并自动推荐维基百科页面。屏幕截图如下所示:
这段代码使用线程来获取推荐(以免打断用户的输入)。另一个名为 wiki_recommendataions.py 的文件创建这些线程,然后调度一个 API 调用。
import wikipedia
import threading
def thread(function):
def wrap(*args, **kwargs):
t = threading.Thread(target=function, args=args, kwargs=kwargs, daemon=True)
t.start()
return t
return wrap
class WikiSearcher:
@thread
def get_search_results(self, text: str, root):
"""
Gets the top Wikipedia articles
:param text: The text to be searched.
:param root: The object that calls this function - useful for returning a result.
:return:
"""
root.articles = wikipedia.search(text)
当用户在搜索栏中键入时,WikiSearcher
对象被实例化并调用 get_search_results()
。这会更新 SearchBar
的 articles
属性,后者又会更新 Recommendations
的子级(一个 BoxLayout)。这些子项本质上只是 Buttons
,当用户按下它们时,它们会将用户引导至推荐页面。
我有一个非常简单的 Kivy 应用程序,可以像这样完美运行:
def run_form():
rules_form().run()
if __name__ == '__main__':
run_form()
但我希望程序在 rules_form window 打开时继续。我尝试了以下方法:
def run_form():
rules_form().run()
if __name__ == '__main__':
t = Thread(target=run_form)
t.start()
print("Hi")
当我这样做时,程序会打印“hi”,但打开的 Kivy window 是白色的,没有响应。
我怎样才能让它发挥作用?
我最近一直在使用 Kivy 处理线程,并且按照 Inclement 的建议完成了。那就是在主线程中有 Kivy 运行,然后将其他任务分派给另一个线程。
这是我创建的使用线程的应用示例:
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.label import Label
import webbrowser
from wiki_recommendations import WikiSearcher
class SearchBar(TextInput):
articles = ListProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bind(text=self.on_text)
self.bind(articles=self.on_articles)
def on_text(self, *args):
WikiSearcher().get_search_results(self.text, self)
def on_articles(self, *args):
self.parent.ids['recommendations'].update_recommendations(self.articles)
class SearchItem(ButtonBehavior, Label):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.url = ''
def on_release(self):
webbrowser.open(self.url)
class Recommendations(BoxLayout):
def update_recommendations(self, recommendations: list):
for (search_item, recommendation) in zip(self.children, recommendations):
search_item.text = recommendation
search_item.url = 'https://en.wikipedia.org/wiki/' + recommendation
kv = """
<SearchItem>:
canvas.before:
Color:
rgba: [0.8, 0.8, 0.8, 1] if self.state == 'normal' else [30/255, 139/255, 195/255, 1]
Rectangle:
size: self.size
pos: self.pos
Color:
rgba: 0, 0, 0, 1
Line:
rectangle: self.x, self.y, self.width, self.height
color: 0, 0, 0, 1
BoxLayout:
canvas.before:
Color:
rgba: 1, 1, 1, 1
Rectangle:
size: self.size
pos: self.pos
orientation: 'vertical'
padding: self.width * 0.1
spacing: self.height * 0.1
SearchBar:
size_hint: 1, 0.2
multiline: False
font_size: self.height*0.8
Recommendations:
id: recommendations
orientation: 'vertical'
SearchItem
SearchItem
SearchItem
SearchItem
SearchItem
"""
class SearchApp(App):
def build(self):
return Builder.load_string(kv)
if __name__ == '__main__':
SearchApp().run()
此应用让用户在搜索栏中输入内容并自动推荐维基百科页面。屏幕截图如下所示:
这段代码使用线程来获取推荐(以免打断用户的输入)。另一个名为 wiki_recommendataions.py 的文件创建这些线程,然后调度一个 API 调用。
import wikipedia
import threading
def thread(function):
def wrap(*args, **kwargs):
t = threading.Thread(target=function, args=args, kwargs=kwargs, daemon=True)
t.start()
return t
return wrap
class WikiSearcher:
@thread
def get_search_results(self, text: str, root):
"""
Gets the top Wikipedia articles
:param text: The text to be searched.
:param root: The object that calls this function - useful for returning a result.
:return:
"""
root.articles = wikipedia.search(text)
当用户在搜索栏中键入时,WikiSearcher
对象被实例化并调用 get_search_results()
。这会更新 SearchBar
的 articles
属性,后者又会更新 Recommendations
的子级(一个 BoxLayout)。这些子项本质上只是 Buttons
,当用户按下它们时,它们会将用户引导至推荐页面。