python - 如何让 Kivy 应用程序在线程内运行?
问题描述
我有一个非常简单的 Kivy 应用程序,它可以像这样完美地运行:
def run_form():
rules_form().run()
if __name__ == '__main__':
run_form()
但我希望程序在 rules_form 窗口打开时继续运行。我尝试了以下方法:
def run_form():
rules_form().run()
if __name__ == '__main__':
t = Thread(target=run_form)
t.start()
print("Hi")
当我这样做时,程序会打印“hi”,但打开的 Kivy 窗口是白色的并且没有响应。
我怎样才能让它工作?
解决方案
我最近一直在用 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()
调用。这会更新 的articles
属性,而SearchBar
后者又会更新Recommendations
(BoxLayout)的子项。这些孩子本质上只是Buttons
在用户被按下时将用户引导到推荐页面。
推荐阅读
- c# - 按钮数组 用于井字游戏分配
- regex - 文本比较的正则表达式与超越比较语法
- android - MpAndroidChat BarChart X_Axis 标签未与条对齐
- javascript - 缺少 src 的图像
- vue.js - 如何在服务端渲染页面中使用一些 Vue 组件
- mysql - 需要将 SQL Query 转换为 Gorm 查询
- android-studio - 如何更改 Android Studio 中 logcat 中显示的模拟器
- reactjs - 当我在子组件中提交表单时,如何更新我定义了 contexAPI 的父类的状态?
- oracle - 插入oracle表时Rowid不按顺序
- javascript - 将具有一些新属性的对象数组添加到另一个具有相同名称的对象数组中