使用tkinter制作tkinterUI编辑器
目录
- 使用tkinter制作tkinterUI编辑器
- 前言
- 一、关于控件创建的管理
- 二、编辑器第一版
- 三、当前目录结构
前言
这篇记录继续上一篇的控件创建,添加一个控件创建的管理类,之后添加编辑器的初版代码,让编辑器能够运行起来
一、关于控件创建的管理
先上代码,componentMgr.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from components import create_component_from_dict
from toolXmlParser import ToolXmlParser
class componentMgr:
def __init__(self, master):
self.master = master
self.xml_parser = ToolXmlParser()
def init_main_frame(self, master, component_info, first_child):
"""
初始化主界面
:param master: parent
:param component_info: 控件信息
:param first_child: 首个孩子
:return: None
"""
# 设置标题
master.title(component_info["title"])
# 设置大小与位置
width = component_info["width"]
height = component_info["height"]
pos_x = component_info["x"]
pos_y = component_info["y"]
master.geometry("%sx%s+%s+%s" % (width, height, pos_x, pos_y))
first_child.place(x=0, y=0, anchor=component_info["anchor"])
def create_component_by_info(self, master, component_info, is_init_main, on_create_success=None):
"""
创建控件by控件信息
:param master: parent
:param component_info: 控件信息
:param is_init_main: 是否是初始化主界面时调用的
:param on_create_success: 创建成功回调
:return: 控件
"""
gui_type = component_info.get("gui_type", "None")
if gui_type == "None":
return None
# 创建控件
component = create_component_from_dict(master, component_info)
# 初始化主界面
is_main = component_info.get("is_main", 0)
if is_main == "1" and is_init_main:
self.init_main_frame(master, component_info, component)
if on_create_success:
on_create_success(component, component_info, master)
# 创建children
for child in component_info.get("children", ()):
if component == None:
print("create_component error component=" + child["component_name"])
continue
master2 = component.get_child_master() if hasattr(component, "get_child_master") else component
self.create_component_by_info(master2, child, is_init_main, on_create_success)
return component
def load_from_xml(self, master, gui_path, is_init_main=False, on_create_success=None):
"""
从xml中读取并创建ui
:param master: 在这个控件创建
:param gui_path: 文件名称
:param is_init_main: 是否初始化主界面
:param on_create_success: 创建成功回调
:return: Dict
"""
components = self.xml_parser.load_xml_to_dict(gui_path)
for parent_name, component_info in components.items():
self.create_component_by_info(master, component_info, is_init_main, on_create_success)
return components
def saves(self, file_name, component_info):
"""
将ui存入xml文件
:param file_name: 文件名字(包括路径)
:param component_info: 控件信息
:return: None
"""
self.xml_parser.write_dict_to_xml(file_name, component_info, "root")
说明:
- init_main_frame进行主界面的处理,xml中is_main字段用来控制是否是主界面,主界面需要设置标题,坐标以及大小
- load_from_xml函数从xml中读取UI并且进行创建,这个函数如果是初始化的时候调用的话才会进行主界面设置,不是初始化的时候调用的话只会把UI创建到指定的父控件里面
- create_component_by_info这个函数递归的去创建所有控件,函数中的get_child_master还是为了我自己写的控件而加的特殊逻辑,以后会进行说明
- saves函数将控件信息存储到xml中
二、编辑器第一版
先上代码,tkinterEditor.py
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os
from tkinter import Tk
from componentMgr import componentMgr
class tkinterEditor(componentMgr):
def __init__(self, master, gui_path):
componentMgr.__init__(self, master)
self.load_from_xml(master, gui_path, True)
def main():
root = Tk()
root.resizable(0, 0)
path = os.path.join(os.getcwd(), "tkinterEditor.xml")
tkinterEditor(root, path)
root.mainloop()
if __name__ == "__main__":
main()
说明:
- 编辑器继承componentMgr类,初始化直接调用load_from_xml读取并创建UI
- 因为所有控件都是用place进行显示的,所以我不希望主界面可以调整大小,使用root.resizable(0, 0)进行限制
三、当前目录结构
说明:
- tkinterEditor.xml就是第一篇记录里面的demo.xml
- tkinterEditor.bat是我为了快速启动加的,不用管
- 有了这些文件之后运行tkinterEditor.py就能够运行第一版编辑器了,如下图: