PoC convert wxPython top-level widgets to wxGlade design files
This proof of concept converts hand-crafted wxPython widgets e.g. dialogs or panels into XML based wxGlade design files.
This document as well as the source code uses three different naming
convention for the same object, depending on the context used:
* node - for any details returned by / related to the
* control - refers to the intermediate representation
* widget - refers to wxWidgets
The parsing of the source code would be the most difficult task. Fortunately
ast module provides all necessary functionality to parse
Python files. The parser returns all the information required in the further
course of the program.
The program uses a subclass of
ast.NodeVisitor to walk the Python
statements and extract the useful details. The
ast parser returns a node
object with all details for each Python statement.
DesignAnalyzer implements the logic. It only uses the node
types for class definitions (
visit_Assign()) and expressions (
Node information returned by the
ast parser is stored as an intermediate
representation in the two dictionaries
controls_wo_parent is a temporary storage for controls not assigned to any
sizer controls. It should be empty when everything has been processed
controls_all provides fast and uniform access to all controls.
If the parser finds a function call of the form
then it appends the control to sizers children list (
removes the control from the
DesignAnalyzer.controls_wo_parent at the same
<Top-Level-Widget>.SetSizer(<Top-Level-Sizer>) the last sizer
without parent object is assigned to the toplevel element
After that, all elements below the top-level element should be processed and
controls_wo_parent should be empty. If not, the remaining widget is not in
use or the source code is too complex for parsing.
The last step completes the tree with the intermediate representation. It can now be transferred to any representation.
In this PoC the program transforms the tree into an XML-based design file for
wxGlade. The class
XMLFormatterWXGlade implements this straight forward
task and writes, starting with the top-level control, all children
recursively into a XML file.
The program does not have consistency checks.
Feedback is very welcome.
Room for improvement
- add XRC support
- add support for class variables e.g. to use for styles
- one class per file
- only one top-level widget (wx.Dialog/wx.Frame/wx.Panel) per class
- variables will be ignored - inline it
Your favourite IDE helps to prepare the Python source code.
Supported and tested Python versions
- Python 2.7, tested with 2.7.18
There are no additional requirements. All you need is Python.
Example: Convert UIReport dialog from example.py
The source file example.py
$ head -n 20 example.py # -*- coding: LATIN-1 -*- import wx class UIReport(wx.Dialog): def __init__(self, *args, **kwds): wx.Dialog.__init__(self, *args, style=wx.DEFAULT_DIALOG_STYLE | wx.MAXIMIZE_BOX | wx.MINIMIZE_BOX | wx.RESIZE_BORDER, **kwds) self.SetSize((600, 300)) self.SetTitle("Bericht ansehen") self.SetFocus() root_sizer = wx.BoxSizer(wx.VERTICAL) text_ctrl = wx.TextCtrl(self, wx.ID_ANY, "") root_sizer.Add(text_ctrl, 1, wx.ALL | wx.EXPAND, 5) static_line = wx.StaticLine(self, wx.ID_ANY)
$ ./wxpy2wxg.py example.py wxpy2wxg.py version 2020-05-21; Carsten Grohmann (c) 2020; Licence: MIT Starting conversion with reading Python source from example.py. WARNING:root:Ignore valid but probably useless assignment at line 17 The conversion is done. The design is written into example.wxg.
Show the design example.wxg
$ head example.wxg <?xml version="1.0" encoding="UTF-8"?> <!-- generated by wxpy2wxg.py version 2020-05-21 --> <application> <object class="UIReport" name="UIReport" base="EditDialog"> <size>600, 300</size> <focused>1</focused> <title>Bericht ansehen</title> <style>wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|wxMINIMIZE_BOX|wxRESIZE_BORDER</style> <object class="wxBoxSizer" name="root_sizer" base="EditBoxSizer"> <orient>wxVERTICAL</orient>
Open the new generated design with wxGlade
$ wxglade example.wxg
- Add a simple test
- Rename variables to better understand the context
- Extend documentation
- Initial version
Project page and feedback
The project page is at https://www.carstengrohmann.de/wxpython2wxglade.html.
The source code is at https://sr.ht/~carstengrohmann/wxPython2wxGlade.
Comments, suggestions and patches are welcome and appreciated. Please email me.
This software is covered by the MIT License.
Copyright (c) 2020-2021 Carsten Grohmann email@example.com
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.