Edifice

Edifice 是一个 Python 下的声明式 UI 库,深受前端 React 的影响。

Edifice 使用 Qt(PySide、PyQt)作为底层,为 Qt 带来了一种声明式开发方式。

相较于传统的命令式编程,声明式编程提升了开发效率与开发体验。

2024 年,很高兴看到 Edifice 又进入活跃维护状态。

我曾经写过一篇 Edifice 介绍文章《Edifice:Python 声明式 UI 库 - Maxiee Blog》,本文作为该内容的延续。

Hello World:

import edifice
from edifice import Label

edifice.App(Label("Hello World!")).start()

其中:

通过 Hello world 可以看出,基于 Edifice 的写法与传统 Qt 完全不同,非常简洁。


Edifice 的优势

Edifice 为 Python GUI 开发带来了声明式编程,Edifice 的优势就是声明式编程相较于命令式编程的优势。

对于声明式 GUI 开发,我们只需要声明页面展示元素,而无需关注元素控件的创建、销毁。我们只需要声明屏幕上有什么即可

对于传统的 Qt、Tkinter 来说,采用命令式编程,我们需要手动地将视图元素显式添加、删除,并且手动维护,比如布局变化时,手动删除、调整,费时费力,而这些基于声明式开发,都会由框架自动完成

Edifice 还提供了两个非常方便的 GUI 开发功能:

尽管 Edifice 自身只覆盖了部分 Qt 组件,但 Edifice 提供了强大的灵活性、扩展性,能够让开发者,方便地自行对 Qt 组件进行封装,引入 Edifice。


Edifice vs QML

Edifice 完全基于 Python 编写,在 PySide、PyQt 语境下无需切换技术栈,UI、实现逻辑都是统一、一体的 Python 实现。而 QML 需要脱离 Python 语境,使用 QML 的写法实现。

因为 Edifice 完全基于 Python 编写,Edifice 与 Python 代码的融合度更高。

Edifice 能够支持更强大的动态布局,在运行时能够更加灵活地进行布局变更。而 QML 更加偏向于静态布局。


Stateful Component

Edifice 继承了 React 中的 state 概念:

import edifice

class Timer(edifice.Component):
    def __init__(self):
        super().__init__()
        self.seconds = 0
        self.timer = edifice.Timer(lambda: self.set_state(seconds=self.seconds+1))

    def did_mount(self):
        self.timer.start(1000)

    def render(self):
        return edifice.Label(
	        self.seconds, 
	        style={"width": 80, "height": 30, "font-size": 20})

edifice.App(Timer()).start()

其中:


复杂场景:Todo

官方示例 Demo:

import datetime
import edifice
from edifice import Button, Label, TextInput, ScrollView, View

# 继承自 edifice.Component 表示组件
class TodoApp(edifice.Component):
    def __init__(self):
        super().__init__()
        # 初始化状态
        self.items = []
        self.text = ""

    # 渲染方法
    def render(self):
        # View 布局容器,默认是纵向
        return View(style={"margin": 10})(
            Label("TODO"),
            # 带有 Props 的自定义组件
            TodoList(items=self.items),
            # View 布局容器,调整为横向
            View(layout="row")(
                Label("What needs to be done?"),
                # 一个典型的受控组件,以及事件响应
                TextInput(self.text,
                          on_change=lambda text:self.set_state(text=text)),
                # 按钮
                Button(f"Add #{len(self.items)+1}",
                       on_click=self.add_item)
            )
        )

	# 点击事件回调,注意参数 e
    def add_item(self, e):
        if not self.text:
            return
        # 状态更新
        new_item = dict(text=self.text, id=datetime.datetime.now())
        self.set_state(items=self.items + [new_item])

class TodoList(edifice.Component):
	# 注册 props
	@edifice.register_props
    def __init__(self, items):
        pass

    def render(self):
	    # 滑动列表组件
        return ScrollView()(
	        # 使用生成器创建 item 元素
            *[Label(f"* {item['text']}").set_key(item['id'])
              for item in self.props.items]
        )

edifice.App(TodoApp()).start()

网络资源


本文作者:Maeiee

本文链接:Edifice

版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!


喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!