开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1475|回复: 49
收起左侧

[易源码分享] 易语言 + Python 混合编程:AUI 浮动布局 + 全面 WxPython 控件...

[复制链接]
结帖率:86% (44/51)
发表于 4 天前 | 显示全部楼层 |阅读模式   浙江省金华市
分享源码
界面截图:
是否带模块: 纯源码
备注说明: -

按下'F' 进入AI正文


正文:

大家好!

在之前的帖子里,我们探讨了易语言(EPL)和 Python 之间进行交互的基础。今天,我非常激动地与大家分享一个终极版的混合编程示例。这个项目不仅展示了如何将 Python强大的 wxPython GUI 库嵌入到易语言中,还实现了一个功能完整、界面现代的复杂应用程序。

这个项目最酷的地方在于:所有界面和交互逻辑都由 Python (wxPython) 实现,而核心的程序入口和事件决策权则保留在易语言中。 这意味着您可以利用 Python 社区庞大而成熟的生态库来打造华丽的界面,同时保留易语言快速开发和编写业务逻辑的优势。


核心特性一览

  1. 高级 AUI 框架: 使用 wx.lib.agw.aui (Advanced User Interface) 实现类似专业开发工具(如 VS)的可停靠、可浮动、可拖拽的窗口布局管理器。
  2. 全面的控件展示: 几乎涵盖了 wxPython 中所有常用控件,包括:
    • 基础控件: 按钮、文本框、单选/复选框、选择器等。
    • 列表类控件: 可编辑的 ListView、高性能的 DataViewListCtrl
    • 高级控件: 网页视图 WebView、富文本编辑器 RichTextCtrl、支持关闭和拖拽的 AuiNotebook 选项卡。
    • 表格与树: Grid 电子表格和 TreeListCtrl 树状列表。
    • 对话框: 各种标准对话框的调用演示。
  3. 动态布局与主题切换:
    • 可以随时恢复默认界面布局
    • 支持一键切换多种界面主题 (如:VS2005, Modern, Chrome, Firefox 等),让你的应用瞬间焕然一新。
  4. 健壮的双向通信:
    • 易语言 -> Python: 易语言负责初始化 Python 环境,加载模块,并调用指定的 Python 函数来创建和显示界面。
    • Python -> 易语言: Python 中的所有 UI 事件(如按钮点击、菜单选择、窗口关闭)都会被捕获,并通过一个带缓冲区的回调函数安全地传递给易语言。易语言可以根据事件内容决定如何响应,甚至可以“否决”某些操作(例如,阻止窗口关闭)。
  5. 清晰的职责分离:
    • 易语言端 (_启动子程序): 专注于环境设置、函数地址获取和资源清理。代码结构清晰,分为七个明确的步骤。
    • Python 端 (ui_library.py): 专注于界面构建。将UI启动流程分解为 init_app, show_main_frame, run_main_loop 三个独立函数,使调用逻辑更清晰、更稳定。

实现原理解析

这个项目的核心是利用 Python 官方提供的 C API,通过易语言的 DLL 调用来实现的。

  1. 初始化与加载:

    • 易语言首先通过 Py_SetPath 设置 Python 的搜索路径,确保能找到所有必要的模块。
    • Py_Initialize 启动 Python 解释器。
    • PyImport_ImportModule 动态导入我们的界面文件 ui_library.py
  2. 函数获取:

    • 通过 PyObject_GetAttrString 从模块中获取我们需要调用的所有 Python 函数的地址,例如 init_appshow_main_frame 等。
  3. 回调注册 (关键步骤):

    • 易语言通过 &子程序地址 获取 HandleEventFromPython 这个回调子程序的内存地址。
    • 使用 PyLong_FromVoidPtr 将这个地址转换为 Python 可以理解的整数对象。
    • 调用 Python 的 set_event_handler 函数,将这个地址传递过去。
    • Python 端使用 ctypes 将这个整数地址重新转换为一个可调用的 Windows 标准调用 (WINFUNCTYPE) 函数指针。从此,E_LANG_CALLBACK 就成了易语言子程序在 Python 中的“代理”。
  4. 事件处理流程:

    • 当用户在 wxPython 界面上点击一个按钮时,触发 Python 的事件处理函数。
    • 该函数调用我们封装好的 handle_event
    • handle_event 创建一个缓冲区,然后调用 E_LANG_CALLBACK,将事件名称(如 "button_click")和事件数据作为参数传递过去。
    • 控制权回到易语言的 HandleEventFromPython 子程序。
    • 易语言处理事件逻辑,并将需要返回给 Python 的结果字符串写入到 Python 提供的缓冲区内存中。
    • Python 从缓冲区读取易语言的响应,并继续执行。

代码片段展示

易语言端:启动与回调核心逻辑

' --- 步骤 5: 将易语言回调函数地址传递给Python ---
pCallbackAddr = &HandleEventFromPython
pArg = PyLong_FromVoidPtr (pCallbackAddr)
' 调用 Python 的 set_event_handler 函数,把我们的回调函数地址传过去
pResult = PyObject_CallFunctionObjArgs_2p (pSetHandlerFunc, pArg, 0)
Py_DecRef (pArg)
.如果 (pResult = 0)
    调试输出 (“回调注册失败!”)
    ' ... 清理并返回 ...
.如果结束
Py_DecRef (pResult)

' --- Python 回调实现 ---
.子程序 HandleEventFromPython, , , Python事件处理器
.参数 event_name, 整数型
.参数 event_data, 整数型
.参数 return_buffer, 整数型, , Python 提供的缓冲区地址
.参数 buffer_size, 整数型, , 缓冲区大小
.局部变量 e_event_name, 文本型
.局部变量 return_text, 文本型
.局部变量 return_bytes, 字节集

' 获取 Python GIL 锁,确保线程安全
gil_state = PyGILState_Ensure ()

e_event_name = 到文本 (指针到文本 (event_name))
调试输出 (“[易语言] 收到事件: '” + e_event_name + “'”)

' --- 在这里处理来自 Python 的所有事件 ---
.如果 (e_event_name = “window_close”)
    .如果 (信息框 (“Python窗口请求关闭,是否允许?”, 1) = 1)
        return_text = “0” ' 返回 "0" 表示允许关闭
    .否则
        return_text = “1” ' 返回 "1" 表示拒绝关闭
    .如果结束
.否则
    return_text = “易语言已收到事件: ” + e_event_name
.如果结束

' 将要返回的字符串,写入到 Python 提供的缓冲区
return_bytes = 到字节集 (return_text) + { 0 }
RtlMoveMemory (return_buffer, 取变量数据地址 (return_bytes), 取字节集长度 (return_bytes))

' 释放 GIL 锁
PyGILState_Release (gil_state)

Python 端:回调设置与事件触发

import ctypes

# 全局变量,用于保存易语言传递过来的回调函数指针
E_LANG_CALLBACK = None

def set_event_handler(callback_address: int):
    """由易语言调用,用于设置回调函数"""
    global E_LANG_CALLBACK
    if callback_address:
        # 定义回调函数的原型,必须与易语言子程序的参数类型和顺序完全一致
        callback_prototype = ctypes.WINFUNCTYPE(
            None,                       # 返回值 (无)
            ctypes.c_char_p,            # event_name (字符串指针)
            ctypes.py_object,           # event_data (任意Python对象)
            ctypes.c_char_p,            # return_buffer (缓冲区地址)
            ctypes.c_int                # buffer_size (缓冲区大小)
        )
        # 将整数地址转换为可调用的函数
        E_LANG_CALLBACK = callback_prototype(callback_address)
    else:
        E_LANG_CALLBACK = None

def handle_event(event_name: str, event_data):
    """在Python中触发一个事件,并通知易语言"""
    if E_LANG_CALLBACK:
        try:
            # 创建一个足够大的缓冲区来接收易语言的返回值
            buffer_size = 4096
            return_buffer = ctypes.create_string_buffer(buffer_size)
            # 将事件名编码为易语言默认的GBK格式
            encoded_name = event_name.encode('gbk')

            # 调用易语言的回调函数!
            E_LANG_CALLBACK(encoded_name, event_data, return_buffer, buffer_size)

            # 将易语言写入缓冲区的内容解码并返回
            return return_buffer.value.decode('gbk')
        except Exception as e:
            return str(e)
    return "E-lang callback not set."

# 在UI事件中调用 handle_event
class MainFrame(wx.Frame):
    def __init__(self):
        # ...
        self.Bind(wx.EVT_CLOSE, self.on_close)

    def on_close(self, event):
        # 当窗口关闭时,调用handle_event通知易语言
        result = handle_event("window_close", "")
        if result == "0":
            # 如果易语言返回 "0", 则销毁窗口
            self.mgr.UnInit()
            self.Destroy()
        else:
            # 否则,调用 event.Veto() 来阻止窗口关闭
            self.log_message("易语言端取消了窗口关闭")
            event.Veto()

如何使用?

  1. 确保你有一个可用的 Python 3.8 环境,并已安装 wxPython
  2. 将 Python 核心文件 (python38.dll, python38.zip, DLLs, Lib) 放在易语言程序生成的 .exe 所在的目录或其子目录中。
  3. ui_library.py 文件也放在 .exe 旁边。
  4. 编译并运行易语言程序。

希望这个终极版的示例能为大家打开一扇新的大门,探索易语言与其他强大语言结合的无限可能!欢迎大家下载源码研究,一起交流讨论!



演示_控制台.e (451.18 KB, 下载次数: 51, 售价: 5 枚 精币)

点评

倒反天罡了属于是   河北省保定市  发表于 4 天前
kat
UI方面可以尝试这个:http://www.soeasyui.com   台湾省*  发表于 4 天前

评分

参与人数 4好评 +3 精币 +5 收起 理由
kyo9766 + 1 感谢分享,很给力!~
fengyishen + 1 探索精神值得肯定
quary + 1 + 2 新技能已get√
szxiao + 1 + 2 感谢分享,很给力!~

查看全部评分


签到天数: 1 天

发表于 11 小时前 | 显示全部楼层   广东省东莞市
谢谢分享
回复 支持 反对

使用道具 举报

签到天数: 8 天

发表于 12 小时前 | 显示全部楼层   浙江省宁波市
感谢分享,支持开源!!!
回复 支持 反对

使用道具 举报

签到天数: 1 天

发表于 12 小时前 | 显示全部楼层   河北省保定市
https://bbs.125.la/thread-14861681-1-1.html易语言 + Python 混合编程:AUI 浮动布局 + 全面 WxPython 控
回复 支持 反对

使用道具 举报

签到天数: 1 天

发表于 12 小时前 | 显示全部楼层   河北省保定市
谢谢分享 谢谢分享 谢谢分享 谢谢分享 谢谢分享
回复 支持 反对

使用道具 举报

结帖率:96% (121/126)

签到天数: 7 天

发表于 14 小时前 | 显示全部楼层   山东省青岛市
感谢您对论坛的支持!
回复 支持 反对

使用道具 举报

结帖率:92% (67/73)

签到天数: 5 天

发表于 14 小时前 | 显示全部楼层   山东省青岛市
感谢发布原创作品,精易因你更精彩!6666666666666
回复 支持 反对

使用道具 举报

签到天数: 2 天

发表于 昨天 20:39 | 显示全部楼层   香港特别行政区*
为什么不直接用python?
回复 支持 反对

使用道具 举报

签到天数: 4 天

发表于 昨天 19:19 | 显示全部楼层   湖南省岳阳市
感谢分享,很给力!~
回复 支持 反对

使用道具 举报

结帖率:83% (25/30)

签到天数: 2 天

发表于 昨天 15:55 | 显示全部楼层   湖南省长沙市
有视频就更好了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表