交互式启动器

在 1.3.0 版本加入.

自 1.10.0 版本弃用: 交互式启动器已被弃用。

:类 InteractiveLauncher 为用户提供了一个友好的 Python 命令行界面,用于与 App 交互,以便能够交互式地进行原型设计和调试。

备注

Kivy API 设计上,某些函数仅应运行一次或在主事件循环启动前调用。在应用程序运行过程中通常可调用的方法会按预期工作,但动态地覆盖诸如 on_touch() 这类方法则会导致问题。

创建交互式启动器

将你的现有 App 子类(可以是生产代码)实例传递给 InteractiveLauncher 构造函数。:

from kivy.interactive import InteractiveLauncher
from kivy.app import App
from kivy.uix.button import Button

class MyApp(App):
    def build(self):
        return Button(text='Hello Shell')

launcher = InteractiveLauncher(MyApp())
launcher.run()

按下*回车*后,脚本将返回。这允许解释器继续运行。通过InteractiveLauncher实例或提供的:class:SafeMembrane`类实例,可以安全地检查或修改:class:`App

备注

如果你想测试这个示例,请先启动Python(不带任何文件),这样会得到一个解释器,然后复制粘贴所有行。最后你仍会拥有解释器,同时Kivy应用程序也在运行。

交互式开发

IPython 提供了一种快速学习 Kivy API 的方法。通过使用 '.' 运算符并按下 'tab' 键,可以快速列出 App 实例及其所有属性,包括方法和整个控件树。请在 Ipython shell 中尝试以下代码。:

from kivy.interactive import InteractiveLauncher
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.graphics import Color, Ellipse

class MyPaintWidget(Widget):
    def on_touch_down(self, touch):
        with self.canvas:
            Color(1, 1, 0)
            d = 30.
            Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))


class TestApp(App):
    def build(self):
        return Widget()


i = InteractiveLauncher(TestApp())
i.run()
i.       # press 'tab' to list attributes of the app
i.root.  # press 'tab' to list attributes of the root widget

# App is boring. Attach a new widget!
i.root.add_widget(MyPaintWidget())

i.safeIn()
# The application is now blocked.
# Click on the screen several times.
i.safeOut()
# The clicks will show up now

# Erase artwork and start over
i.root.canvas.clear()

备注

模块中使用的所有代理都将它们的引用对象存储在 _ref 属性中,如有需要(例如获取文档字符串),可以直接访问该属性。help()type() 会访问代理本身,而非其引用对象。

直接暂停应用程序

: InteractiveLauncherSafeMembrane 都持有对 EventLoop 的 'safe' 和 'confirmed' threading.Event 对象的内部引用。您可以使用它们的 safing 方法来手动控制应用程序。

SafeMembrane.safeIn() 将导致应用程序暂停,而 SafeMembrane.safeOut() 将允许暂停的应用程序继续运行。这对于将需要屏幕更新等操作的脚本动作嵌入函数中可能非常有用。

备注

暂停功能是通过 Clocks'schedule_once() 方法实现的,并且在每一帧开始之前发生。

动态添加属性

备注

该模块使用线程和对象代理来封装正在运行的 App。如果在线程内部直接引用而未通过提供的代理(proxy)进行访问,可能会导致死锁和内存损坏。

: InteractiveLauncher 可以像普通对象一样向其添加属性,但如果这些属性是在膜外部创建的,它们将不具备线程安全性,因为 Python 解释器中对它们的外部引用不会经过 InteractiveLauncher 从 SafeMembrane 继承的膜行为。

为了使这些外部引用线程安全,只需将它们自身赋值给 SafeMembrane 实例,如下所示:

from kivy.interactive import SafeMembrane

interactiveLauncher.attribute = myNewObject
# myNewObject is unsafe
myNewObject = SafeMembrane(myNewObject)
# myNewObject is now safe. Call at will.
myNewObject.method()

待办事项

单元测试、示例,以及更清晰地说明在运行中的应用程序中哪些方法是安全的,这些都会很有帮助。三者兼备则更佳。

可以用上下文管理器风格重写,即:

with safe:
    foo()

除了压缩代码之外,还有其他用例吗?

class kivy.interactive.InteractiveLauncher(app=None, *args, **kwargs)[源代码]

基类:SafeMembrane

代理到一个应用程序实例,该实例在线程中启动它,然后返回并作为该线程中应用程序的代理。

class kivy.interactive.SafeMembrane(ob, *args, **kwargs)[源代码]

基类:object

此帮助信息是针对代理对象的。您是否想查看代理所引用对象的帮助?请尝试使用 help(<instance>._ref)。

SafeMembrane 是一个线程安全的代理,它不仅将属性作为新的线程安全对象返回,还确保方法调用是线程安全的,从而防止线程不安全的对象泄露到用户环境中。

safeIn()[源代码]

为交互式启动提供线程安全的入口点。

safeOut()[源代码]

为交互式启动提供线程安全的退出点。