Skip to content

zimolab/PyGUIAdapter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PyGUIAdapter

一、简介

PyGUIAdapter是一个用于快速构建图形用户界面的Python库,只需极少的代码,就可以将几乎任意Python函数无缝转化为图形用户界面,大大简化了GUI应用程序的开发过程。PyGUIAdapter的核心理念是,以尽可能“无感”和“低侵入性”的方式,帮助开发者创建用户界面,使开发者能够专注于核心功能的实现,而不必将精力分散到复杂、繁琐的GUI编程上,降低了开发者的学习成本和心智负担。

二、适用场景

PyGUIAdapter与“输入(Input)-处理(Process)-输出(Output)”程序设计模式高度契合,特别适合用于:

  • 工具类应用程序的开发;
  • 将现有的CLI应用快速迁移到GUI

下面是Python官方文档给出的一个使用argparse创建命令行的例子:

import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                    help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))

借助PyGUIAdapter,开发者可以用极少的代码将其转换成GUI程序。

from typing import List, Literal
from pyguiadapter.adapter import GUIAdapter


def process_integers(
    integers: List[int], operation: Literal["sum", "max"] = "max"
) -> int:
    """
    Process some integers.

    @param integers: an integer for the accumulator
    @param operation: sum the integers (default: find the max)
    """
    func = max if operation == "max" else sum
    return func(integers)


if __name__ == "__main__":
    adapter = GUIAdapter()
    adapter.add(process_integers)
    adapter.run()

三、特性

  • 使用简单,开发快速,可以用极少的代码创建图形用户界面,学习成本低,心智负担小。
  • 丰富的内置控件类型,近30种内置控件,基本实现开箱即用。Python的基本数据类型均实现了对应输入控件。同时,对基本类型进行了扩展,提供了丰富的语义类型,方便用户输入日期、时间、颜色、文件路径等特殊对象。实现了通用对象输入控件,支持输入Json对象和任意Python字面量对象(包括intfloatboolstrbyteslisttuplesetdict)。
  • 高度可扩展性,提供了自定义控件接口。开发者可以很方便地为自定义数据类型实现专用输入控件。
  • 高度灵活性。控件与窗口均定义了大量可配置属性,开发者可以灵活地调整控件及窗口的外观、样式、行为,提升用户体验。
  • 支持使用QSS,自由定制界面风格,支持接入现有第三方界面美化库。
  • 支持自定义窗口菜单栏、工具栏,支持监听窗口事件,支持动态修改控件,为构建复杂应用提供了可能。
  • 基于qtpy抽象层,不依赖特定Qt绑定库,用户可自由选择PyQt5PyQt6PySide2PySide2
  • 界面底层使用Qt,兼容性好,相比webview类方案,系统资源占用更小。
  • 纯Python,跨平台,支持主流桌面操作系统,包括WindowsLinuxMacOS等。

四、快速开始

(一)依赖条件

要使用PyGUIAdapter开发应用程序,需满足以下条件:

  • Python 3.8+
  • 安装PyGUIAdapter
  • 安装Qt的绑定库之一,可选PyQt5PyQt6PySide2PySide6

(二)安装依赖

1、安装PyGUIAdapter

pip install PyGUIAdapter

2、安装Qt的绑定库之一,这里以PySide2为例:

pip install pyside2

如果你的环境下同时安装了多个Qt绑定库,qtpy默认会使用PyQt5(如果存在的话)。或者可以通过环境变量QT_API来明确指定要使用的绑定库,可以指定以下值:

  • pyqt5
  • pyside2
  • pyqt6
  • pyside6

更多详细信息,可以参见qtpy官方说明

(三)编写代码

1、实现业务逻辑,并封装为函数。

from typing import Optional

from pyguiadapter.adapter.uoutput import uprint
from pyguiadapter.exceptions import ParameterError


def equation_solver(a: float = 1.0, b: float = 0.0, c: float = 0.0) -> Optional[tuple]:
    """A simple equation solver for equations like:

    **ax^2 + bx + c = 0** (a, b, c ∈ **R** and a ≠ 0)

    @param a: a ∈ R and a ≠ 0
    @param b: b ∈ R
    @param c: c ∈ R
    @return:
    """
    if a == 0:
        raise ParameterError(parameter_name="a", message="a cannot be zero!")
    uprint(f"Equation:")
    uprint(f"  {a}x² + {b}x + {c} = 0")
    delta = b**2 - 4 * a * c
    if delta < 0:
        return None
    x1 = (-b + delta**0.5) / (2 * a)
    if delta == 0:
        return x1, x1
    x2 = (-b - delta**0.5) / (2 * a)
    return x1, x2

2、为业务代码适配GUI界面

from pyguiadapter.adapter import GUIAdapter
...
if __name__ == "__main__":
    adapter = GUIAdapter()
    adapter.add(equation_solver)
    adapter.run()

完整代码如下:

from typing import Optional

from pyguiadapter.adapter import GUIAdapter
from pyguiadapter.adapter.uoutput import uprint
from pyguiadapter.exceptions import ParameterError


def equation_solver(a: float = 1.0, b: float = 0.0, c: float = 0.0) -> Optional[tuple]:
    """A simple equation solver for equations like:

    **ax^2 + bx + c = 0** (a, b, c ∈ **R** and a ≠ 0)

    @param a: a ∈ R and a ≠ 0
    @param b: b ∈ R
    @param c: c ∈ R
    @return:
    """
    if a == 0:
        raise ParameterError(parameter_name="a", message="a cannot be zero!")
    uprint(f"Equation:")
    uprint(f"  {a}x² + {b}x + {c} = 0")
    delta = b**2 - 4 * a * c
    if delta < 0:
        return None
    x1 = (-b + delta**0.5) / (2 * a)
    if delta == 0:
        return x1, x1
    x2 = (-b - delta**0.5) / (2 * a)
    return x1, x2


if __name__ == "__main__":
    adapter = GUIAdapter()
    adapter.add(equation_solver)
    adapter.run()

界面效果如下:

3、限制条件

PyGUIAdapter几乎可以将任意的Python函数转换成图形用户界面,但也存在一些限制条件:

  • 不支持lambda函数和一些内置函数
  • 不支持参数列表带有Positional-Only参数的函数,如:
def foo(a: int, b: int, /, c: int, d: int):
    pass

可能还有一些其他未知的限制,当然,不用担心,经过大量的测试,普通的python函数基本都可以无缝转化为图形用户界面。

对应不能直接转换的情形,也可以通过非常简单的方式解决,将函数包装一层即可,比如:

def foo(a: int, b: int, /, c: int, d: int):
    pass


def foo_wrapper(a: int, b: int, c: int, d: int):
    return foo(a, b, c, d)

if __name__ == "__main__":
    from pyguiadapter.adapter import GUIAdapter
    adapter = GUIAdapter()
    adapter.add(foo_wrapper)
    adapter.run()

五、文档

PyGUIAdapter还提供了许多高级特性,开发者可以阅读文档,了解PyGUIAdapter的进阶用法。以下是文档地址:

六、示例代码

为了演示PyGUIAdapter的各种功能, 作者编写了大量示例代码,这些代码可以在example/目录下找到。

七、许可协议

PyGUIAdapter使用MIT许可协议进行发布。得益于qtpy的抽象能力,PyGUIAdapter本身并不依赖特定的Qt绑定库。开发者在使用PyGUIAdapter开发应用程序时,若依赖特定的Qt绑定库,则在遵守本项目的许可协议的同时,还应当遵守所选绑定库的许可协议。例如:

  • 若开发者选择使用PySide2,则其须遵守LGPL(具体以随附的许可协议为准)。
  • 若开发者选择使用PyQt5,则其须遵守GPL(具体以随附的许可协议为准)。

八、致谢

PyGUIAdapter依赖如下开源项目,在此向作者表示感谢。

  • qtpy

  • qtawesome

  • docstring-parser

  • tomli

  • pyqcodeeditor

  • yapf

About

Turn almost any python functions into a GUI app

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published