我曾经在2014年在随笔《Winform开发框架之参数配置管理功能实现-基于SettingsProvider.net的构建》介绍过基于.NET开发的参数配置管理界面,本篇随笔基于类似的效果,介绍在WxPython跨平台开发框架上使用LabelBook 控件实现配置管理界面的效果。

1、参数配置管理界面的特点和 .NET 实现回顾

参数配置管理界面的特点主要体现在以下几个方面:

界面按照不同的功能模块或参数类别划分为多个部分,常见形式包括选项卡。

每个模块包含相关参数的设置控件,便于用户快速定位和修改特定设置。

界面逻辑清晰,便于维护。避免信息过于集中,提高可读性。

涉及不同类型的参数,例如布尔值(复选框)、枚举值(下拉菜单)、数值(文本框或滑块)、路径(文件选择器)等。可根据参数的用途选择适当的控件以提高用户体验。

提供保存和加载配置的功能,将配置保存到文件、数据库或云端,便于多次使用和分享。

一个好的参数配置管理界面会综合考虑这些特点,提供高效、直观且安全的操作体验,同时满足系统可扩展性的需求。

随笔《Winform开发框架之参数配置管理功能实现-基于SettingsProvider.net的构建》介绍过基于.NET开发的参数配置管理功能,如下界面所示。

它的实现是通过一个主窗体容器,如下所示,

然后再提供各个面板的整合形成一个多面板的配置管理界面。

2、基于WxPython跨平台开发框架的配置管理界面实现

在WxPython组件模块中,我们可以使用 wx.lib.agw.labelbook 的 LabelBook 控件实现配置管理界面的功能。

LabelBook 是 wxPython AGW 库中的一个增强选项卡控件,类似于标准的 wx.Notebook,但提供了更丰富的外观和功能。使用它来实现配置管理界面有以下优势:

LabelBook 是 wx.lib.agw.labelbook 模块的一部分。

我们来看看一个简单的使用案例,如下代码所示。

import wx
import wx.lib.agw.labelbook as LB
from wx.lib.agw.fmresources import * class ConfigApp(wx.Frame):
def __init__(self, parent=None):
super().__init__(parent, title="配置管理", size=(800, 600)) # 创建 LabelBook 控件
panel = wx.Panel(self)
labelbook = LB.LabelBook(panel, agwStyle=LB.INB_LEFT | INB_FIT_LABELTEXT) # 创建布局
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(labelbook, 1, wx.EXPAND)
panel.SetSizer(sizer) # 添加配置页面
self.add_pages(labelbook)
self.Layout()
self.SendSizeEvent() def add_pages(self, labelbook: LB.LabelBook): # 创建图像列表
self.image_list = wx.ImageList(32, 32)
self.image_list.Add(
wx.ArtProvider.GetBitmap(wx.ART_NEW_DIR, wx.ART_OTHER, (32, 32))
)
self.image_list.Add(
wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_OTHER, (32, 32))
)
self.image_list.Add(
wx.ArtProvider.GetBitmap(wx.ART_CDROM, wx.ART_OTHER, (32, 32))
)
labelbook.AssignImageList(self.image_list) # 示例页面 1: 基础设置
page1 = wx.Panel(labelbook)
wx.StaticText(page1, label="基础设置内容", pos=(20, 20))
labelbook.AddPage(page1, "基础设置", select=True, imageId=0) # 示例页面 2: 网络设置
page2 = wx.Panel(labelbook)
wx.StaticText(page2, label="网络设置内容", pos=(20, 20))
labelbook.AddPage(page2, "网络设置", select=True, imageId=1) # 示例页面 3: 高级设置
page3 = wx.Panel(labelbook)
wx.StaticText(page3, label="高级设置内容", pos=(20, 20))
labelbook.AddPage(page3, "高级设置", select=True, imageId=2) if __name__ == "__main__":
app = wx.App(False)
frame = ConfigApp()
frame.Show()
app.MainLoop()

简单的界面效果如下所示。

我们有一个主要的结构后,就可以设计它们的样式和面板的内容了。我们可以通过一个函数来设置它的相关颜色效果。

    def SetUserColours(self):
"""设置LabelBook用户自定义颜色""" self.background = wx.Colour(132, 164, 213)
self.activetab = wx.Colour(255, 255, 255)
self.tabsborder = wx.Colour(0, 0, 204)
self.textcolour = wx.Colour(0, 0, 0)
self.activetextcolour = wx.Colour(0, 0, 0)
self.hilite = wx.Colour(191, 216, 216) self.book.SetColour(INB_TAB_AREA_BACKGROUND_COLOUR, self.background)
self.book.SetColour(INB_ACTIVE_TAB_COLOUR, self.activetab)
self.book.SetColour(INB_TABS_BORDER_COLOUR, self.tabsborder)
self.book.SetColour(INB_TEXT_COLOUR, self.textcolour)
self.book.SetColour(INB_ACTIVE_TEXT_COLOUR, self.activetextcolour)
self.book.SetColour(INB_HILITE_TAB_COLOUR, self.hilite)

我们让每个面板的创建独立一个函数来创建,如下所示。

        # 添加页面
self.email_panel = self.create_email_panel(self.book)
self.system_panel = self.create_system_panel(self.book) self.book.AddPage(self.email_panel, "邮箱配置", True, imageId=0)
self.book.AddPage(self.system_panel, "系统设置", True, imageId=1)

其中系统设置简单如下所示。

    def create_system_panel(self, parent):
panel = wx.Panel(parent)
sizer = wx.BoxSizer(wx.VERTICAL) # 系统参数1
param1_sizer = wx.BoxSizer(wx.HORIZONTAL)
param1_label = wx.StaticText(panel, label="参数1:")
self.param1_input = wx.TextCtrl(panel)
param1_sizer.Add(param1_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
param1_sizer.Add(self.param1_input, 1, wx.EXPAND | wx.ALL, 10) # 系统参数2
param2_sizer = wx.BoxSizer(wx.HORIZONTAL)
param2_label = wx.StaticText(panel, label="参数2:")
self.param2_input = wx.TextCtrl(panel)
param2_sizer.Add(param2_label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 10)
param2_sizer.Add(self.param2_input, 1, wx.EXPAND | wx.ALL, 10) # 添加到面板
sizer.Add(param1_sizer, 0, wx.EXPAND)
sizer.Add(param2_sizer, 0, wx.EXPAND) panel.SetSizer(sizer)
return panel

通过上面的各司其职,就可以很好的创建对应的界面控件输入及处理了,创建的界面效果如下所示。

由于配置页面可能有很多个,不同的业务参数设置处理可能也有所不同。我们设计一个配置界面基类:MyConfigDialog

其他业务配置类,继承它即可具有默认的常规处理效果和实现,如我们有一个 FrmConfigSettings 的子类,关系图如下所示。

我们只需要再配置界面基类MyConfigDialog中定义创建添加页面的方法,留给子类实现即可,如下所示。

    def create_papges(self, parent: LB.LabelBook):
"""创建页面 - 子类重写"""

如我们在子类FrmConfigSettings 实现了添加页面的方法,如下所示。

    def create_papges(self, parent: LB.LabelBook):
"""创建页面 - 子类重写"""
# 设置图像列表
image_list = wx.ImageList(32, 32)
image_list.Add(get_bitmap("email", 32))
image_list.Add(get_bitmap("computer_key", 32)) # ART_INFORMATION
image_list.Add(get_bitmap("book", 32))
self.set_image_list(image_list) self.email_panel = self.create_email_panel(self.book)
self.book.AddPage(self.email_panel, "邮箱配置", True, imageId=0) self.env_panel = self.create_env_panel(self.book)
self.book.AddPage(self.env_panel, "应用程序信息", False, imageId=1) self.params_panel = self.create_params_panel(self.book)
self.book.AddPage(self.params_panel, "系统参数配置", False, imageId=2)

我们添加界面引入只定义的辅助类GridBagUtil 来简化添加的处理,如下代码是创建一个邮箱配置的界面。

    def create_email_panel(self, parent):
"""创建邮箱配置页面"""
panel = wx.Panel(parent, wx.ID_ANY)
# 创建一个 GridBagSizer
grid_sizer = wx.GridBagSizer(2, 2) # 行间距和列间距为 5
util = GridBagUtil(panel, grid_sizer, 4) self.email = ctrl.MyTextCtrl(panel)
self.pop3_server = ctrl.MyTextCtrl(panel)
self.pop3_port = ctrl.MyTextCtrl(panel)
self.smtp_server = ctrl.MyTextCtrl(panel)
self.smtp_port = ctrl.MyTextCtrl(panel)
self.username = ctrl.MyTextCtrl(panel)
self.password = ctrl.MyTextCtrl(panel, style=wx.TE_PASSWORD)
self.user_ssl = ctrl.MyCheckBox(panel, label="使用SSL加密") util.add_control("邮件账号", self.email, is_expand=True, is_span=True, border=10)
util.add_control("POP3服务器:", self.pop3_server, is_expand=True, border=10)
util.add_control("POP3端口号:", self.pop3_port, is_expand=True, border=10)
util.add_control("SMTP服务器:", self.smtp_server, is_expand=True, border=10)
util.add_control("SMTP端口号:", self.smtp_port, is_expand=True, border=10)
util.add_control( "登录账号:", self.username, is_expand=True, is_span=True, border=10)
util.add_control("登录密码:", self.password, is_expand=True, is_span=True, border=10 )
util.add_control("是否SSL加密:", self.user_ssl, is_expand=True, is_span=True, border=10) # 让控件跟随窗口拉伸
grid_sizer.AddGrowableCol(1) # 允许第二列拉伸
grid_sizer.AddGrowableCol(3) # 允许第三行拉伸
panel.SetSizer(grid_sizer)
panel.Layout()
return panel

最终界面效果如下所示。

对比一下之前的界面效果,整体效果各有千秋吧。

上面的WxPython的参数配置管理界面中,我设计了几个不同的参数管理,包括对ini文件的处理,.env配置文件的读取,以及基于系统在后台数据库的参数管理界面实现多个不同内容的管理。

如对于邮箱的相关配置信息,我们存储在INI文件中,因此创建一个INI文件存取信息的辅助类来处理即可。

显示数据的时候,通过调用辅助类来实现数据的显示,如下是邮件参数的读取显示函数。

    def display_email_data(self):
"""显示邮箱配置数据"""
# print(settings.AppDir)
filepath = settings.AppDir + "/" + self.filepath
ini_setting = IniSettingUtil(filepath) self.email.SetValue(ini_setting.get(self.section, "email", ""))
self.pop3_server.SetValue(ini_setting.get(self.section, "pop3_server", ""))
self.pop3_port.SetValue(ini_setting.get_int(self.section, "pop3_port", 0))
self.smtp_server.SetValue(ini_setting.get(self.section, "smtp_server", ""))
self.smtp_port.SetValue(ini_setting.get_int(self.section, "smtp_port", 0))
self.username.SetValue(ini_setting.get(self.section, "username", ""))
self.password.SetValue(ini_setting.get(self.section, "password", ""))
self.user_ssl.SetValue(ini_setting.get_bool(self.section, "ssl", False))

而程序的相关参数信息,我们通过Pydantic_Setting的进行加载到系统的配置类中的,那么直接读取即可。

    def display_env_data(self):
"""显示应用程序信息数据""" self.app_name.SetValue(settings.APP_NAME)
self.app_version.SetValue(settings.APP_VERSION)
self.app_desc.SetValue(settings.DESCRIPTION)
self.app_baseapi.SetValue(settings.API_BASE_URL)
self.app_unit.SetValue(settings.APP_UNIT)
self.app_author.SetValue(settings.App_Author)
self.app_email.SetValue(settings.App_Email)

关于settings是如何来的,可以了解一下Pydantic_Setting的处理方式,它是一个参数类的实例,可以读取目录下的.env配置参数到类里面作为属性处理。

class Settings(BaseSettings):
"""系统信息配置类""" model_config = SettingsConfigDict(
env_file=f"{BasePath}/.env", # 加载env文件
extra="ignore", # 加载env文件,如果没有在Settings中定义属性,也不抛出异常
env_file_encoding="utf-8",
env_prefix="",
case_sensitive=False,
) # 应用程序信息(项目名称、版本、描述等),从.env文件中读取
APP_NAME: str = "wxpython-Project"
APP_VERSION: str = "1.0.0"
DESCRIPTION: str = "本项目是基于 wxPython 开发的 GUI 应用。"
API_BASE_URL: str = "http://localhost:8000/api/"
APP_UNIT: str = "广州爱奇迪软件科技有限公司" # 单位名称
App_Author: str = "伍华聪" # 项目作者
App_Email: str = "" # 项目作者邮箱

如果.env没有值,那么就使用这里面的默认值,如有,则加载.env中的参数值。

另外,我们系统提供了一个常用的参数管理模块,也可以整合在其中进行显示。

这个模块直接是通过API进行远程读取获取数据显示的。

    async def display_params_data(self):
"""显示参数配置数据"""
company_name = await api_systemparam.get_by_name("公司名称")
address = await api_systemparam.get_by_name("公司地址")
contact = await api_systemparam.get_by_name("公司联系人")
invoice = await api_systemparam.get_by_name("开票信息") self.param_company.SetValue(company_name.content)
self.param_address.SetValue(address.content)
self.param_contact.SetValue(contact.content)
self.param_invoice.SetValue(invoice.content)

以上就是我们在做WxPython跨平台的配置管理界面中,实现的思路和处理过程,通过抽象基类的方式,减少常用的代码和逻辑,并提供很好的扩展。

WxPython跨平台开发框架之参数配置管理界面的设计和实现的更多相关文章

  1. Production环境中iptables常用参数配置

    production环境中iptables常用参数配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我相信在实际生产环境中有很多运维的兄弟跟我一样,很少用到iptables的这个 ...

  2. Winform开发框架之参数配置管理功能实现-基于SettingsProvider.net的构建

    在较早时期,我写过一篇文章<结合Control.FirefoxDialog控件,构造优秀的参数配置管理模块>,介绍过在我的Winform框架基础上集成的参数配置模块功能,但是参数模块的配置 ...

  3. [ionic开源项目教程] - 手把手教你使用移动跨平台开发框架Ionic开发一个新闻阅读APP

    前言 这是一个系列文章,从环境搭建开始讲解,包括网络数据请求,将持续更新到项目完结.实战开发中遇到的各种问题的解决方案,也都将毫无保留的分享给大家. 关注订阅号:TongeBlog ,查看移动端跨平台 ...

  4. 移动跨平台开发框架Ionic开发一个新闻阅读APP

    移动跨平台开发框架Ionic开发一个新闻阅读APP 前言 这是一个系列文章,从环境搭建开始讲解,包括网络数据请求,将持续更新到项目完结.实战开发中遇到的各种问题的解决方案,也都将毫无保留的分享给大家. ...

  5. HttpClient 4.3连接池参数配置及源码解读

    目前所在公司使用HttpClient 4.3.3版本发送Rest请求,调用接口.最近出现了调用查询接口服务慢的生产问题,在排查整个调用链可能存在的问题时(从客户端发起Http请求->ESB-&g ...

  6. echarts画饼环状饼图相关参数配置

    今天做页面的时候用到了环状饼图,大家都知道echarts的API文档看起来实在费劲,折腾了半天才画出来我想要的饼图,把我用到的参数配置分享给大家,希望能帮到和我一样的对echarts不是那么熟悉的童鞋 ...

  7. 性能测试 Apache参数配置与性能调优

    Apache性能调优 by:授客 QQ:1033553122 环境: Apache 2.4 1.选择合适的MPM(Multi -Processing Modules, 多处理模块) Unix/Linu ...

  8. golang学习笔记8 beego参数配置 打包linux命令

    golang学习笔记8 beego参数配置 打包linux命令 参数配置 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/docs/mvc/contro ...

  9. qt configure参数配置介绍

    ======================================全文是按照./configure -help来翻译的==================================== ...

  10. logback 常用参数配置详解

    logback 常用配置详解(二) <appender> <appender>: <appender>是<configuration>的子节点,是负责写 ...

随机推荐

  1. SpringMVC —— RESTful入门

    RESTful入门案例   1.设定http请求动作(动词) @RequestMapping(value = "/users",method = RequestMethod.POS ...

  2. QT疑难杂症之如何使用自定义模型实现文件系统模型?类似QFileSystemModel,却比QFileSystemModel更好用

    简介 本文讨论了QT文件系统模型QFileSystemModel的不足之处,并且讨论了改进目标,如何实现自定义文件系统模型,以及进一步改进的空间. 目录 QFileSystemModel的不足之处 改 ...

  3. [namespace hdk] 64位 bitset

    功能 已重载运算符 [](int) (右值,修改请使用 set() 方法) ~() +(bitset) +(unsigned long long) +=(bitset) +=(unsigned lon ...

  4. Windows11忘记开机密码重置

    在锁屏页面按着shift键重启,找到命令行输入一下两行代码 copy c:\windows\system\system32\utilman.exe c:\windows\system32\utilma ...

  5. Linux_权限理解(详细PLUS)

    1.用户 Linux下有两种用户:超级用户(root)和普通用户: 超级用户:可以再linux系统下做任何事情,不受限制 普通用户:在linux下做有限的事情 超级用户的命令提示符是"#&q ...

  6. 使用ValueConverters扩展实现枚举控制页面的显示

    1.ValueConverters 本库包含了IValueConverter接口的的最常用的实现,ValueConverters用于从视图到视图模型的值得转换,某些情况下,可用进行反向转换.里面有一些 ...

  7. 【VMware VCF】使用 SFTP 服务器备份 VCF 核心组件的配置文件。

    可以定期对 VMware Cloud Foundation 环境中的相关核心组件(如 SDDC Manager.NSX Manager 以及 vCenter Server 等)创建配置备份,以防止当意 ...

  8. Linux 循环设备 loop疑惑

    什么是loop设备? loop设备是一种伪设备,是使用文件来模拟块设备的一种技术,文件模拟成块设备后, 就像一个磁盘或光盘一样使用.在使用之前,一个 loop 设备必须要和一个文件进行连接.这种结合方 ...

  9. dotnet实现多态的三种方法

    虚方法 virual 抽象方法 abstract 不能 new  不带方法体: 接口 Interface

  10. 2-3 C++复合类型

    目录 2.3.1 引用(References) 2.3.2 指针(Pointers) 关于指针 指针操作 其它事项 空指针的三种表示 void* 指针 易混淆的符号 指针的值(地址)的四种状态 对比与 ...