SOUI4Python开发实战:用Python3构建高性能桌面应用

SOUI4Python开发实战:用Python3构建高性能桌面应用

【免费下载链接】soui4 soui是一套持续开发维护了14年的PC端APP开发框架,现已经支持windows, linux, macos三个PC平台,后续也可能增加移动端支持,敬请期待! 【免费下载链接】soui4 项目地址: https://gitcode.com/setoutsoft/soui4

引言:Python桌面开发的性能困境与解决方案

你是否还在为Python桌面应用的性能问题而困扰?尝试过Tkinter的简陋界面、PyQt的臃肿体积、wxPython的复杂API?本文将带你探索一种革命性的解决方案——SOUI4Python框架,它完美结合了C++的性能优势与Python的开发效率,让你轻松构建高性能、高颜值的跨平台桌面应用。

读完本文,你将获得:

  • 掌握SOUI4Python框架的核心概念与架构
  • 学会如何搭建SOUI4Python开发环境
  • 能够使用XML设计精美的用户界面
  • 掌握事件处理、数据绑定等核心技术
  • 了解性能优化与跨平台部署的最佳实践

SOUI4框架简介:14年磨一剑的桌面开发利器

SOUI(Simple Object-Oriented User Interface)是一套持续开发维护了14年的PC端应用开发框架,目前已支持Windows、Linux、macOS三个平台。作为一款轻量级框架,SOUI4内核编译后体积仅1M左右,却提供了丰富的控件库和灵活的扩展机制。

SOUI4架构图

SOUI4的核心优势在于:

  • 高效性能:可选择GDI或Skia渲染引擎
  • 界面与逻辑分离:基于XML配置UI,支持lua、js等脚本语言
  • 丰富控件:内置百余种常用控件,支持自定义扩展
  • 跨平台支持:一套代码运行于Windows、Linux、macOS

官方文档:README.zh-CN.md 核心源码:SOUI/ 扩展控件:controls.extend/

SOUI4Python:架起Python与C++之间的桥梁

SOUI4Python(简称SPY)是SOUI4框架的Python3绑定,它通过高效的C++/Python桥接技术,让开发者能够充分利用Python的便捷性和SOUI4的高性能。

SOUI4Python的技术架构

mermaid

SOUI4Python的主要组件:

  • API封装层:将SOUI4的C++接口封装为Python友好的API
  • 事件循环桥接:协调Python解释器与SOUI4的事件循环
  • 类型转换系统:处理Python与C++之间的数据类型转换
  • 资源管理:简化Python环境下的SOUI资源加载

为什么选择SOUI4Python?

框架性能界面美观度开发效率跨平台体积
Tkinter一般
PyQt
wxPython
SOUI4Python

环境搭建:从零开始配置开发环境

系统要求

  • Python 3.6+
  • Windows 7+ / Linux (Ubuntu 18.04+) / macOS 10.13+
  • CMake 3.10+ (编译SOUI4核心库)
  • 编译器:
    • Windows: Visual Studio 2017+ 或 MinGW-w64
    • Linux: GCC 7+
    • macOS: Clang 9+

获取源码与安装

首先,克隆SOUI4仓库:

git clone https://gitcode.com/setoutsoft/soui4.git
cd soui4

SOUI4Python的安装有两种方式:使用预编译包或手动编译。

使用预编译包(推荐)
# Windows
pip install soui4py -i https://pypi.tuna.tsinghua.edu.cn/simple

# Linux/macOS
pip3 install soui4py -i https://pypi.tuna.tsinghua.edu.cn/simple
手动编译
# 拉取子模块
git submodule update --init

# 创建构建目录
mkdir build && cd build

# 生成项目文件
cmake .. -DCMAKE_INSTALL_PREFIX=./install -DBUILD_PYTHON_BINDINGS=ON

# 编译
make -j8

# 安装Python包
cd python
pip install .

编译文档:doc/build.md 编译工具:tools/

验证安装

创建一个简单的Python脚本验证安装是否成功:

import soui4

app = soui4.Application()
print(f"SOUI4Python version: {soui4.__version__}")
print(f"Supported render engines: {soui4.get_supported_render_engines()}")

运行脚本,如果输出SOUI4Python版本和支持的渲染引擎列表,则说明安装成功。

第一个SOUI4Python应用:Hello World

让我们从经典的"Hello World"程序开始,体验SOUI4Python的开发流程。

项目结构

一个典型的SOUI4Python应用具有以下结构:

hello_soui/
├── main.py              # Python主程序
├── res/                 # 资源目录
│   ├── ui/
│   │   └── main.xml      # 界面描述文件
│   ├── images/           # 图片资源
│   └── theme/            # 主题文件
└── soui-sys-resource/    # 系统资源(可选)

编写界面XML文件

创建res/ui/main.xml文件:

<window size="400,200" caption="0,0,0,30" title="SOUI4Python Hello World">
    <text name="txt_hello" pos="center" text="Hello, SOUI4Python!" font="20" color="#FF0000"/>
    <button name="btn_quit" pos="150,120,250,150" text="Quit" />
</window>

编写Python代码

创建main.py文件:

import soui4
from soui4 import Window, EventInfo

class HelloWindow(Window):
    def __init__(self):
        # 加载XML界面
        super().__init__("res/ui/main.xml")
        
        # 获取控件引用
        self.btn_quit = self.find_control("btn_quit")
        
        # 绑定事件处理函数
        self.btn_quit.on_click = self.on_quit_click
        
    def on_quit_click(self, event: EventInfo):
        # 关闭窗口
        self.close()

if __name__ == "__main__":
    # 创建应用实例
    app = soui4.Application()
    
    # 设置中文字体支持
    app.set_default_font("simsun.ttc", 12)
    
    # 创建并显示窗口
    window = HelloWindow()
    window.show()
    
    # 运行消息循环
    app.run()

运行应用

python main.py

你将看到一个带有"Hello, SOUI4Python!"文本和"Quit"按钮的窗口。点击按钮将关闭应用。

Hello World程序截图

界面设计:XML布局与样式系统

SOUI4采用XML描述用户界面,将界面设计与业务逻辑分离。这种方式不仅提高了开发效率,还便于设计师参与界面设计过程。

XML布局基础

SOUI4的XML布局系统支持以下核心概念:

  • 控件(Control):界面的基本构建块,如窗口、按钮、文本框等
  • 属性(Attribute):控制控件的外观和行为,如pos、size、text等
  • 布局(Layout):管理控件的排列方式,如水平布局、垂直布局等
  • 资源引用(Resource Reference):引用图片、字体等资源
常用布局属性
属性描述示例
pos控件位置pos="10,10" 或 pos="10,10,200,100"
size控件大小size="190,30"
margin外边距margin="5,5,5,5"
padding内边距padding="5,5,5,5"
align对齐方式align="center"
visible可见性visible="true"
enabled是否启用enabled="true"
布局管理器

SOUI4提供了多种布局管理器,用于自动排列控件:

<!-- 垂直布局 -->
<vertical layout="vbox" spacing="5" margin="10">
    <button text="Button 1" size="100,-1"/>
    <button text="Button 2" size="100,-1"/>
    <button text="Button 3" size="100,-1"/>
</vertical>

<!-- 水平布局 -->
<horizontal layout="hbox" spacing="5" margin="10">
    <button text="OK" size="80,-1"/>
    <button text="Cancel" size="80,-1"/>
</horizontal>

<!-- 网格布局 -->
<grid layout="grid" rows="2" cols="2" spacing="5">
    <text text="Name:" align="right"/>
    <edit name="edit_name"/>
    <text text="Age:" align="right"/>
    <edit name="edit_age" input_type="number"/>
</grid>

样式系统

SOUI4的样式系统允许你定义控件的外观,支持状态样式(如 hover、pressed 等)。样式可以在XML中内联定义,也可以在主题文件中集中管理。

内联样式
<button text="Styled Button">
    <style>
        <normal bg_color="#4CAF50" text_color="#FFFFFF" border_radius="4"/>
        <hover bg_color="#45a049"/>
        <pressed bg_color="#3d8b40"/>
        <disabled bg_color="#cccccc" text_color="#666666"/>
    </style>
</button>
主题文件

推荐将样式定义在单独的主题文件中,如theme.xml

<style name="Button" base="Button">
    <normal bg_color="#4CAF50" text_color="#FFFFFF" border_radius="4" padding="8,4"/>
    <hover bg_color="#45a049"/>
    <pressed bg_color="#3d8b40"/>
    <disabled bg_color="#cccccc" text_color="#666666"/>
</style>

<style name="Edit" base="Edit">
    <normal bg_color="#FFFFFF" border_color="#dddddd" border_width="1" border_radius="4" padding="4"/>
    <focused border_color="#4CAF50"/>
    <disabled bg_color="#f5f5f5"/>
</style>

然后在窗口XML中引用:

<window theme="theme.xml">
    <button text="Styled Button" class="Button"/>
    <edit class="Edit"/>
</window>

系统主题资源:soui-sys-resource/

事件处理:从基础到高级

SOUI4Python提供了灵活而强大的事件处理机制,支持多种事件绑定方式,满足不同场景的需求。

基础事件绑定

最常用的事件绑定方式是直接将事件处理函数赋值给控件的事件属性:

class MyWindow(Window):
    def __init__(self):
        super().__init__("main.xml")
        
        # 获取按钮控件
        self.btn_click = self.find_control("btn_click")
        
        # 绑定点击事件
        self.btn_click.on_click = self.on_button_click
        
    def on_button_click(self, event):
        # 显示消息框
        self.show_message_box("提示", "按钮被点击了!", soui4.MB_OK)

事件参数与事件类型

事件处理函数通常接收一个EventInfo对象,包含事件的详细信息:

def on_mouse_move(self, event):
    # 获取鼠标位置
    x = event.x
    y = event.y
    
    # 获取事件源
    sender = event.sender
    
    # 阻止事件冒泡
    event.handled = True

SOUI4支持丰富的事件类型,包括:

  • 鼠标事件:click, dblclick, mouse_down, mouse_up, mouse_move等
  • 键盘事件:key_down, key_up, key_press等
  • 控件事件:text_changed, selection_changed, value_changed等
  • 窗口事件:close, resize, move, paint等

高级事件处理

事件委托

对于复杂应用,可以使用事件委托模式,将事件处理逻辑集中管理:

class EventDelegate:
    @staticmethod
    def on_button_click(event):
        window = event.sender.get_top_level_window()
        window.show_message_box("提示", "按钮被点击了!", soui4.MB_OK)

# 绑定事件委托
button.on_click = EventDelegate.on_button_click
事件过滤器

事件过滤器允许在事件到达目标控件之前拦截和处理事件:

class LogEventFilter(soui4.IEventFilter):
    def before_event(self, event):
        print(f"Event: {event.type}, Sender: {event.sender.name}")
        return False  # 不阻止事件传播

# 安装事件过滤器
app.install_event_filter(LogEventFilter())

数据绑定:模型-视图分离

SOUI4Python提供了灵活的数据绑定机制,实现模型(Model)与视图(View)的分离,简化数据展示和编辑流程。

简单数据绑定

class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

class UserWindow(Window):
    def __init__(self):
        super().__init__("user_window.xml")
        
        # 创建数据对象
        self.user = User("张三", 30)
        
        # 获取控件
        self.txt_name = self.find_control("txt_name")
        self.txt_age = self.find_control("txt_age")
        
        # 绑定数据
        self.txt_name.bind_text(self.user, "name")
        self.txt_age.bind_text(self.user, "age")
        
        # 绑定按钮事件
        self.btn_save = self.find_control("btn_save")
        self.btn_save.on_click = self.on_save_click
        
    def on_save_click(self, event):
        # 保存数据(此时用户输入已自动更新到user对象)
        print(f"保存用户数据: {self.user.name}, {self.user.age}")

对应的XML布局:

<window size="300,200">
    <vertical margin="10" spacing="10">
        <horizontal spacing="5">
            <text text="姓名:" width="60" align="right"/>
            <edit name="txt_name" width="-1"/>
        </horizontal>
        <horizontal spacing="5">
            <text text="年龄:" width="60" align="right"/>
            <edit name="txt_age" width="-1" input_type="number"/>
        </horizontal>
        <button name="btn_save" text="保存" align="right"/>
    </vertical>
</window>

列表数据绑定

对于列表类控件(如列表框、下拉框等),SOUI4Python提供了更高级的数据源绑定:

class UserListWindow(Window):
    def __init__(self):
        super().__init__("user_list_window.xml")
        
        # 创建列表数据
        self.users = [
            User("张三", 30),
            User("李四", 25),
            User("王五", 35)
        ]
        
        # 获取列表控件
        self.list_users = self.find_control("list_users")
        
        # 创建并绑定数据源
        self.adapter = soui4.ObjectAdapter(self.users)
        self.adapter.bind_text(lambda user: user.name)
        self.adapter.bind_sub_text(lambda user: f"年龄: {user.age}")
        
        self.list_users.set_adapter(self.adapter)
        
        # 绑定选择事件
        self.list_users.on_selection_changed = self.on_selection_changed
        
    def on_selection_changed(self, event):
        # 获取选中项
        selected_index = self.list_users.selected_index
        if selected_index != -1:
            user = self.users[selected_index]
            print(f"选中用户: {user.name}")

扩展列表控件:controls.extend/SListCtrlEx.cpp

高级控件:表格、树状视图与富文本

SOUI4提供了丰富的高级控件,满足复杂界面需求。

表格控件(SListCtrl)

表格控件用于展示和编辑二维数据:

<listctrl name="list_data" size="-1,-1" header="true" edit_labels="true">
    <columns>
        <column text="姓名" width="100"/>
        <column text="年龄" width="60" align="center"/>
        <column text="邮箱" width="-1"/>
    </columns>
</listctrl>
# 获取表格控件
list_data = self.find_control("list_data")

# 添加数据行
list_data.add_item(["张三", "30", "zhangsan@example.com"])
list_data.add_item(["李四", "25", "lisi@example.com"])
list_data.add_item(["王五", "35", "wangwu@example.com"])

# 设置单元格数据
list_data.set_item_text(0, 1, "31")  # 将第一行第二列改为"31"

# 获取单元格数据
name = list_data.get_item_text(1, 0)  # 获取第二行第一列数据

树状视图(STreeCtrl)

树状视图用于展示层次化数据:

<treectrl name="tree_categories" size="-1,-1"/>
# 获取树状视图控件
tree_categories = self.find_control("tree_categories")

# 添加根节点
root = tree_categories.add_root("产品分类")

# 添加子节点
electronics = tree_categories.add_child(root, "电子产品")
tree_categories.add_child(electronics, "手机")
tree_categories.add_child(electronics, "电脑")

clothing = tree_categories.add_child(root, "服装")
tree_categories.add_child(clothing, "男装")
tree_categories.add_child(clothing, "女装")

# 展开根节点
tree_categories.expand(root)

树状控件实现:controls.extend/STreeBox.cpp

富文本控件(SRichEdit)

富文本控件支持格式化文本、图片插入等高级编辑功能:

<richedit name="richedit_content" size="-1,-1" scrollbars="vertical"/>
# 获取富文本控件
richedit_content = self.find_control("richedit_content")

# 设置富文本内容
richedit_content.set_rich_text("""
<h1>欢迎使用SOUI4Python</h1>
<p>这是一个富文本编辑器示例,可以展示不同的文本格式:</p>
<ul>
  <li>粗体文本: <b>加粗显示</b></li>
  <li>斜体文本: <i>斜体显示</i></li>
  <li>下划线: <u>下划线文本</u></li>
  <li>字体大小: <font size="20">大字体</font></li>
  <li>字体颜色: <font color="#FF0000">红色文本</font></li>
</ul>
""")

# 插入图片
richedit_content.insert_image("res/images/logo.png", 100, 100)

富文本控件实现:controls.extend/SChatEdit.cpp

主题与皮肤:打造个性化界面

SOUI4的主题系统允许你轻松定制应用的外观,实现品牌化和个性化。

主题资源结构

SOUI4的主题资源通常包含以下内容:

  • 图片资源:按钮、图标、背景等图片
  • XML样式文件:定义控件的样式
  • 颜色定义:集中管理应用的颜色方案
  • 字体定义:指定应用使用的字体

典型的主题资源目录结构:

theme/
├── images/
│   ├── btn_normal.png
│   ├── btn_hover.png
│   ├── btn_pressed.png
│   └── ...
├── colors.xml
├── fonts.xml
└── styles.xml

自定义主题

以下是一个简单的深色主题示例:

colors.xml:

<colors>
    <color name="bg_color" value="#2d2d2d"/>
    <color name="text_color" value="#ffffff"/>
    <color name="accent_color" value="#4CAF50"/>
    <color name="border_color" value="#444444"/>
    <color name="hover_color" value="#3d3d3d"/>
</colors>

styles.xml:

<style name="Window" base="Window">
    <normal bg_color="@bg_color"/>
</style>

<style name="Button" base="Button">
    <normal bg_color="#3d3d3d" text_color="@text_color" border_radius="4" padding="8,4"/>
    <hover bg_color="@hover_color"/>
    <pressed bg_color="@accent_color"/>
</style>

应用主题:

app = soui4.Application()
app.load_theme("theme/styles.xml")

系统主题资源:soui-sys-resource/theme_sys_res/

性能优化:让Python应用飞起来

虽然Python以开发效率著称,但在性能敏感的场景下,仍需进行针对性优化。SOUI4Python提供了多种优化手段,确保应用的高性能运行。

渲染性能优化

  1. 选择合适的渲染引擎
    • 简单界面:使用GDI渲染(内存占用小)
    • 复杂界面:使用Skia渲染(性能更好)
# 初始化时指定渲染引擎
app = soui4.Application(render_engine="skia")
  1. 启用硬件加速
# 启用GPU加速(仅Skia引擎支持)
app.enable_gpu_acceleration(True)
  1. 减少重绘区域
# 局部重绘而非整体重绘
control.invalidate(rect)  # 仅重绘指定区域

Python代码优化

  1. 使用C++扩展模块:将性能敏感的代码用C++实现,并通过SOUI4Python桥接

  2. 延迟加载与异步处理

# 使用异步任务加载数据
def load_large_data():
    # 耗时数据加载操作
    data = load_data_from_database()
    
    # 在UI线程更新界面
    def update_ui():
        list_ctrl.set_data(data)
    
    app.invoke_ui_thread(update_ui)

# 启动异步任务
app.post_task(load_large_data)
  1. 避免不必要的对象创建:在频繁调用的函数中,尽量重用对象而非创建新对象

内存管理

  1. 及时释放资源:对于大型资源(如图像、文档),不再使用时及时释放

  2. 使用对象池:对于频繁创建和销毁的对象(如列表项),使用对象池减少内存分配开销

  3. 监控内存使用

# 打印内存使用情况
print(f"内存使用: {soui4.get_memory_usage()} MB")

跨平台开发:一次编写,多平台运行

SOUI4Python支持Windows、Linux和macOS三大桌面平台,让你能够用一套代码覆盖多个操作系统。

平台差异处理

虽然SOUI4已经屏蔽了大部分平台差异,但在某些场景下仍需针对不同平台编写特定代码:

if soui4.get_platform() == "windows":
    # Windows平台特定代码
    window.set_window_style(soui4.WS_SYSMENU | soui4.WS_MINIMIZEBOX)
elif soui4.get_platform() == "linux":
    # Linux平台特定代码
    window.set_window_decorations(True)
elif soui4.get_platform() == "macos":
    # macOS平台特定代码
    window.set_title_bar_style(soui4.MAC_TITLE_BAR_UNIFIED)

资源适配

不同平台可能需要不同的资源适配策略:

  1. 图像资源适配
# 根据平台选择不同的图像资源
def get_image_path(image_name):
    platform = soui4.get_platform()
    return f"res/images/{platform}/{image_name}"
  1. 字体适配
# 根据平台设置默认字体
if soui4.get_platform() == "windows":
    app.set_default_font("simsun.ttc", 12)
elif soui4.get_platform() == "linux":
    app.set_default_font("simhei.ttf", 12)
elif soui4.get_platform() == "macos":
    app.set_default_font("Arial Unicode MS", 12)

跨平台编译与打包

Windows打包

使用pyinstaller打包:

pip install pyinstaller
pyinstaller --onefile --windowed --icon=res/icon.ico main.py
Linux打包

使用pyinstaller或打包为deb/rpm包:

# 使用pyinstaller
pyinstaller --onefile --windowed main.py

# 或创建deb包
sudo apt install python3-stdeb
python3 setup.py --command-packages=stdeb.command bdist_deb
macOS打包

使用pyinstaller或创建.app bundle:

pyinstaller --onefile --windowed --icon=res/icon.icns main.py

# 或创建.app bundle
python3 setup.py py2app

实战案例:构建一个简易文件管理器

为了综合运用前面所学的知识,我们将构建一个简易的文件管理器应用。

功能规划

我们的文件管理器将包含以下功能:

  • 目录浏览:显示当前目录下的文件和文件夹
  • 文件操作:打开、删除、重命名文件
  • 搜索功能:搜索指定目录下的文件
  • 视图切换:列表视图/图标视图切换

项目结构

file_manager/
├── main.py
├── ui/
│   ├── main_window.xml
│   ├── toolbar.xml
│   └── statusbar.xml
├── res/
│   ├── icons/
│   │   ├── folder.png
│   │   ├── file.png
│   │   ├── search.png
│   │   └── ...
│   └── theme/
│       ├── styles.xml
│       └── images/
└── utils/
    ├── file_utils.py
    └── ui_utils.py

核心代码实现

main_window.xml:

<window size="800,600" caption="0,0,0,32" title="SOUI文件管理器">
    <vbox>
        <!-- 工具栏 -->
        <include src="toolbar.xml"/>
        
        <!-- 主内容区 -->
        <hbox>
            <!-- 目录树 -->
            <treeview name="tree_dirs" width="200" splitter="true"/>
            
            <!-- 文件列表 -->
            <tabctrl name="tab_views">
                <tabpage text="列表视图">
                    <listctrl name="list_files" header="true">
                        <columns>
                            <column text="名称" width="-1"/>
                            <column text="大小" width="80" align="right"/>
                            <column text="修改日期" width="160"/>
                        </columns>
                    </listctrl>
                </tabpage>
                <tabpage text="图标视图">
                    <tileview name="tile_files" item_width="100" item_height="100"/>
                </tabpage>
            </tabctrl>
        </hbox>
        
        <!-- 状态栏 -->
        <include src="statusbar.xml"/>
    </vbox>
</window>

main.py:

import soui4
import os
import time
from utils.file_utils import get_file_icon, format_file_size, get_file_modified_time

class FileManagerWindow(soui4.Window):
    def __init__(self):
        super().__init__("ui/main_window.xml")
        
        # 获取控件引用
        self.tree_dirs = self.find_control("tree_dirs")
        self.list_files = self.find_control("list_files")
        self.tile_files = self.find_control("tile_files")
        self.txt_path = self.find_control("txt_path")
        self.btn_back = self.find_control("btn_back")
        self.btn_forward = self.find_control("btn_forward")
        self.btn_up = self.find_control("btn_up")
        self.btn_refresh = self.find_control("btn_refresh")
        self.txt_search = self.find_control("txt_search")
        self.btn_search = self.find_control("btn_search")
        self.statusbar = self.find_control("statusbar")
        
        # 初始化导航历史
        self.nav_history = []
        self.nav_index = -1
        
        # 绑定事件
        self.bind_events()
        
        # 初始化目录树
        self.init_dir_tree()
        
        # 显示初始目录
        self.navigate_to(os.path.expanduser("~"))
    
    def bind_events(self):
        # 导航按钮事件
        self.btn_back.on_click = self.on_back_click
        self.btn_forward.on_click = self.on_forward_click
        self.btn_up.on_click = self.on_up_click
        self.btn_refresh.on_click = self.on_refresh_click
        
        # 目录树事件
        self.tree_dirs.on_selection_changed = self.on_dir_selected
        
        # 文件列表事件
        self.list_files.on_item_double_click = self.on_file_double_click
        self.tile_files.on_item_double_click = self.on_file_double_click
        
        # 搜索事件
        self.btn_search.on_click = self.on_search_click
        self.txt_search.on_key_press = self.on_search_key_press
    
    def init_dir_tree(self):
        # 添加系统目录
        if soui4.get_platform() == "windows":
            # Windows系统添加所有驱动器
            drives = soui4.get_available_drives()
            for drive in drives:
                item = self.tree_dirs.add_root(drive)
                self.tree_dirs.set_item_image(item, "res/icons/drive.png")
                self.tree_dirs.expand(item, False)  # 不展开子节点
        else:
            # Linux/macOS添加根目录
            root = self.tree_dirs.add_root("/")
            self.tree_dirs.set_item_image(root, "res/icons/folder.png")
            self.tree_dirs.expand(root, False)
    
    def navigate_to(self, path):
        if not os.path.exists(path):
            return
            
        # 更新导航历史
        if self.nav_index < len(self.nav_history) - 1:
            self.nav_history = self.nav_history[:self.nav_index + 1]
        self.nav_history.append(path)
        self.nav_index = len(self.nav_history) - 1
        
        # 更新路径文本框
        self.txt_path.text = path
        
        # 加载目录内容
        self.load_directory(path)
        
        # 更新状态栏
        self.update_statusbar(path)
        
        # 更新导航按钮状态
        self.update_nav_buttons()
    
    def load_directory(self, path):
        try:
            # 获取目录内容
            items = os.listdir(path)
            
            # 清空列表
            self.list_files.clear()
            self.tile_files.clear()
            
            # 添加目录和文件
            for item in sorted(items):
                item_path = os.path.join(path, item)
                is_dir = os.path.isdir(item_path)
                
                # 获取文件信息
                icon = get_file_icon(item_path)
                size = format_file_size(item_path) if not is_dir else ""
                modified = get_file_modified_time(item_path)
                
                # 添加到列表视图
                list_item = self.list_files.add_item([item, size, modified])
                self.list_files.set_item_image(list_item, icon)
                
                # 添加到图标视图
                tile_item = self.tile_files.add_item(item)
                self.tile_files.set_item_image(tile_item, icon)
                self.tile_files.set_item_sub_text(tile_item, modified)
                
        except Exception as e:
            self.show_message_box("错误", f"无法加载目录: {str(e)}", soui4.MB_OK | soui4.MB_ICONERROR)
    
    def update_statusbar(self, path):
        try:
            # 获取文件计数
            items = os.listdir(path)
            file_count = 0
            dir_count = 0
            
            for item in items:
                if os.path.isdir(os.path.join(path, item)):
                    dir_count += 1
                else:
                    file_count += 1
            
            self.statusbar.set_text(f"文件夹: {dir_count}, 文件: {file_count}")
        except:
            self.statusbar.set_text("")
    
    def update_nav_buttons(self):
        # 更新后退按钮状态
        self.btn_back.enabled = self.nav_index > 0
        
        # 更新前进按钮状态
        self.btn_forward.enabled = self.nav_index < len(self.nav_history) - 1
    
    # 事件处理函数
    def on_dir_selected(self, event):
        # 获取选中的目录路径
        selected_item = self.tree_dirs.selected_item
        if selected_item:
            path = self.tree_dirs.get_item_data(selected_item)
            if path and os.path.isdir(path):
                self.navigate_to(path)
    
    def on_file_double_click(self, event):
        # 获取选中的文件名
        if event.sender.name == "list_files":
            selected_index = self.list_files.selected_index
            if selected_index != -1:
                filename = self.list_files.get_item_text(selected_index, 0)
        else:
            selected_index = self.tile_files.selected_index
            if selected_index != -1:
                filename = self.tile_files.get_item_text(selected_index)
        
        if filename:
            path = os.path.join(self.txt_path.text, filename)
            if os.path.isdir(path):
                self.navigate_to(path)
                # 在目录树中选中该目录
                self.tree_dirs.select_path(path)
            else:
                # 打开文件
                soui4.shell_execute(path)
    
    def on_back_click(self, event):
        if self.nav_index > 0:
            self.nav_index -= 1
            self.navigate_to(self.nav_history[self.nav_index])
    
    def on_forward_click(self, event):
        if self.nav_index < len(self.nav_history) - 1:
            self.nav_index += 1
            self.navigate_to(self.nav_history[self.nav_index])
    
    def on_up_click(self, event):
        parent_dir = os.path.dirname(self.txt_path.text)
        if parent_dir != self.txt_path.text:  # 防止根目录
            self.navigate_to(parent_dir)
            # 在目录树中选中父目录
            self.tree_dirs.select_path(parent_dir)
    
    def on_refresh_click(self, event):
        self.navigate_to(self.txt_path.text)
    
    def on_search_click(self, event):
        self.perform_search()
    
    def on_search_key_press(self, event):
        if event.key_code == soui4.VK_RETURN:
            self.perform_search()
    
    def perform_search(self):
        search_text = self.txt_search.text.lower()
        current_path = self.txt_path.text
        
        if not search_text:
            self.load_directory(current_path)
            return
            
        # 搜索当前目录中匹配的文件
        self.list_files.clear()
        self.tile_files.clear()
        
        for item in os.listdir(current_path):
            if search_text in item.lower():
                item_path = os.path.join(current_path, item)
                is_dir = os.path.isdir(item_path)
                
                icon = get_file_icon(item_path)
                size = format_file_size(item_path) if not is_dir else ""
                modified = get_file_modified_time(item_path)
                
                # 添加到列表视图
                list_item = self.list_files.add_item([item, size, modified])
                self.list_files.set_item_image(list_item, icon)
                
                # 添加到图标视图
                tile_item = self.tile_files.add_item(item)
                self.tile_files.set_item_image(tile_item, icon)
                self.tile_files.set_item_sub_text(tile_item, modified)
        
        self.statusbar.set_text(f"搜索结果: '{search_text}'")

if __name__ == "__main__":
    app = soui4.Application()
    
    # 设置中文字体
    app.set_default_font("simsun.ttc", 12)
    
    # 加载主题
    app.load_theme("res/theme/styles.xml")
    
    # 创建并显示主窗口
    window = FileManagerWindow()
    window.show()
    
    # 运行应用
    app.run()

运行效果

文件管理器截图

总结与展望

SOUI4Python为Python开发者提供了一个构建高性能桌面应用的强大框架。通过结合C++的性能优势和Python的开发效率,SOUI4Python打破了传统Python桌面应用性能不佳的瓶颈。

核心优势回顾

  • 性能卓越:基于C++内核,渲染效率高
  • 开发高效:Python API简洁易用,XML布局直观
  • 界面精美:丰富的控件库和主题系统
  • 跨平台:支持Windows、Linux、macOS
  • 轻量级:核心体积小,资源占用低

进阶学习资源

未来展望

SOUI4Python团队正在积极开发以下功能:

  • 移动平台支持(Android、iOS)
  • 更完善的Python API文档
  • 可视化设计工具集成
  • 更多第三方库集成(数据可视化、报表等)

无论你是需要开发企业级应用还是个人项目,SOUI4Python都能为你提供一个高效、灵活的开发解决方案。立即开始你的SOUI4Python之旅,构建属于你的高性能桌面应用吧!

【免费下载链接】soui4 soui是一套持续开发维护了14年的PC端APP开发框架,现已经支持windows, linux, macos三个PC平台,后续也可能增加移动端支持,敬请期待! 【免费下载链接】soui4 项目地址: https://gitcode.com/setoutsoft/soui4

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值