I previously wrote about this in 2014 in the essay "TheWinform development framework of the parameter configuration management functional realization - based on the construction of theNET-based parameter configuration management interface, this essay is based on a similar effect, and introduces the use of the WxPython cross-platform development framework on theLabelBook
control to realize the effect of the configuration management interface.
1. Review of the characteristics of the parameter configuration management interface and the .
The Essay.Winform development framework of the parameter configuration management functional realization - based on the construction of theNET-based parameter configuration management function, as shown in the following interface.
It is implemented through a main form container, as shown below, the
The integration of individual panels is then provided to form a multi-panel configuration management interface.
2. Configuration management interface implementation based on the WxPython cross-platform development framework
In the WxPython Component Module, we can use the LabelBook control to implement the functionality of the configuration management interface.
LabelBook
Yes, wxPython.AGW
library is an enhanced tab control similar to the standard, but offers a richer appearance and functionality. Using it for the configuration management interface has the following advantages:
LabelBook
be Part of the module.
Let's look at a simple use case as shown in the code below.
import wx import as LB from import * class ConfigApp(): def __init__(self, parent=None): super().__init__(parent, title="configuration management", size=(800, 600)) # Creating a LabelBook Control panel = (self) labelbook = (panel, agwStyle=LB.INB_LEFT | INB_FIT_LABELTEXT) # Creating a Layout sizer = () (labelbook, 1, ) (sizer) # Adding a Configuration Page self.add_pages(labelbook) () () def add_pages(self, labelbook: ): # Creating a list of images self.image_list = (32, 32) self.image_list.Add( (wx.ART_NEW_DIR, wx.ART_OTHER, (32, 32)) ) self.image_list.Add( (wx.ART_ADD_BOOKMARK, wx.ART_OTHER, (32, 32)) ) self.image_list.Add( (wx.ART_CDROM, wx.ART_OTHER, (32, 32)) ) (self.image_list) # Example Page 1: Basic Settings page1 = (labelbook) (page1, label="Basic setup contents", pos=(20, 20)) (page1, "Basic settings", select=True, imageId=0) # Example Page 2: Network Settings page2 = (labelbook) (page2, label="Network Setup Content", pos=(20, 20)) (page2, "network setup", select=True, imageId=1) # Example Page 3: Advanced Settings page3 = (labelbook) (page3, label="Advanced Setting Contents", pos=(20, 20)) (page3, "Advanced Settings", select=True, imageId=2) if __name__ == "__main__": app = (False) frame = ConfigApp() () ()
The simple interface effect is shown below.
Once we have a main structure, we can design their styles and the content of the panels. We can set its associated color effects with a function.
def SetUserColours(self): """Setting LabelBook user-defined colors""" = (132, 164, 213) = (255, 255, 255) = (0, 0, 204) = (0, 0, 0) = (0, 0, 0) = (191, 216, 216) (INB_TAB_AREA_BACKGROUND_COLOUR, ) (INB_ACTIVE_TAB_COLOUR, ) (INB_TABS_BORDER_COLOUR, ) (INB_TEXT_COLOUR, ) (INB_ACTIVE_TEXT_COLOUR, ) (INB_HILITE_TAB_COLOUR, )
We let the creation of each panel be created independently of a function, as shown below.
# Add Page self.email_panel = self.create_email_panel() self.system_panel = self.create_system_panel() (self.email_panel, "Mailbox Configuration", True, imageId=0) (self.system_panel, "System settings", True, imageId=1)
Where the system setup is simple as shown below.
def create_system_panel(self, parent): panel = (parent) sizer = () # System parameter 1 param1_sizer = () param1_label = (panel, label="Parameter 1:") self.param1_input = (panel) param1_sizer.Add(param1_label, 0, wx.ALIGN_CENTER_VERTICAL | , 10) param1_sizer.Add(self.param1_input, 1, | , 10) # System Parameter 2 param2_sizer = () param2_label = (panel, label="Parameter 2:") self.param2_input = (panel) param2_sizer.Add(param2_label, 0, wx.ALIGN_CENTER_VERTICAL | , 10) param2_sizer.Add(self.param2_input, 1, | , 10) # Add to Panel (param1_sizer, 0, ) (param2_sizer, 0, ) (sizer) return panel
Through the above division, you can create a good corresponding interface control input and processing, the creation of the interface effect is shown below.
Since there may be many configuration pages, the handling of different business parameter settings may vary. We design a configuration interface base class:MyConfigDialog
Other business configuration classes can have default regular processing effects and implementations by inheriting from it, e.g. we have aFrmConfigSettings subclasses, the relationship diagram is shown below.
We just need to configure the interface base class againMyConfigDialogDefine the method to create the add page in the following, and leave it to the subclasses to implement it.
def create_papges(self, parent: ): """Create Page - Subclass Override"""
If we subclassFrmConfigSettings The method to add a page is implemented as follows.
def create_papges(self, parent: ): """Create Page - Subclass Override""" # Setting the image list image_list = (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.email_panel, "Mailbox Configuration", True, imageId=0) self.env_panel = self.create_env_panel() (self.env_panel, "Application Information", False, imageId=1) self.params_panel = self.create_params_panel() (self.params_panel, "System Parameter Configuration", False, imageId=2)
We add the interface to introduce only defined auxiliary class GridBagUtil to simplify the addition of processing, the following code is to create a mailbox configuration interface.
def create_email_panel(self, parent): """Creating a Mailbox Configuration Page""" panel = (parent, wx.ID_ANY) # Create a GridBagSizer grid_sizer = (2, 2) # Row and column spacing of 5 util = GridBagUtil(panel, grid_sizer, 4) = (panel) self.pop3_server = (panel) self.pop3_port = (panel) self.smtp_server = (panel) self.smtp_port = (panel) = (panel) = (panel, style=wx.TE_PASSWORD) self.user_ssl = (panel, label="Using SSL encryption") util.add_control("Mail Account", , is_expand=True, is_span=True, border=10) util.add_control("POP3 server:", self.pop3_server, is_expand=True, border=10) util.add_control("POP3 port number:", self.pop3_port, is_expand=True, border=10) util.add_control("SMTP server:", self.smtp_server, is_expand=True, border=10) util.add_control("SMTP port number:", self.smtp_port, is_expand=True, border=10) util.add_control( "Log in to your account:", , is_expand=True, is_span=True, border=10) util.add_control("Login Password:", , is_expand=True, is_span=True, border=10 ) util.add_control("Whether SSL encryption:", self.user_ssl, is_expand=True, is_span=True, border=10) # Make the control stretch with the window grid_sizer.AddGrowableCol(1) # Allow second column to stretch grid_sizer.AddGrowableCol(3) # Allow third row to stretch (grid_sizer) () return panel
The final interface effect is shown below.
Compare to the previous interface effect, the overall effect has its own flavor, right?
In the parameter configuration management interface for WxPython above, I designed several different parameter management, including the handling of ini files, the reading of .env configuration files, and the implementation of several different elements based on the system's parameter management interface in the backend database.
For example, for mailbox configuration information, we store it in an INI file, so it is sufficient to create a helper class for accessing the information in the INI file.
When displaying the data, the data is displayed by calling the auxiliary class, as follows is the read display function for the mail parameter.
def display_email_data(self): """Displaying Mailbox Configuration Data""" # print() filepath = + "/" + ini_setting = IniSettingUtil(filepath) (ini_setting.get(, "email", "")) self.pop3_server.SetValue(ini_setting.get(, "pop3_server", "")) self.pop3_port.SetValue(ini_setting.get_int(, "pop3_port", 0)) self.smtp_server.SetValue(ini_setting.get(, "smtp_server", "")) self.smtp_port.SetValue(ini_setting.get_int(, "smtp_port", 0)) (ini_setting.get(, "username", "")) (ini_setting.get(, "password", "")) self.user_ssl.SetValue(ini_setting.get_bool(, "ssl", False))
The program's parameter information is loaded into the system's configuration class through Pydantic_Setting, so it can be read directly.
def display_env_data(self): """Displaying application information data""" self.app_name.SetValue(settings.APP_NAME) self.app_version.SetValue(settings.APP_VERSION) self.app_desc.SetValue() 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)
A good way to understand how settings come about is to understand how Pydantic_Setting is handled, which is an instance of a parameter class that reads .env configuration parameters from the directory into the class to be handled as properties.
class Settings(BaseSettings): """System Information Configuration Class""" model_config = SettingsConfigDict( env_file=f"{BasePath}/.env", # Loading env files extra="ignore", # Load the env file and don't throw an exception if no properties are defined in Settings env_file_encoding="utf-8", env_prefix="", case_sensitive=False, ) # Application information (project name, version, description, etc.), read from .env file APP_NAME: str = "wxpython-Project" APP_VERSION: str = "1.0.0" DESCRIPTION: str = "This project is a GUI application based on wxPython." API_BASE_URL: str = "http://localhost:8000/api/" APP_UNIT: str = "Guangzhou Aqidi Software Technology Co." # Name of unit App_Author: str = "Ng Wah Chung (1974-), * actor" # Project Author App_Email: str = "" # Project Author Email
If .env does not have a value, then the default value here is used, and if it does, the parameter values in .env are loaded.
In addition, our system provides a common parameter management module, which can also be integrated for display.
This module is directly read remotely through the API to get the data to display.
async def display_params_data(self): """Display parameter configuration data""" company_name = await api_systemparam.get_by_name("company identification") address = await api_systemparam.get_by_name("Company Address") contact = await api_systemparam.get_by_name("Company Contacts") invoice = await api_systemparam.get_by_name("Invoicing Information") self.param_company.SetValue(company_name.content) self.param_address.SetValue() self.param_contact.SetValue() self.param_invoice.SetValue()
Above is the idea and process we realized in doing WxPython cross-platform configuration management interface, through the way of abstract base class, to reduce the commonly used code and logic, and provide a good extension.