8

python Gui编程工具详解:beeware - wan了个蛋

 1 year ago
source link: https://www.cnblogs.com/qtclm/p/17152723.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

各个gui开发工具对比

Flexx: 可以使用Flexx创建桌面应用程序和web应用程序,同时可以将程序导出到独立的HTML文档中,GitHub推荐
Kivy&BeeWare: 只需编写一套代码便可轻松运行于各大移动平台和桌面上,像Android,iOS,Linux,OS X和Windows,https://blog.csdn.net/ZNJIAYOUYA/article/details/126553693,两者各有特别,kivy更灵活,后者兼容性好
Pyforms:  旨在提高开发效率,用于开发可以在Windows GUI模式、Web模式或终端模式下执行的应用程序
PyQt: 目前最强大的库之一,可以使用Python做任何C++能做的事
PyAutoGUI:  利用它可以实现所有GUI自动化,无需机械性操作
wxPython: wxPython具有非常优秀的跨平台能力,可以在不修改程序的情况下在多种平台上运行

为啥选择beeware

1.支持跨平台开发
2.相对Kivy更简单,兼容性更好,kivy灵活性更高,所以建议结合实际情况选择

beeware官方教程:https://docs.beeware.org/en/latest/tutorial/tutorial-0.html
中文文档:https://github.com/xianchengyue/Beeware--

1.设置虚拟环境

1.mkdir beeware-tutorial
2.python3 -m venv beeware-venv #创建虚拟环境
3.source beeware-venv/bin/activate (windows:使用git bash工具执行) #切换至虚拟环境
4.beeware-venv\Scripts\activate.bat (windows:cmd执行)#切换至虚拟环境

2.创建第一个应用

1.安装briefcase: pip install briefcase
2.新建项目:briefcase new ,之后的内容按需填写即可,Pyproject.toml 文件描述了如何对应用程序进行打包以便发行
3.在开发者模式下运行应用程序: cd project_dir && briefcase dev
4.项目结构说明:__init__.py:标记项目目录是一个python包,__main__.py 将项目目录标记为一个特殊的可执行模块,app.py:创建app窗口的逻辑

打包以便发布

1.创建应用程序脚手架: briefcase create
2.搭建应用程序: 编译:briefcase build 
3.运行app: briefcase run
4.搭建安装包: macos: briefcase package --no-sign;Linux&Windows:briefcase package,详细说明:https://briefcase.readthedocs.io/en/latest/how-to/code-signing/macOS.html

更新app

1.briefcase dev: 每次执行都能看到修改后最新的效果
2.briefcase run:则不会,需要先执行:briefcase update,然后在执行briefcase run,最后使用briefcase package 命令重新打包app 以便分发
3.macOS 的用户记住在第三章中提到的使用 briefcase package 命令时带上 --no-sign 标志避免设置代码签名标识的复杂工作并使教程尽可能简单
4.一步更新和运行: briefcase run -u,会自动触发更新,重新打包:briefcase package -u

使之成为移动 app

1.IOS:
    1.安装xcode
    2.briefcase create iOS #创建app
    3.briefcase build iOS #编译
    4.briefcase run iOS ,运行时指定设备名称&选择特定版本的iOS,-d "设备名称::ios 版本号",使用特定设备的UDID名称: -d 4768AA69-497B-4B37-BD0C-3961756C38AC
2.安卓
    1.MacOs&Liunx&windows: briefcase create android ,首次执行会比较慢,会自动下载java jdk与安装sdk #创建app
    2.briefcase build android ,Gradle可能停止工作:将会打印CONFIGURING:100%,但看起来什么事也没做,此时它在下载更多安卓SDK组件 #编译app
    4.模拟设备上运行app: 
        1.briefcase run android ,执行此命令会提示你可运行app的设备清单,最后一个选项始终是创建一个新的安卓模拟器 #运行app
        2.如果模拟器没启动: 执行briefcase run检查一下终端找到错误信息
        3.如果你想不使用菜单在设备上运行app: briefcase run android -d @beePhone
    5.实体设备上运行app: 
        1.启用开发者选项;2.启用USB调试;3.briefcase run android,直接运行:briefcase run android -d 设备标识号
        2.我的设备没有出现: 要么你没有启动 USB 调试,要么设备根本没插进去
        3.显示为“未知设备(不是未授权开发): 1.重新启用开发者模式;2.然后重新运行 briefcase run android 命令

开始使用第三方库

1.访问 API:使用jsonplaceholder(https://jsonplaceholder.typicode.com)作为数据源
2.安装第三库,例如:pip install httpx
3.briefcase dev #本地运行
4.briefcase update : 更新app代码
5.briefcase build : 编译app
6.briefcase run : 运行app 
7.启动时提示module not found: 
    1.修改app全局依赖: key:[tool.briefcase.app.appname]
        1.修改pyproject.toml,修改requires,将依赖添加至requires
        2.添加时可以指定版本与版本范围,例如:httpx==0.19.0,httpx>=0.19
        3.指定克隆仓库的路径: 如"git+https://github.com/encode/httpx"
    2.修改指定平台的依赖: key:[tool.briefcase.app.appname.macOS、windows、linux、iOS、web、android]
        1.修改pyproject.toml,修改requires,将依赖添加至requires
8.Python只在移动端:
    1.在桌面平台: 任何pip能安装的都可以被添加到你的需求中
    2.在移动平台: 只能使用纯Python包及包中不能包含二进制模块,numpy、scikit-learn、cryptography等不能在移动平台上使用
9. briefcase update -d #更新依赖
10.briefcase build #编译
11. briefcase run # 运行

让app运行更流畅

1.GUI事件循环: 当app正在处理一个事件,不能重绘也不能处理其他事件
2.异步编程: 使用 async 和 await 关键字实现
3.制作异步教程
    ![img.png](img.png)
    ![img_1.png](img_1.png)

测试app

1.briefcase dev -r #自动检查依赖安装情况
2.briefcase dev --test #执行测试
3.test_app.py #编写测试用例
4.briefcase run --test -r #运行时测试
5.briefcase run iOS --test、 briefcase run android --test #指定平台运行测试用例

实战:开始撸代码

项目配置文件详解

1.https://briefcase.readthedocs.io/en/latest/reference/index.html

Toga小部件工具详解

1.https://toga.readthedocs.io/en/latest/tutorial/index.html
2.安装toga依赖: pip install toga

1.编写应用程序

1.代码示例:

import toga

def button_handler(widget):
    print("hello")

def build(app):
    box = toga.Box()
    button = toga.Button("Hello world", on_press=button_handler)
    button.style.padding = 50
    button.style.flex = 1
    box.add(button)
    return box

def main():
    return toga.App("First App", "org.beeware.helloworld", startup=build)

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

2.细节介绍

1.button_handler方法:widget参数,该函数将激活的小部件作为第一个参数
2.build方法: app参数,为toga.app实例,用于自定义app启动的方法
3.toga.Box: 盒子是一个对象,可用于容纳多个小部件,并定义小部件周围的填充
4.toga.Button: 定义一个按钮,参数1:按钮的展示名称;2.on_press:点击按钮后触发的行为(函数对象)
5.button.style: 定义按钮在窗口中的显示方式,默认情况下,Toga 使用一种名为 的样式算法Pack,有点像“CSS-lite”
    1.button.style.padding = 50 #按钮的所有边都有 50 像素的填充
    2.padding_top = 20 padding = (20, 50, 50, 50) #在按钮顶部定义20像素的填充
    3.button.style.flex = 1 #使按钮占据所有可用宽度
6.box.add(button): 将按钮添加到框中
7.return box: 返回包含所有 UI 内容的外部盒子,此框将是应用程序主窗口的内容
1.建议首先创建一个虚拟环境
2.Toga 有一些最低要求:
    如果您使用的是 macOS,则需要使用 10.10 (Yosemite) 或更高版本。
    如果您使用的是 Linux,则需要 GTK+ 3.10 或更新版本。这是从 Ubuntu 14.04 和 Fedora 20 开始发布的版本。
    如果您使用的是 Windows,则需要安装 Windows 10 或更新版本。
3.运行脚本: cd 项目/src && python -m 项目名称

2.来写一个更复杂一点的页面:华氏度到摄氏度转换器

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


def build(app):
    c_box = toga.Box()
    f_box = toga.Box()
    box = toga.Box()

    c_input = toga.TextInput(readonly=True)
    f_input = toga.TextInput()

    c_label = toga.Label("Celsius", style=Pack(text_align=LEFT))
    f_label = toga.Label("Fahrenheit", style=Pack(text_align=LEFT))
    join_label = toga.Label("is equivalent to", style=Pack(text_align=RIGHT))

    def calculate(widget):
        try:
            c_input.value = (float(f_input.value) - 32.0) * 5.0 / 9.0
        except ValueError:
            c_input.value = "???"

    button = toga.Button("Calculate", on_press=calculate)

    f_box.add(f_input)
    f_box.add(f_label)

    c_box.add(join_label)
    c_box.add(c_input)
    c_box.add(c_label)

    box.add(f_box)
    box.add(c_box)
    box.add(button)

    box.style.update(direction=COLUMN, padding=10)
    f_box.style.update(direction=ROW, padding=5)
    c_box.style.update(direction=ROW, padding=5)

    c_input.style.update(flex=1)
    f_input.style.update(flex=1, padding_left=160)
    c_label.style.update(width=100, padding_left=10)
    f_label.style.update(width=100, padding_left=10)
    join_label.style.update(width=150, padding_right=10)

    button.style.update(padding=15)

    return box


def main():
    return toga.App("Temperature Converter", "org.beeware.f_to_c", startup=build)


if __name__ == "__main__":
    main().main_loop()
1.此示例展示了 Toga 的 Pack 风格引擎的更多功能。在这个示例应用程序中,我们设置了一个垂直堆叠的外框;在那个盒子里,我们放了 2 个水平盒子和一个按钮。
2.由于水平框上没有宽度样式,它们将尝试将它们包含的小部件放入可用空间。
3.小TextInput 部件的样式为flex=1,但是Label小部件的宽度是固定的;
4.结果,TextInput小部件将被拉伸以适应可用的水平空间。然后,边距和填充项确保小部件将垂直和水平对齐。
5.toga.TextInput: 定义一个文本输入框,readonly=True:设置为不可编辑
6.toga.Label: 定义表头,text_align:文字对齐方式,LEFT:居左,RIGHT:居右
7.box.style: 定义按钮在窗口中的显示方式,默认情况下,Toga 使用一种名为 的样式算法Pack,有点像“CSS-lite”
    1.box.style.padding = 50 #按钮的所有边都有 50 像素的填充
    2.padding = (20, 50, 50, 50) #在按钮顶部定义20像素的填充
    3.box.style.flex = 1 #使按钮占据所有可用宽度
    4.box.style.update: 更新页面布局,direction:指定方向
    5.box、button、input、label均可设置style

把盒子放在另一个盒子里:涉及布局、滚动条和其他容器内的容器

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

def button_handler(widget):
    print("button handler")
    for i in range(0, 10):
        print("hello", i)
        yield 1
    print("done", i)


def action0(widget):
    print("action 0")


def action1(widget):
    print("action 1")


def action2(widget):
    print("action 2")


def action3(widget):
    print("action 3")


def action5(widget):
    print("action 5")


def action6(widget):
    print("action 6")


def build(app):
    brutus_icon = "icons/brutus"
    cricket_icon = "icons/cricket-72.png"

    data = [("root%s" % i, "value %s" % i) for i in range(1, 100)]

    left_container = toga.Table(headings=["Hello", "World"], data=data)

    right_content = toga.Box(style=Pack(direction=COLUMN, padding_top=50))

    for b in range(0, 10):
        right_content.add(
            toga.Button(
                "Hello world %s" % b,
                on_press=button_handler,
                style=Pack(width=200, padding=20),
            )
        )

    right_container = toga.ScrollContainer(horizontal=False)

    right_container.content = right_content

    split = toga.SplitContainer()

    # The content of the split container can be specified as a simple list:
    #    split.content = [left_container, right_container]
    # but you can also specify "weight" with each content item, which will
    # set an initial size of the columns to make a "heavy" column wider than
    # a narrower one. In this example, the right container will be twice
    # as wide as the left one.
    split.content = [(left_container, 1), (right_container, 2)]

    # Create a "Things" menu group to contain some of the commands.
    # No explicit ordering is provided on the group, so it will appear
    # after application-level menus, but *before* the Command group.
    # Items in the Things group are not explicitly ordered either, so they
    # will default to alphabetical ordering within the group.
    things = toga.Group("Things")
    cmd0 = toga.Command(
        action0,
        text="Action 0",
        tooltip="Perform action 0",
        icon=brutus_icon,
        group=things,
    )
    cmd1 = toga.Command(
        action1,
        text="Action 1",
        tooltip="Perform action 1",
        icon=brutus_icon,
        group=things,
    )
    cmd2 = toga.Command(
        action2,
        text="Action 2",
        tooltip="Perform action 2",
        icon=toga.Icon.TOGA_ICON,
        group=things,
    )

    # Commands without an explicit group end up in the "Commands" group.
    # The items have an explicit ordering that overrides the default
    # alphabetical ordering
    cmd3 = toga.Command(
        action3,
        text="Action 3",
        tooltip="Perform action 3",
        shortcut=toga.Key.MOD_1 + "k",
        icon=cricket_icon,
        order=3,
    )

    # Define a submenu inside the Commands group.
    # The submenu group has an order that places it in the parent menu.
    # The items have an explicit ordering that overrides the default
    # alphabetical ordering.
    sub_menu = toga.Group("Sub Menu", parent=toga.Group.COMMANDS, order=2)
    cmd5 = toga.Command(
        action5, text="Action 5", tooltip="Perform action 5", order=2, group=sub_menu
    )
    cmd6 = toga.Command(
        action6, text="Action 6", tooltip="Perform action 6", order=1, group=sub_menu
    )

    def action4(widget):
        print("CALLING Action 4")
        cmd3.enabled = not cmd3.enabled

    cmd4 = toga.Command(
        action4, text="Action 4", tooltip="Perform action 4", icon=brutus_icon, order=1
    )

    # The order in which commands are added to the app or the toolbar won't
    # alter anything. Ordering is defined by the command definitions.
    app.commands.add(cmd1, cmd0, cmd6, cmd4, cmd5, cmd3)
    app.main_window.toolbar.add(cmd1, cmd3, cmd2, cmd4)

    return split
注意: 为了呈现图标,您需要将图标文件夹移动到与应用程序文件相同的目录中。
1.toga.Table: 定义一个表格,参数详细说明:
    1.headings(表头)=["Hello", "World","desc"], data(内容)=data
    2.id:唯一标识符;3.style:指定样式
    3.accessors:访问器,multiple_select:支持多选框,
    4.on_select:提供的回调函数必须接受两个参数表(obj:“表”)和行(' '行' '或' '没有' '),on_double_click:双点击提供的回调函数必须接受两个参数表(obj:“表”)和行(' '行' '或' '没有' '),
    5.missing_value:缺省值,factory:已经弃用
2.toga.ScrollContainer: 定义一个滚动条,参数详细说明:
    1.horizontal:True(为水平,即横向滚动条),False(为垂直,即纵向滚动条)
3.toga.SplitContainer: 定义一个拆分控件,分别展示,参数详细说明:
        1.id:指定唯一标识符,style:指定样式,
        2.direction:是否水平展示,默认垂直展示,content:切换的内容,
        例如:[(left_container, 1), (right_container, 2)]
        3.factory:已经弃用
4.toga.Group:定义一个顶部选项卡(菜单),参数详细说明:
    1.text:菜单名称,order:指定排序,section:是否部件,
    2.parent:指定父级选项卡,label:目前已经弃用
    4.系统默认可调用的对象:
        Group.APP = Group("*", order=0)
        Group.FILE = Group("File", order=1)
        Group.EDIT = Group("Edit", order=10)
        Group.VIEW = Group("View", order=20)
        Group.COMMANDS = Group("Commands", order=30)
        Group.WINDOW = Group("Window", order=90)
        Group.HELP = Group("Help", order=100)
5.toga.Command: 需要调用命令时使用,参数详细说明:
    1.action:函数对象,text:标题,shortcut:命令描述,icon:指定展示图标,
    2.group:所属的选项卡,section:是否部件,order:指定排序,enabled:是否启用,factory&label:已经弃用
6.app.commands.add: 添加一组命令到commands选项卡中
7.app.main_window(程序主运行窗口).toolbar:工具栏操作,add添加
8.app.main_window.info_dialog: 正常提示弹窗,error_dialog:错误提示弹窗

构建一个浏览器

尽管可以构建复杂的 GUI 布局,但您可以使用现代平台上原生的丰富组件,用很少的代码获得很多功能

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


class Graze(toga.App):
    def startup(self):
        self.main_window = toga.MainWindow(title=self.name)

        self.webview = toga.WebView(
            on_webview_load=self.on_webview_loaded, style=Pack(flex=1)
        )
        self.url_input = toga.TextInput(
            value="https://beeware.org/", style=Pack(flex=1)
        )

        box = toga.Box(
            children=[
                toga.Box(
                    children=[
                        self.url_input,
                        toga.Button(
                            "Go",
                            on_press=self.load_page,
                            style=Pack(width=50, padding_left=5),
                        ),
                    ],
                    style=Pack(
                        direction=ROW,
                        alignment=CENTER,
                        padding=5,
                    ),
                ),
                self.webview,
            ],
            style=Pack(direction=COLUMN),
        )

        self.main_window.content = box
        self.webview.url = self.url_input.value

        # Show the main window
        self.main_window.show()

    def load_page(self, widget):
        self.webview.url = self.url_input.value

    def on_webview_loaded(self, widget):
        self.url_input.value = self.webview.url


def main():
    return Graze("Graze", "org.beeware.graze")


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

在此示例中,您可以看到一个应用程序被开发为一个类,而不是一个构建方法。
您还可以看到以声明方式定义的框 - 如果您不需要保留对特定小部件的引用,您可以内联定义一个小部件,并将其作为参数传递给框,它将成为那个盒子。

1.toga.WebView: 指定一个web页面

打造独家app

1.添加图标
2.下一步

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK