在教程 1中,我们生成了一个能够运行的存根项目,但我们自己没有编写任何代码。让我们看看为我们生成了什么。
产生了什么
在src/helloworld目录中,您应该看到 3 个文件__init__.py: __main__.py和app.py.
__init__.py将目录标记helloworld为可导入的 Python 模块。它是一个空文件;它存在的事实告诉 Python 解释器该helloworld目录定义了一个模块。
__main__.py将模块标记helloworld为一种特殊的模块 - 可执行模块。如果您尝试使用 运行helloworld模块 ,则该文件是 Python 将开始执行的位置。的内容比较简单:python -m helloworld__main__.py__main__.py
from helloworld.app import main
if __name__ == '__main__':
main().main_loop()
也就是说 - 它main从 helloworld 应用程序中导入方法;如果它作为入口点执行,则调用 main() 方法,并启动应用程序的主循环。主循环是 GUI 应用程序监听用户输入(如鼠标点击和键盘按下)的方式。
更有趣的文件是app.py- 它包含创建我们的应用程序窗口的逻辑:
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
class HelloWorld(toga.App):
def startup(self):
main_box = toga.Box()
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
def main():
return HelloWorld()
让我们逐行浏览:
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
首先,我们导入toga小部件工具包,以及一些与样式相关的实用程序类和常量。我们的代码还没有使用这些——但我们很快就会使用它们。
然后,我们定义一个类:
class HelloWorld(toga.App):
每个 Toga 应用程序都有一个toga.App实例,代表应用程序的运行实体。该应用程序最终可能会管理多个窗口;但对于简单的应用程序,将只有一个主窗口。
接下来,我们定义一个startup()方法:
def startup(self):
main_box = toga.Box()
启动方法做的第一件事是定义一个主框。Toga 的布局方案的行为类似于 HTML。您可以通过构建一组盒子来构建应用程序,每个盒子都包含其他盒子或实际的小部件。然后将样式应用于这些框以定义它们将如何使用可用窗口空间。
在这个应用程序中,我们定义了一个盒子,但我们没有往里面放任何东西。
接下来,我们定义一个窗口,我们可以将这个空框放入其中:
self.main_window = toga.MainWindow(title=self.formal_name)
这将创建一个 a 的实例,该实例toga.MainWindow将具有与应用程序名称匹配的标题。主窗口是 Toga 中一种特殊的窗口——它是一个与应用程序的生命周期密切相关的窗口。当主窗口关闭时,应用程序退出。主窗口也是具有应用程序菜单的窗口(如果您在像 Windows 这样的平台上,其中菜单栏是窗口的一部分)
然后我们添加我们的空框作为主窗口的内容,并指示应用程序显示我们的窗口:
self.main_window.content = main_box
self.main_window.show()
最后,我们定义了一个main()方法。这就是创建我们应用程序实例的原因:
def main():
return HelloWorld()
此main()方法是由 导入和调用的方法 __main__.py。HelloWorld 它创建并返回我们应用程序的一个实例。
这是最简单的 Toga 应用程序。让我们把我们自己的一些内容放到应用程序中,让应用程序做一些有趣的事情。
添加一些我们自己的内容
在里面修改你的HelloWorld类src/helloworld/app.py,使它看起来像这样:
class HelloWorld(toga.App):
def startup(self):
main_box = toga.Box(style=Pack(direction=COLUMN))
name_label = toga.Label(
'Your name: ',
style=Pack(padding=(0, 5))
)
self.name_input = toga.TextInput(style=Pack(flex=1))
name_box = toga.Box(style=Pack(direction=ROW, padding=5))
name_box.add(name_label)
name_box.add(self.name_input)
button = toga.Button(
'Say Hello!',
on_press=self.say_hello,
style=Pack(padding=5)
)
main_box.add(name_box)
main_box.add(button)
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
def say_hello(self, widget):
print("Hello", self.name_input.value)
笔记
不要删除文件顶部或main()底部的导入。您只需要更新HelloWorld类。
让我们详细看看发生了什么变化。
我们仍在创建一个主盒子;但是,我们现在正在应用一种样式:
main_box = toga.Box(style=Pack(direction=COLUMN))
Toga 的内置布局系统称为“Pack”。它的行为很像 CSS。您在层次结构中定义对象 - 在 HTML 中,对象是<div>、<span>和其他 DOM 元素;在 Toga 中,它们是小部件和盒子。然后,您可以将样式分配给各个元素。在这种情况下,我们表示这是一个COLUMN盒子——也就是说,它是一个会消耗所有可用宽度的盒子,并且会随着内容的添加而扩大其高度,但它会尽量短。
接下来,我们定义几个小部件:
name_label = toga.Label(
'Your name: ',
style=Pack(padding=(0, 5))
)
self.name_input = toga.TextInput(style=Pack(flex=1))
在这里,我们定义了一个 Label 和一个 TextInput。两个小部件都有与之关联的样式;标签将在其左右两侧有 5px 的填充,并且在顶部和底部没有填充。TextInput 被标记为灵活的——也就是说,它将吸收其布局轴上的所有可用空间。
TextInput 被分配为类的实例变量。这使我们可以轻松访问小部件实例——我们稍后将使用它。
接下来,我们定义一个盒子来容纳这两个小部件:
name_box = toga.Box(style=Pack(direction=ROW, padding=5))
name_box.add(name_label)
name_box.add(self.name_input)
和主name_box盒子一样是一个盒子;然而,这一次,它是一个 ROW盒子。这意味着内容将水平添加,并且会尝试使其宽度尽可能窄。盒子也有一些内边距——四面都是 5px。
现在我们定义一个按钮:
button = toga.Button(
'Say Hello!',
on_press=self.say_hello,
style=Pack(padding=5)
)
该按钮的所有边也有 5px 的填充。我们还定义了一个处理程序- 按下按钮时调用的方法。
然后,我们将名称框和按钮添加到主框:
main_box.add(name_box)
main_box.add(button)
这样就完成了我们的布局;启动方法的其余部分和以前一样 - 定义一个 MainWindow,并将主框指定为窗口的内容:
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
我们需要做的最后一件事是定义按钮的处理程序。处理程序可以是任何方法、生成器或异步协程;它接受生成事件的小部件作为参数,并在按下按钮时调用:
def say_hello(self, widget):
print("Hello, ", self.name_input.value)
该方法的主体是一个简单的打印语句 - 但是,它将询问名称输入的当前值,并将该内容用作打印的文本。
现在我们已经进行了这些更改,我们可以通过再次启动应用程序来查看它们的外观。和以前一样,我们将使用开发者模式:
苹果系统
(beeware-venv) $ briefcase dev
[helloworld] Starting in dev mode...
Linux
(beeware-venv) $ briefcase dev
[helloworld] Starting in dev mode...
视窗
(beeware-venv) C:\...>briefcase dev
[helloworld] Starting in dev mode...
您会注意到这一次,它没有安装依赖项。公文包可以检测到应用程序之前已经运行过,并且为了节省时间,只会运行该应用程序。-d如果您将新的依赖项添加到您的应用程序,您可以通过在运行时传入一个选项 来确保它们已安装。briefcase dev
这应该会打开一个 GUI 窗口:
苹果系统
Linux
视窗
macOS 上的 Hello World 教程 2 窗口
如果您在文本框中输入名称,然后按 GUI 按钮,您应该会在启动应用程序的控制台中看到输出。
下一步
我们现在有一个应用程序可以做一些更有趣的事情。但它只在我们自己的电脑上运行。让我们打包这个应用程序以进行分发。在教程 3中,我们将把我们的应用程序打包成一个独立的安装程序,我们可以将它发送给朋友、客户或上传到 App Store。