原力计划

  

💭 写在前面:我们假定读者已经安装好了 3.8 版本后的 Python,并且安装好了依赖项,在 Windows 上构建 BeeWare 应用程序需要 Git,你可以可以从 git-scm.org 网站下载。安装完毕后重新启动 cmd,然后就可以准备建立虚拟环境了。

0x00 建立虚拟环境(基于 Windows)

首先,我们需要创建一个 “沙盒” 用于教程的演示,在虚拟环境中安装软件包,我们电脑上的其他 Python 项目将不会被影响。如此一来,即使玩坏了也不会污染环境,直接把 “沙盒” 丢了就行。

💬 具体操作:在 Windows cmd 下输入

md beeware-tutorial
cd beeware-tutorial
py -m venv beeware-venv
beeware-venv\Scripts\activate.bat

输入完这些后,你的提示符前会出现 (beeware-env) 前缀:

这表示你已经在 BeeWare 的虚拟环境中了,在学习本教程时,请确保你的虚拟环境被激活!

下次运行时,直接运行 activate 指令来重新激活环境即可:

beeware-venv\Scripts\activate.bat   # 环境激活

0x01 安装 BeeWare 工具

” 工欲善其事必先利其器 “

在 BeeWare 之旅开始前,我们需要先安装 “小蜜蜂的公文包” —— Briefcase!

Briefcase 是 BeeWare 的一个工具,可以用来打包你的应用程序,以便分发给最终用户。

当然,它也可以用来启动一个新的项目,就像核武器手提箱一样无所不能!

请确保你已在创建的 beeware-tutorial 目录中,并已激活 (beeware-env) 虚拟环境。

💬 操作:在 beeware-tutorial 目录下输入

python -m pip install briefcase

 稍等片刻…… 

当出现 Successfully installed 字样时,则表示已安装成功!

” 恭喜你,你已经拥有了小蜜蜂的万能手提箱 —— Briefcase 了 “

我们前面说过,Briefcase 可以用来打包你的应用程序,分发给最终用户。

还可以用来引导一个新的项目,下面我们就来教大家如何使用公文包启动一个新的项目!

0x02 利用 Briecase 启动新项目

” 任何伟大,都是从一个小小的 Hello,World 开始的,这里我们也不例外!”

我们使用 Briefcase 的 new 命令来创建一个名为 Hello World 的应用程序!

💬 操作:在 beeware-tutorial 目录下输入

briefcase new

公文包会让我们给新的应用程序添加 “亿点点” 细节 (details) :

第一次你可以按照我们的例子输入,”默认值” 直接输入回车即可。

  • 正式名 – Formal Name:默认值 Hello World

  • 应用程序名 – App Name:默认值 helloworld

  • 捆绑 – Bundle:如果你有自己的域名,请按相反的顺序输入域名。举个例子,如果你拥有 foxny.com 域名,请输入 com.foxny。如果你没有自己的域名,就老老实实用默认捆绑 com.example。

  • 项目名称 – Project Name:默认值 Hello World.

  • 描述 – Description:默认值(或者你也可以写一段比较有意义的描述)

  • 作者 – Author:写下你的名字

  • 作者邮箱 – Author’s email – 输入你自己的电子邮件地址,这将用于配置文件、帮助文本,以及向应用商店提交应用时需要电子邮件的任何地方。

  • URL:你的应用程序的登陆页面的URL。同样,如果你拥有自己的域名,在该域名上输入一个URL(包括 https://)。否则,就接受默认的 URL(https://example.com/helloworld)。这个 URL 不需要实际存在(目前),只有当你把你的应用程序发布到应用商店时才会用到。

  • 许可证 – License:接受默认的许可证(BSD)。不过这不会影响到教程的任何操作–所以如果你对许可证的选择有特别强烈的感受,可以自由选择其他许可证

  • GUI 框架 – GUI framework:选择 Toga (BeeWare 自己的 GUI 工具包,后续介绍)

然后 Briefcase 会生成一个项目框架供你使用,如果你按照我们给的示例写细节,你的文件系统应该是这样的:

beeware-tutorial/
    beeware-venv/
        ...
    helloworld/
        CHANGELOG
        LICENSE
        README.rst
        pyproject.toml
        src/
            helloworld/
                resources/
                    helloworld.icns
                    helloworld.ico
                    helloworld.png
                __init__.py
                __main__.py
                app.py
        tests/
            __init__.py
            helloworld.py
            test_app.py

这个框架实际上是一个功能齐全的应用程序,不需要添加任何其他东西。其中:

  • src 文件夹内包含了应用程序的所有代码,
  • test 文件夹包含了一个初始的测试套件。
  • pyproject.toml 文件则描述了如何对应用程序进行打包发布。

如果你在编辑器中打开 pyproject.toml,你会看到你刚刚提供给 Briefcase 的配置细节。

现在我们有了一个存根应用程序 (stub application),可以用 Briefcase 来运行这个应用程序了。

0x03 在开发者模式下运行应用程序

cd 至 helloworld 项目目录,告诉 briefcase 在 Developer 模式 (或 dev 模式) 下启动该项目:

cd helloworld    # cd至项目目录
briefcase dev    # 启动项目

[helloworld] Installing requirements...
...
[helloworld] Starting in dev mode...

然后我们只需稍等片刻,GUI 窗口就打开了:

恭喜你,你刚刚用 Python 写了一个独立的本地应用程序!

我们现在有了一个工作的应用程序,在开发者模式下运行。现在我们可以添加一些我们自己的逻辑,使我们的应用程序做一些更有趣的事情。下面我们将为我们的应用程序添加一个更有用的用户界面。

0x04 默认生成了什么?

在 src/helloworld 目录中你能看到三个文件,分别是 __init__.py,__main__.py 和 app.py

  • __init__.py:将 helloworld 目录标记为一个可导入的 Python 模块。它是一个空文件;它存在的事实告诉 Python 解释器,helloworld 目录定义了一个模块。
  • __main__.py:将 helloworld 模块标记为一种特殊的模块 – 一个可执行模块 (executable module)。如果你试图用 python -m helloworld 来运行 helloworld 模块,__main__.py 文件就是 Python 开始执行的地方。
  • app.py 中包含了创建应用程序窗口的逻辑。

其中 __main__.py 的内容相对简单,只有短短的 3 行代码:

from helloworld.app import main

if __name__ == '__main__':
    main().main_loop()

不难理解,它从 helloworld 应用程序导入 main 方法,如果它作为入口点执行,则调用 main() 方法,并启动应用程序的主循环,主循环是 GUI 应用程序侦听用户输入 (如鼠标点击和键盘按下) 的方式。

0x05 分析默认生成的 app.py

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()

是不是一脸茫然?不用担心,我们逐行解析它们!

🔑 详细解析:

① 首先我们导入 toga widget 工具包,以及一些与主题风格相关的实用类和常量。

import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW

② 然后我们定义了一个 class 类:

class HelloWorld(toga.App):

每个 Toga 应用程序都有一个 toga.App 实例,代表应用程序的运行实体。应用程序最终可能会管理多个窗口 (multiple windows),但对于简单的应用程序,只会有一个主窗口 (main window) 。

③ 下面,我们定义了一个 startup() 启动方法:

def startup(self):
    main_box = toga.Box()

startup 方法做的第一件事是定义一个主盒 (main box)。Toga 的布局方案的行为类似于 HTML,通过构建单盒 (single box) 的集合来建立一个应用程序,每个都包含其它的盒子,或一些部件 (actual widgets) 。然后,你将样式应用于这些盒子,以定义它们将如何使用可用的窗口空间。

在该应用程序中,我们只定义了单盒 (single box),没有放进去任何东西:

self.main_window = toga.MainWindow(title=self.formal_name)

这将创建一个 toga.MainWindow 的实例,它的标题将与应用程序的名称相符。在 Toga 中,主窗口是一种特殊的窗口,它是一个与应用程序的生命周期紧密相连的窗口。当主窗口销毁,应用程序就退出了。主窗口也是拥有应用程序菜单的窗口(如果你在像Windows这样的平台上,菜单栏是窗口的一部分)。

然后添加我们的 空盒 (empty box) 作为主窗口的内容,并指示应用程序显示我们的窗口:

self.main_window.content = main_box
self.main_window.show()

最后,我们定义了 main() 方法,它是创建我们应用程序的实例:

def main():
    return HelloWorld()

这个 main() 方法是由 __main__.py 导入和调用的,它创建并返回一个我们的 HelloWorld 应用程序的实例。这是最简单的 Toga 应用程序,让我们把一些我们自己的内容放到应用程序中,并让应用程序做一些有趣的事情!

0x06 添加一些我们自己的内容

我们可以尝试修改 src/helloworld/app.py 中的 HelloWorld 类:

class HelloWorld(toga.App):
    ## 启动函数
    def startup(self):
        ## 创建一个垂直排列的 Box 容器
        main_box = toga.Box(style=Pack(direction=COLUMN))
        
        ## 通过 toga.Label 创建一个标签
        name_label = toga.Label (
            "Input your name: ",        # 提示用户输出名字
            style=Pack(padding=(0, 5))
        )

        ## 通过 toga.TextInput 创建一个编辑框
        self.name_input = toga.TextInput(style=Pack(flex=1))

        ## 创建水平排列的 Box 容器,将标签和编辑框组合在一起
        name_box = toga.Box (
            style = Pack(direction = ROW, padding = 5)
        )
        name_box.add(name_label)         # 添加标签
        name_box.add(self.name_input)    # 添加编辑框

        ## 通过 toga.Button 创建按钮
        button = toga.Button (
            "Click here to say hello",   # 按钮内容
            on_press = self.say_hello,   #按钮1_被单击 -> 触发 say_hello 函数
            style = Pack(padding = 5)    # 设置按钮风格
        )

        ## 将组件添加到主框中 [*]
        main_box.add(name_box)   # 添加 - 刚才创建的水平排列的 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(f"Hello, {self.name_input.value}")
        print("hello world!\n");

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2022.3.
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

Write once. Deploy everywhere.— BeeWare

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年4月26日
下一篇 2023年4月26日

相关推荐