├── GUI2Py.aardio ├── GUI2Py.tar.lzma ├── LICENSE ├── Measurement ├── OptMeasure.py ├── __pycache__ │ ├── demo1.cpython-38.pyc │ └── demo2.cpython-38.pyc ├── demo1.py └── demo2.py ├── README.md ├── Test ├── main.aardio └── test.py └── main.aardio /GUI2Py.aardio: -------------------------------------------------------------------------------- 1 | //解析aardio界面生成Python Tkinter 2 | import color 3 | import string 4 | import math 5 | import ide 6 | 7 | namespace GUI2Py 8 | 9 | class GUI2Tk { 10 | ctor( winform ){ 11 | this = winform; 12 | this.pycode = ""; 13 | this.translateNamelist = {}; 14 | }; 15 | 16 | write = function(code, space=0, end_='\r\n'){ 17 | if space>0 { 18 | for i=1;space { 19 | this.pycode += ' '; 20 | } 21 | } 22 | this.pycode += code++end_; 23 | }; 24 | 25 | 26 | //转换为主界面 27 | transfer2root = function(){ 28 | var window_width = this.width; 29 | var window_height = this.height; 30 | var window_text = this.text; 31 | this.pycode = /*** 32 | import tkinter as tk 33 | import tkinter.ttk as ttk 34 | import tkinter.font as tkFont 35 | 36 | root = tk.Tk() 37 | 38 | ### 界面设计部分 ### 39 | 40 | 41 | ***/; 42 | owner.write(..string.format('root.geometry("%ix%i")', window_width, window_height)); 43 | owner.write(..string.format('root.title("%s")', window_text)); 44 | var ctrlNameList = { 45 | 'button' = 0; 46 | 'static' = 0; 47 | 'edit' = 0; 48 | 'radio' = 0; 49 | 'check' = 0; 50 | 'pic' = 0; 51 | 'listbox' = 0; 52 | 'combobox' = 0; 53 | 'progress' = 0; 54 | 'trackbar' = 0; 55 | 'listview' = 0; 56 | 'treeview' = 0; 57 | 'canvas' = 0; 58 | 'groupbox' = 0; 59 | 'frame' = 0; 60 | 'tab' = 0; 61 | 62 | }; 63 | for ( hwnd,ctrl in this.eachControlEx() ){ 64 | winctrol = this.getCtrl(hwnd); 65 | var x = winctrol.left; 66 | var y = winctrol.top; 67 | var width = winctrol.width; 68 | var height = winctrol.height; 69 | var text = winctrol.text; 70 | var hide = ctrl.hide; 71 | var disabled = ctrl.disabled; 72 | var readonly = ctrl.readonly; 73 | var bgcolor = ctrl.bgcolor; 74 | var frcolor = ctrl.color; 75 | var font = ctrl.font; 76 | var align = ctrl.align; 77 | var justify; 78 | if !align { 79 | justify = 'justify="left"'; 80 | } elseif align == "center" { 81 | justify = 'justify="center"'; 82 | } else { 83 | justify = 'justify="right"'; 84 | }; 85 | //按钮 86 | if winctrol.cls == "button" { 87 | var id = ctrlNameList.button + 1; 88 | ctrlNameList.button = id; 89 | this.translateNamelist[ctrl.z] = "button"++id; 90 | owner.write(..string.format('button%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 91 | owner.write(..string.format('button%i = ttk.Button(button%i_frame, text="%s")', id, id, text)); 92 | owner.write(..string.format('button%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 93 | if hide { owner.write(..string.format('button%i.place_forget()', id)); }; 94 | if disabled { owner.write(..string.format('button%i.configure(state="disabled")', id)); }; 95 | 96 | owner.write(..string.format('button%i_frame.place(x=%i, y=%i)', id, x, y)); 97 | }; 98 | //标签 99 | if winctrol.cls == "static" { 100 | var id = ctrlNameList.static + 1; 101 | ctrlNameList.static = id; 102 | this.translateNamelist[ctrl.z] = "label"++id; 103 | owner.write(..string.format('label%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 104 | owner.write(..string.format('label%i = ttk.Label(label%i_frame, text="%s", %s)', id, id, text, justify)); 105 | owner.write(..string.format('label%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 106 | if hide { owner.write(..string.format('label%i.place_forget()')); }; 107 | if disabled { owner.write(..string.format('label%i.configure(state="disabled")')); }; 108 | if font { 109 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 110 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 111 | var family = 'family="'+font.name+'"'; 112 | var underline = font.underline ? 'underline=True' : 'underline=False'; 113 | var size = 'size='++..math.round(font.h*(-3)/4); 114 | owner.write(..string.format('label%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", "))); 115 | owner.write(..string.format('label%i.configure(font=label%i_font)', id, id)); 116 | }; 117 | if bgcolor { 118 | bgcolorStr = ..color.stringify(bgcolor,false); 119 | owner.write(..string.format('label%i.config(background="%s")', id, bgcolorStr)); 120 | }; 121 | if frcolor { 122 | frcolorStr = ..color.stringify(frcolor,false); 123 | owner.write(..string.format('label%i.config(foreground="%s")', id, frcolorStr)); 124 | }; 125 | owner.write(..string.format('label%i_frame.place(x=%i, y=%i)', id, x, y)); 126 | }; 127 | //文本框 128 | if winctrol.cls == "edit" { 129 | var id = ctrlNameList.edit + 1; 130 | ctrlNameList.edit = id; 131 | this.translateNamelist[ctrl.z] = "edit"++id; 132 | var vscroll = ctrl.vscroll; 133 | var hscroll = ctrl.hscroll; 134 | owner.write(..string.format('editVar%i = tk.StringVar(value="%s")', id, text)); 135 | owner.write(..string.format('edit%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 136 | if winctrol.multiline == 1 { 137 | owner.write(..string.format('edit%i = tk.Text(edit%i_frame)', id, id)); 138 | owner.write(..string.format('edit%i.insert("end", "%s")', id, text)); 139 | } else { 140 | owner.write(..string.format('edit%i = ttk.Entry(edit%i_frame, textvariable=editVar%i, %s)', id, id, id, justify)); 141 | } 142 | owner.write(..string.format('edit%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 143 | if ctrl.password { owner.write(..string.format('edit%i.configure(show="*")', id)); }; 144 | if(readonly or disabled) { owner.write(..string.format('edit%i.configure(state="disabled")', id)); }; 145 | if hide { owner.write(..string.format('edit%i.place_forget()', id)); }; 146 | if vscroll { 147 | owner.write(..string.format('edit%i_vscroll = tk.Scrollbar(edit%i, orient="vertical", command=edit%i.yview)', id, id, id)); 148 | owner.write(..string.format('edit%i.configure(yscrollcommand=edit%i_vscroll.set)', id, id)); 149 | owner.write(..string.format('edit%i_vscroll.pack(side="right", fill="y")', id)); 150 | }; 151 | if hscroll { 152 | owner.write(..string.format('edit%i_hscroll = tk.Scrollbar(edit%i, orient="horizontal", command=edit%i.xview)',id, id, id)); 153 | owner.write(..string.format('edit%i.configure(xscrollcommand=edit%i_hscroll.set)', id, id)); 154 | owner.write(..string.format('edit%i_hscroll.pack(side="bottom", fill="x")', id)); 155 | }; 156 | if font { 157 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 158 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 159 | var family = 'family="'+font.name+'"'; 160 | var underline = font.underline ? 'underline=True' : 'underline=False'; 161 | var size = 'size='++..math.round(font.h*(-3)/4); 162 | owner.write(..string.format('edit%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", "))); 163 | owner.write(..string.format('edit%i.configure(font=edit%i_font)', id, id)); 164 | }; 165 | if bgcolor { 166 | bgcolorStr = ..color.stringify(bgcolor,false); 167 | owner.write(..string.format('edit%i.config(background="%s")', id, bgcolorStr)); 168 | }; 169 | if frcolor { 170 | frcolorStr = ..color.stringify(frcolor,false); 171 | owner.write(..string.format('edit%i.config(foreground="%s")', id, frcolorStr)); 172 | }; 173 | owner.write(..string.format('edit%i_frame.place(x=%i, y=%i)', id, x, y)); 174 | }; 175 | //单选 176 | if winctrol.cls == "radiobutton" { 177 | var id = ctrlNameList.radio + 1; 178 | ctrlNameList.radio = id; 179 | this.translateNamelist[ctrl.z] = "radio"++id; 180 | owner.write(..string.format('radio%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 181 | owner.write(..string.format('radio%i = ttk.Radiobutton(radio%i_frame, text="%s", value=%i)', id, id, text, id)); 182 | owner.write(..string.format('radio%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 183 | if hide { owner.write(..string.format('radio%i.place_forget()', id)); }; 184 | if disabled { owner.write(..string.format('radio%i.configure(state="disabled")', id)); }; 185 | 186 | owner.write(..string.format('radio%i_frame.place(x=%i, y=%i)', id, x, y)); 187 | }; 188 | //复选 189 | if winctrol.cls == "checkbox" { 190 | var id = ctrlNameList.check + 1; 191 | ctrlNameList.check = id; 192 | this.translateNamelist[ctrl.z] = "check"++id; 193 | owner.write(..string.format('check%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 194 | owner.write(..string.format('check%i = ttk.Checkbutton(check%i_frame, text="%s")', id, id, text)); 195 | owner.write(..string.format('check%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 196 | if hide { owner.write(..string.format('check%i.place_forget()', id)); }; 197 | if disabled { owner.write(..string.format('check%i.configure(state="disabled")', id)); }; 198 | owner.write(..string.format('check%i_frame.place(x=%i, y=%i)', id, x, y)); 199 | }; 200 | //图片框 201 | if winctrol.cls == "picturebox" { 202 | var id = ctrlNameList.pic + 1; 203 | ctrlNameList.pic = id; 204 | this.translateNamelist[ctrl.z] = "pic"++id; 205 | owner.write(..string.format('pic%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 206 | var picpath = winctrol.background; 207 | if picpath { 208 | owner.write(..string.format('img%i = tk.PhotoImage(file=r"%s")', id, picpath)); 209 | owner.write(..string.format('pic%i = ttk.Label(pic%i_frame, image=img%i, %s)', id, id, id, justify)); 210 | } else { 211 | owner.write(..string.format('pic%i = ttk.Label(pic%i_frame, %s)', id, id, justify)); 212 | } 213 | owner.write(..string.format('pic%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 214 | if hide { owner.write(..string.format('pic%i.place_forget()', id)); }; 215 | if disabled { owner.write(..string.format('pic%i.configure(state="disabled")', id)); }; 216 | if bgcolor { 217 | bgcolorStr = ..color.stringify(bgcolor,false); 218 | owner.write(..string.format('pic%i.config(background="%s")', id, bgcolorStr)); 219 | }; 220 | if frcolor { 221 | frcolorStr = ..color.stringify(frcolor,false); 222 | owner.write(..string.format('pic%i.config(foreground="%s")', id, frcolorStr)); 223 | }; 224 | owner.write(..string.format('pic%i_frame.place(x=%i, y=%i)', id, x, y)); 225 | }; 226 | //画板 227 | if winctrol.cls == "plus" { 228 | var id = ctrlNameList.canvas + 1; 229 | ctrlNameList.canvas = id; 230 | this.translateNamelist[ctrl.z] = "canvas"++id; 231 | var vscroll = ctrl.vscroll; 232 | var hscroll = ctrl.hscroll; 233 | var bgcolor = winctrol.backgroundColor; 234 | owner.write(..string.format('canvas%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 235 | owner.write(..string.format('canvas%i = tk.Canvas(canvas%i_frame)', id, id)); 236 | owner.write(..string.format('canvas%i.place(x=0, y=0, width=%i, height=%i)', id , width, height)); 237 | if hide { owner.write(..string.format('canvas%i.place_forget()', id)); }; 238 | if disabled { owner.write(..string.format('canvas%i.configure(state="disabled")', id)); }; 239 | if vscroll { 240 | owner.write(..string.format('canvas%i_vscroll = tk.Scrollbar(canvas%i, orient="vertical", command=canvas%i.yview)', id, id, id)); 241 | owner.write(..string.format('canvas%i.configure(yscrollcommand=canvas%i_vscroll.set)', id, id)); 242 | owner.write(..string.format('canvas%i_vscroll.pack(side="right", fill="y")', id)); 243 | }; 244 | if hscroll { 245 | owner.write(..string.format('canvas%i_hscroll = tk.Scrollbar(canvas%i, orient="horizontal", command=canvas%i.xview)', id, id, id)); 246 | owner.write(..string.format('canvas%i.configure(xscrollcommand=canvas%i_hscroll.set)', id, id)); 247 | owner.write(..string.format('canvas%i_hscroll.pack(side="bottom", fill="x")', id)); 248 | }; 249 | if bgcolor { 250 | bgcolorStr = ..color.stringify(bgcolor,false); 251 | bStr = ..string.slice(bgcolorStr,2,3); 252 | gStr = ..string.slice(bgcolorStr,4,5); 253 | rStr = ..string.slice(bgcolorStr,6,7); 254 | owner.write(..string.format('canvas%i.config(background="#%s%s%s")', id, rStr, gStr, bStr)); 255 | }; 256 | owner.write(..string.format('canvas%i_frame.place(x=%i, y=%i)', id, x, y)); 257 | }; 258 | //ListBox 259 | if winctrol.cls == "listbox" { 260 | var id = ctrlNameList.listbox + 1; 261 | ctrlNameList.listbox = id; 262 | this.translateNamelist[ctrl.z] = "list"++id; 263 | var vscroll = ctrl.vscroll; 264 | var hscroll = ctrl.hscroll; 265 | owner.write(..string.format('list%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 266 | var items = winctrol.items; 267 | if #items>0 { 268 | owner.write(..string.format('items%i = tk.Variable(value=[', id), 0, ""); 269 | for i,item in items { 270 | owner.write('"' ++ item ++'", ', 0, ""); 271 | } 272 | owner.write('])'); 273 | owner.write(..string.format('list%i = tk.Listbox(list%i_frame, listvariable=items%i, %s)', id, id, id, justify)); 274 | 275 | } else { 276 | owner.write(..string.format('list%i = tk.Listbox(list%i_frame, %s)', id, id, justify)); 277 | } 278 | owner.write(..string.format('list%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 279 | if hide { owner.write(..string.format('list%i.place_forget()', id)); }; 280 | if disabled { owner.write(..string.format('list%i.configure(state="disabled")', id)); }; 281 | if vscroll { 282 | owner.write(..string.format('list%i_vscroll = tk.Scrollbar(list%i, orient="vertical", command=list%i.yview)', id, id, id)); 283 | owner.write(..string.format('list%i.configure(yscrollcommand=list%i_vscroll.set)', id, id)); 284 | owner.write(..string.format('list%i_vscroll.pack(side="right", fill="y")', id)); 285 | }; 286 | if hscroll { 287 | owner.write(..string.format('list%i_hscroll = tk.Scrollbar(list%i, orient="horizontal", command=list%i.xview)', id, id, id)); 288 | owner.write(..string.format('list%i.configure(xscrollcommand=list%i_hscroll.set)', id, id)); 289 | owner.write(..string.format('list%i_hscroll.pack(side="bottom", fill="x")', id)); 290 | }; 291 | if font { 292 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 293 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 294 | var family = 'family="'+font.name+'"'; 295 | var underline = font.underline ? 'underline=True' : 'underline=False'; 296 | var size = 'size='++..math.round(font.h*(-3)/4); 297 | owner.write(..string.format('list%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", "))); 298 | owner.write(..string.format('list%i.configure(font=list%i_font)', id, id)); 299 | }; 300 | if bgcolor { 301 | bgcolorStr = ..color.stringify(bgcolor,false); 302 | owner.write(..string.format('list%i.config(background="%s")', id, bgcolorStr)); 303 | }; 304 | if frcolor { 305 | frcolorStr = ..color.stringify(frcolor,false); 306 | owner.write(..string.format('list%i.config(foreground="%s")', id, frcolorStr)); 307 | }; 308 | owner.write(..string.format('list%i_frame.place(x=%i, y=%i)', id, x, y)); 309 | }; 310 | //下拉框 311 | if winctrol.cls == "combobox" { 312 | var id = ctrlNameList.combobox + 1; 313 | ctrlNameList.combobox = id; 314 | this.translateNamelist[ctrl.z] = "combobox"++id; 315 | owner.write(..string.format('combobox%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 316 | var items = winctrol.items; 317 | if #items>0 { 318 | owner.write(..string.format('combobox%i= ttk.Combobox(combobox%i_frame, value=[', id, id), 0, ""); 319 | for i,item in items { 320 | owner.write('"' ++ item ++'", ', 0, ""); 321 | } 322 | owner.write(..string.format('], %s)', justify)); 323 | 324 | } else { 325 | owner.write(..string.format('combobox%i = ttk.Combobox(combobox%i_frame, %s)', id, id, justify)); 326 | } 327 | owner.write(..string.format('combobox%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 328 | if hide { owner.write(..string.format('combobox%i.place_forget()', id)); }; 329 | if disabled { owner.write(..string.format('combobox%i.configure(state="disabled")', id)); }; 330 | if font { 331 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 332 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 333 | var family = 'family="'+font.name+'"'; 334 | var underline = font.underline ? 'underline=True' : 'underline=False'; 335 | var size = 'size='++..math.round(font.h*(-3)/4); 336 | owner.write(..string.format('combobox%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", "))); 337 | owner.write(..string.format('combobox%i.configure(font=combobox%i_font)', id, id)); 338 | }; 339 | if bgcolor { 340 | bgcolorStr = ..color.stringify(bgcolor,false); 341 | owner.write(..string.format('combobox%i.config(background="%s")', id, bgcolorStr)); 342 | }; 343 | if frcolor { 344 | frcolorStr = ..color.stringify(frcolor,false); 345 | owner.write(..string.format('combobox%i.config(foreground="%s")', id, frcolorStr)); 346 | }; 347 | owner.write(..string.format('combobox%i_frame.place(x=%i, y=%i)', id, x, y)); 348 | }; 349 | //表格 350 | if winctrol.cls == "listview" { 351 | var id = ctrlNameList.treeview + 1; 352 | ctrlNameList.treeview = id; 353 | this.translateNamelist[ctrl.z] = "tree"++id; 354 | owner.write(..string.format('tree%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 355 | owner.write(..string.format('tree%i = ttk.Treeview(tree%i_frame)', id, id)); 356 | owner.write(..string.format('tree%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 357 | if hide { owner.write(..string.format('tree%i.place_forget()', id)); }; 358 | if disabled { owner.write(..string.format('tree%i.configure(state="disabled")', id)); }; 359 | owner.write(..string.format('tree%i_frame.place(x=%i, y=%i)', id, x, y)); 360 | }; 361 | //进度条 362 | if winctrol.cls == "progress" { 363 | var id = ctrlNameList.progress + 1; 364 | ctrlNameList.progress = id; 365 | this.translateNamelist[ctrl.z] = "progress"++id; 366 | owner.write(..string.format('progress%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 367 | var max = winctrol.max; 368 | var value = winctrol.pos; 369 | owner.write(..string.format('progress%i = ttk.Progressbar(progress%i_frame, value=%i, maximum=%i)', id, id, value, max)); 370 | owner.write(..string.format('progress%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 371 | if hide { owner.write(..string.format('progress%i.place_forget()', id)); }; 372 | if disabled { owner.write(..string.format('progress%i.configure(state="disabled")', id)); }; 373 | owner.write(..string.format('progress%i_frame.place(x=%i, y=%i)', id, x, y)); 374 | }; 375 | //Trackbar 376 | if winctrol.cls == "trackbar" { 377 | var id = ctrlNameList.trackbar + 1; 378 | ctrlNameList.trackbar = id; 379 | this.translateNamelist[ctrl.z] = "scale"++id; 380 | owner.write(..string.format('scale%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height)); 381 | var min = winctrol.min; 382 | var max = winctrol.max; 383 | var value = winctrol.pos; 384 | owner.write(..string.format('scale%i = ttk.Scale(scale%i_frame, from_=%i, to=%i, value=%i)', id, id, min, max, value)); 385 | owner.write(..string.format('scale%i.place(x=0, y=0, width=%i, height=%i)', id, width, height)); 386 | if hide { owner.write(..string.format('scale%i.place_forget()', id)); }; 387 | if disabled { owner.write(..string.format('scale%i.configure(state="disabled")', id)); }; 388 | owner.write(..string.format('scale%i_frame.place(x=%i, y=%i)', id, x, y)); 389 | }; 390 | //GroupBox 391 | if winctrol.cls == "groupbox" { 392 | var id = ctrlNameList.groupbox + 1; 393 | ctrlNameList.groupbox = id; 394 | this.translateNamelist[ctrl.z] = "labelframe"++id; 395 | owner.write(..string.format('labelframe%i = ttk.Labelframe(text="%s", width=%i, height=%i)', id, text, width, height)); 396 | owner.write(..string.format('labelframe%i.place(x=%i, y=%i, width=%i, height=%i)', id, x, y, width, height)); 397 | if hide { owner.write(..string.format('labelframe%i.place_forget()', id)); }; 398 | if font { 399 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 400 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 401 | var family = 'family="'+font.name+'"'; 402 | var underline = font.underline ? 'underline=True' : 'underline=False'; 403 | var size = 'size='++..math.round(font.h*(-3)/4); 404 | owner.write(..string.format('labelframe%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", "))); 405 | owner.write(..string.format('labelframe%i.configure(font=labelframe%i_font)', id, id)); 406 | }; 407 | }; 408 | //Frame 409 | if winctrol.cls == "custom" { 410 | var id = ctrlNameList.frame + 1; 411 | ctrlNameList.frame = id; 412 | this.translateNamelist[ctrl.z] = "frame"++id; 413 | owner.write(..string.format('frame%i = ttk.Frame(width=%i, height=%i)', id, width, height)); 414 | owner.write(..string.format('frame%i.place(x=%i, y=%i, width=%i, height=%i)', id, x, y, width, height)); 415 | if hide { owner.write(..string.format('frame%i.place_forget()', id)); }; 416 | }; 417 | //Tab 418 | if winctrol.cls == "tab" { 419 | var id = ctrlNameList.tab + 1; 420 | ctrlNameList.tab = id; 421 | this.translateNamelist[ctrl.z] = "nb"++id; 422 | owner.write(..string.format('nb%i = ttk.Notebook(width=%i, height=%i)', id, width, height)); 423 | owner.write(..string.format('nb%i.place(x=%i, y=%i, width=%i, height=%i)', id, x, y, width, height)); 424 | if hide { owner.write(..string.format('nb%i.place_forget()', id)); }; 425 | if font { 426 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 427 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 428 | var family = 'family="'+font.name+'"'; 429 | var underline = font.underline ? 'underline=True' : 'underline=False'; 430 | var size = 'size='++..math.round(font.h*(-3)/4); 431 | owner.write(..string.format('nb%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", "))); 432 | owner.write(..string.format('nb%i.configure(font=nb%i_font)', id, id)); 433 | }; 434 | }; 435 | }; 436 | 437 | owner.write('\r\n\r\n### 功能逻辑部分 ###\r\n'); 438 | 439 | owner.write('root.mainloop()'); 440 | 441 | return this.pycode; 442 | }; 443 | 444 | 445 | //转换为组件 446 | transfer2place = function(name="SubAssembly"){ 447 | var window_width = this.width; 448 | var window_height = this.height; 449 | var window_text = this.text; 450 | this.pycode = /*** 451 | import tkinter as tk 452 | import tkinter.ttk as ttk 453 | import tkinter.font as tkFont 454 | 455 | class ***/ 456 | owner.write(name++'():\r\n ### 界面设计部分 ###\r\n \r\n def __init__(self, master):'); 457 | owner.write(..string.format('self.mainframe = ttk.Frame(master, width=%i, height=%i)', window_width, window_height), 8); 458 | var ctrlNameList = { 459 | 'button' = 0; 460 | 'static' = 0; 461 | 'edit' = 0; 462 | 'radio' = 0; 463 | 'check' = 0; 464 | 'pic' = 0; 465 | 'listbox' = 0; 466 | 'combobox' = 0; 467 | 'progress' = 0; 468 | 'trackbar' = 0; 469 | 'listview' = 0; 470 | 'treeview' = 0; 471 | 'canvas' = 0; 472 | 'groupbox' = 0; 473 | 'frame' = 0; 474 | 'tab' = 0; 475 | 476 | }; 477 | for ( hwnd,ctrl in this.eachControlEx() ){ 478 | winctrol = this.getCtrl(hwnd); 479 | var x = winctrol.left; 480 | var y = winctrol.top; 481 | var width = winctrol.width; 482 | var height = winctrol.height; 483 | var text = winctrol.text; 484 | var hide = ctrl.hide; 485 | var disabled = ctrl.disabled; 486 | var readonly = ctrl.readonly; 487 | var bgcolor = ctrl.bgcolor; 488 | var frcolor = ctrl.color; 489 | var font = ctrl.font; 490 | var align = ctrl.align; 491 | var justify; 492 | if !align { 493 | justify = 'justify="left"'; 494 | } elseif align == "center" { 495 | justify = 'justify="center"'; 496 | } else { 497 | justify = 'justify="right"'; 498 | }; 499 | //按钮 500 | if winctrol.cls == "button" { 501 | var id = ctrlNameList.button + 1; 502 | ctrlNameList.button = id; 503 | this.translateNamelist[ctrl.z] = "button"++id; 504 | owner.write(..string.format('self.button%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 505 | owner.write(..string.format('self.button%i = ttk.Button(self.button%i_frame, text="%s")', id, id, text), 8); 506 | owner.write(..string.format('self.button%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 507 | if hide { owner.write(..string.format('self.button%i.place_forget()', id), 8); }; 508 | if disabled { owner.write(..string.format('self.button%i.configure(state="disabled")', id), 8); }; 509 | 510 | owner.write(..string.format('self.button%i_frame.place(x=%i, y=%i)', id, x, y), 8); 511 | }; 512 | //标签 513 | if winctrol.cls == "static" { 514 | var id = ctrlNameList.static + 1; 515 | ctrlNameList.static = id; 516 | this.translateNamelist[ctrl.z] = "label"++id; 517 | owner.write(..string.format('self.label%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 518 | owner.write(..string.format('self.label%i = ttk.Label(self.label%i_frame, text="%s", %s)', id, id, text, justify), 8); 519 | owner.write(..string.format('self.label%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 520 | if hide { owner.write(..string.format('self.label%i.place_forget()'), 8); }; 521 | if disabled { owner.write(..string.format('self.label%i.configure(state="disabled")'), 8); }; 522 | if font { 523 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 524 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 525 | var family = 'family="'+font.name+'"'; 526 | var underline = font.underline ? 'underline=True' : 'underline=False'; 527 | var size = 'size='++..math.round(font.h*(-3)/4); 528 | owner.write(..string.format('self.label%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", ")), 8); 529 | owner.write(..string.format('self.label%i.configure(font=self.label%i_font)', id, id), 8); 530 | }; 531 | if bgcolor { 532 | bgcolorStr = ..color.stringify(bgcolor,false); 533 | owner.write(..string.format('self.label%i.config(background="%s")', id, bgcolorStr), 8); 534 | }; 535 | if frcolor { 536 | frcolorStr = ..color.stringify(frcolor,false); 537 | owner.write(..string.format('self.label%i.config(foreground="%s")', id, frcolorStr), 8); 538 | }; 539 | owner.write(..string.format('self.label%i_frame.place(x=%i, y=%i)', id, x, y), 8); 540 | }; 541 | //文本框 542 | if winctrol.cls == "edit" { 543 | var id = ctrlNameList.edit + 1; 544 | ctrlNameList.edit = id; 545 | this.translateNamelist[ctrl.z] = "edit"++id; 546 | var vscroll = ctrl.vscroll; 547 | var hscroll = ctrl.hscroll; 548 | owner.write(..string.format('self.editVar%i = tk.StringVar(value="%s")', id, text), 8); 549 | owner.write(..string.format('self.edit%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 550 | if winctrol.multiline == 1 { 551 | owner.write(..string.format('self.edit%i = tk.Text(self.edit%i_frame)', id, id), 8); 552 | owner.write(..string.format('self.edit%i.insert("end", "%s")', id, text), 8); 553 | } else { 554 | owner.write(..string.format('self.edit%i = ttk.Entry(self.edit%i_frame, textvariable=self.editVar%i, %s)', id, id, id, justify), 8); 555 | } 556 | owner.write(..string.format('self.edit%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 557 | if ctrl.password { owner.write(..string.format('self.edit%i.configure(show="*")', id), 8); }; 558 | if(readonly or disabled) { owner.write(..string.format('self.edit%i.configure(state="disabled")', id), 8); }; 559 | if hide { owner.write(..string.format('self.edit%i.place_forget()', id), 8); }; 560 | if vscroll { 561 | owner.write(..string.format('self.edit%i_vscroll = tk.Scrollbar(self.edit%i, orient="vertical", command=self.edit%i.yview)', id, id, id), 8); 562 | owner.write(..string.format('self.edit%i.configure(yscrollcommand=self.edit%i_vscroll.set)', id, id), 8); 563 | owner.write(..string.format('self.edit%i_vscroll.pack(side="right", fill="y")', id), 8); 564 | }; 565 | if hscroll { 566 | owner.write(..string.format('self.edit%i_hscroll = tk.Scrollbar(self.edit%i, orient="horizontal", command=self.edit%i.xview)',id, id, id), 8); 567 | owner.write(..string.format('self.edit%i.configure(xscrollcommand=self.edit%i_hscroll.set)', id, id), 8); 568 | owner.write(..string.format('self.edit%i_hscroll.pack(side="bottom", fill="x")', id), 8); 569 | }; 570 | if font { 571 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 572 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 573 | var family = 'family="'+font.name+'"'; 574 | var underline = font.underline ? 'underline=True' : 'underline=False'; 575 | var size = 'size='++..math.round(font.h*(-3)/4); 576 | owner.write(..string.format('self.edit%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", ")), 8); 577 | owner.write(..string.format('self.edit%i.configure(font=self.edit%i_font)', id, id), 8); 578 | }; 579 | if bgcolor { 580 | bgcolorStr = ..color.stringify(bgcolor,false); 581 | owner.write(..string.format('self.edit%i.config(background="%s")', id, bgcolorStr), 8); 582 | }; 583 | if frcolor { 584 | frcolorStr = ..color.stringify(frcolor,false); 585 | owner.write(..string.format('self.edit%i.config(foreground="%s")', id, frcolorStr), 8); 586 | }; 587 | owner.write(..string.format('self.edit%i_frame.place(x=%i, y=%i)', id, x, y), 8); 588 | }; 589 | //单选 590 | if winctrol.cls == "radiobutton" { 591 | var id = ctrlNameList.radio + 1; 592 | ctrlNameList.radio = id; 593 | this.translateNamelist[ctrl.z] = "radio"++id; 594 | owner.write(..string.format('self.radio%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 595 | owner.write(..string.format('self.radio%i = ttk.Radiobutton(self.radio%i_frame, text="%s", value=%i)', id, id, text, id), 8); 596 | owner.write(..string.format('self.radio%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 597 | if hide { owner.write(..string.format('self.radio%i.place_forget()', id), 8); }; 598 | if disabled { owner.write(..string.format('self.radio%i.configure(state="disabled")', id), 8); }; 599 | owner.write(..string.format('self.radio%i_frame.place(x=%i, y=%i)', id, x, y), 8); 600 | }; 601 | //复选 602 | if winctrol.cls == "checkbox" { 603 | var id = ctrlNameList.check + 1; 604 | ctrlNameList.check = id; 605 | owner.translateNamelist[ctrl.z] = "check"++id; 606 | owner.write(..string.format('self.check%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 607 | owner.write(..string.format('self.check%i = ttk.Checkbutton(self.check%i_frame, text="%s")', id, id, text), 8); 608 | owner.write(..string.format('self.check%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 609 | if hide { owner.write(..string.format('self.check%i.place_forget()', id), 8); }; 610 | if disabled { owner.write(..string.format('self.check%i.configure(state="disabled")', id), 8); }; 611 | owner.write(..string.format('self.check%i_frame.place(x=%i, y=%i)', id, x, y), 8); 612 | }; 613 | //图片框 614 | if winctrol.cls == "picturebox" { 615 | var id = ctrlNameList.pic + 1; 616 | ctrlNameList.pic = id; 617 | this.translateNamelist[ctrl.z] = "pic"++id; 618 | owner.write(..string.format('self.pic%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 619 | var picpath = winctrol.background; 620 | if picpath { 621 | owner.write(..string.format('self.img%i = tk.PhotoImage(file=r"%s")', id, picpath), 8); 622 | owner.write(..string.format('self.pic%i = ttk.Label(self.pic%i_frame, image=self.img%i, %s)', id, id, id, justify), 8); 623 | } else { 624 | owner.write(..string.format('self.pic%i = ttk.Label(self.pic%i_frame, %s)', id, id, justify), 8); 625 | } 626 | owner.write(..string.format('self.pic%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 627 | if hide { owner.write(..string.format('self.pic%i.place_forget()', id), 8); }; 628 | if disabled { owner.write(..string.format('self.pic%i.configure(state="disabled")', id), 8); }; 629 | if bgcolor { 630 | bgcolorStr = ..color.stringify(bgcolor,false); 631 | owner.write(..string.format('self.pic%i.config(background="%s")', id, bgcolorStr), 8); 632 | }; 633 | if frcolor { 634 | frcolorStr = ..color.stringify(frcolor,false); 635 | owner.write(..string.format('self.pic%i.config(foreground="%s")', id, frcolorStr), 8); 636 | }; 637 | owner.write(..string.format('self.pic%i_frame.place(x=%i, y=%i)', id, x, y), 8); 638 | }; 639 | //画板 640 | if winctrol.cls == "plus" { 641 | var id = ctrlNameList.canvas + 1; 642 | ctrlNameList.canvas = id; 643 | this.translateNamelist[ctrl.z] = "canvas"++id; 644 | var vscroll = ctrl.vscroll; 645 | var hscroll = ctrl.hscroll; 646 | var bgcolor = winctrol.backgroundColor; 647 | owner.write(..string.format('self.canvas%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 648 | owner.write(..string.format('self.canvas%i = tk.Canvas(self.canvas%i_frame)', id, id), 8); 649 | owner.write(..string.format('self.canvas%i.place(x=0, y=0, width=%i, height=%i)', id , width, height), 8); 650 | if hide { owner.write(..string.format('self.canvas%i.place_forget()', id), 8); }; 651 | if disabled { owner.write(..string.format('self.canvas%i.configure(state="disabled")', id), 8); }; 652 | if vscroll { 653 | owner.write(..string.format('self.canvas%i_vscroll = tk.Scrollbar(self.canvas%i, orient="vertical", command=self.canvas%i.yview)', id, id, id), 8); 654 | owner.write(..string.format('self.canvas%i.configure(yscrollcommand=self.canvas%i_vscroll.set)', id, id), 8); 655 | owner.write(..string.format('self.canvas%i_vscroll.pack(side="right", fill="y")', id), 8); 656 | }; 657 | if hscroll { 658 | owner.write(..string.format('self.canvas%i_hscroll = tk.Scrollbar(self.canvas%i, orient="horizontal", command=self.canvas%i.xview)', id, id, id), 8); 659 | owner.write(..string.format('self.canvas%i.configure(xscrollcommand=self.canvas%i_hscroll.set)', id, id), 8); 660 | owner.write(..string.format('self.canvas%i_hscroll.pack(side="bottom", fill="x")', id), 8); 661 | }; 662 | if bgcolor { 663 | bgcolorStr = ..color.stringify(bgcolor,false); 664 | bStr = ..string.slice(bgcolorStr,2,3); 665 | gStr = ..string.slice(bgcolorStr,4,5); 666 | rStr = ..string.slice(bgcolorStr,6,7); 667 | owner.write(..string.format('self.canvas%i.config(background="#%s%s%s")', id, rStr, gStr, bStr), 8); 668 | }; 669 | owner.write(..string.format('self.canvas%i_frame.place(x=%i, y=%i)', id, x, y), 8); 670 | }; 671 | //ListBox 672 | if winctrol.cls == "listbox" { 673 | var id = ctrlNameList.listbox + 1; 674 | ctrlNameList.listbox = id; 675 | this.translateNamelist[ctrl.z] = "list"++id; 676 | var vscroll = ctrl.vscroll; 677 | var hscroll = ctrl.hscroll; 678 | owner.write(..string.format('self.list%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 679 | var items = winctrol.items; 680 | if #items>0 { 681 | owner.write(..string.format('self.items%i = tk.Variable(value=[', id), 0, ""); 682 | for i,item in items { 683 | owner.write('"' ++ item ++'", ', 0, ""); 684 | } 685 | owner.write('])'); 686 | owner.write(..string.format('self.list%i = tk.Listbox(self.list%i_frame, listvariable=self.items%i, %s)', id, id, id, justify), 8); 687 | 688 | } else { 689 | owner.write(..string.format('self.list%i = tk.Listbox(self.list%i_frame, %s)', id, id, justify), 8); 690 | } 691 | owner.write(..string.format('self.list%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 692 | if hide { owner.write(..string.format('self.list%i.place_forget()', id), 8); }; 693 | if disabled { owner.write(..string.format('self.list%i.configure(state="disabled")', id), 8); }; 694 | if vscroll { 695 | owner.write(..string.format('self.list%i_vscroll = tk.Scrollbar(self.list%i, orient="vertical", command=self.list%i.yview)', id, id, id), 8); 696 | owner.write(..string.format('self.list%i.configure(yscrollcommand=self.list%i_vscroll.set)', id, id), 8); 697 | owner.write(..string.format('self.list%i_vscroll.pack(side="right", fill="y")', id), 8); 698 | }; 699 | if hscroll { 700 | owner.write(..string.format('self.list%i_hscroll = tk.Scrollbar(self.list%i, orient="horizontal", command=self.list%i.xview)', id, id, id), 8); 701 | owner.write(..string.format('self.list%i.configure(xscrollcommand=self.list%i_hscroll.set)', id, id), 8); 702 | owner.write(..string.format('self.list%i_hscroll.pack(side="bottom", fill="x")', id), 8); 703 | }; 704 | if font { 705 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 706 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 707 | var family = 'family="'+font.name+'"'; 708 | var underline = font.underline ? 'underline=True' : 'underline=False'; 709 | var size = 'size='++..math.round(font.h*(-3)/4); 710 | owner.write(..string.format('self.list%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", ")), 8); 711 | owner.write(..string.format('self.list%i.configure(font=list%i_font)', id, id), 8); 712 | }; 713 | if bgcolor { 714 | bgcolorStr = ..color.stringify(bgcolor,false); 715 | owner.write(..string.format('self.list%i.config(background="%s")', id, bgcolorStr), 8); 716 | }; 717 | if frcolor { 718 | frcolorStr = ..color.stringify(frcolor,false); 719 | owner.write(..string.format('self.list%i.config(foreground="%s")', id, frcolorStr), 8); 720 | }; 721 | owner.write(..string.format('self.list%i_frame.place(x=%i, y=%i)', id, x, y), 8); 722 | }; 723 | //下拉框 724 | if winctrol.cls == "combobox" { 725 | var id = ctrlNameList.combobox + 1; 726 | ctrlNameList.combobox = id; 727 | this.translateNamelist[ctrl.z] = "combobox"++id; 728 | owner.write(..string.format('self.combobox%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 729 | var items = winctrol.items; 730 | if #items>0 { 731 | owner.write(..string.format('self.combobox%i= ttk.Combobox(self.combobox%i_frame, value=[', id, id), 0, ""); 732 | for i,item in items { 733 | owner.write('"' ++ item ++'", ', 0, ""); 734 | } 735 | owner.write(..string.format('], %s)', justify), 8); 736 | 737 | } else { 738 | owner.write(..string.format('self.combobox%i = ttk.Combobox(self.combobox%i_frame, %s)', id, id, justify), 8); 739 | } 740 | owner.write(..string.format('self.combobox%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 741 | if hide { owner.write(..string.format('self.combobox%i.place_forget()', id), 8); }; 742 | if disabled { owner.write(..string.format('self.combobox%i.configure(state="disabled")', id), 8); }; 743 | if font { 744 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 745 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 746 | var family = 'family="'+font.name+'"'; 747 | var underline = font.underline ? 'underline=True' : 'underline=False'; 748 | var size = 'size='++..math.round(font.h*(-3)/4); 749 | owner.write(..string.format('self.combobox%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", ")), 8); 750 | owner.write(..string.format('self.combobox%i.configure(font=self.combobox%i_font)', id, id), 8); 751 | }; 752 | if bgcolor { 753 | bgcolorStr = ..color.stringify(bgcolor,false); 754 | owner.write(..string.format('self.combobox%i.config(background="%s")', id, bgcolorStr), 8); 755 | }; 756 | if frcolor { 757 | frcolorStr = ..color.stringify(frcolor,false); 758 | owner.write(..string.format('self.combobox%i.config(foreground="%s")', id, frcolorStr), 8); 759 | }; 760 | owner.write(..string.format('self.combobox%i_frame.place(x=%i, y=%i)', id, x, y), 8); 761 | }; 762 | //表格 763 | if winctrol.cls == "listview" { 764 | var id = ctrlNameList.treeview + 1; 765 | ctrlNameList.treeview = id; 766 | this.translateNamelist[ctrl.z] = "tree"++id; 767 | owner.write(..string.format('self.tree%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 768 | owner.write(..string.format('self.tree%i = ttk.Treeview(self.tree%i_frame)', id, id), 8); 769 | owner.write(..string.format('self.tree%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 770 | if hide { owner.write(..string.format('self.tree%i.place_forget()', id), 8); }; 771 | if disabled { owner.write(..string.format('self.tree%i.configure(state="disabled")', id), 8); }; 772 | owner.write(..string.format('self.tree%i_frame.place(x=%i, y=%i)', id, x, y), 8); 773 | }; 774 | //进度条 775 | if winctrol.cls == "progress" { 776 | var id = ctrlNameList.progress + 1; 777 | ctrlNameList.progress = id; 778 | this.translateNamelist[ctrl.z] = "progress"++id; 779 | owner.write(..string.format('self.progress%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 780 | var max = winctrol.max; 781 | var value = winctrol.pos; 782 | owner.write(..string.format('self.progress%i = ttk.Progressbar(self.progress%i_frame, value=%i, maximum=%i)', id, id, value, max), 8); 783 | owner.write(..string.format('self.progress%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 784 | if hide { owner.write(..string.format('self.progress%i.place_forget()', id), 8); }; 785 | if disabled { owner.write(..string.format('self.progress%i.configure(state="disabled")', id), 8); }; 786 | owner.write(..string.format('self.progress%i_frame.place(x=%i, y=%i)', id, x, y), 8); 787 | }; 788 | //Trackbar 789 | if winctrol.cls == "trackbar" { 790 | var id = ctrlNameList.trackbar + 1; 791 | ctrlNameList.trackbar = id; 792 | this.translateNamelist[ctrl.z] = "scale"++id; 793 | owner.write(..string.format('self.scale%i_frame = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 794 | var min = winctrol.min; 795 | var max = winctrol.max; 796 | var value = winctrol.pos; 797 | owner.write(..string.format('self.scale%i = ttk.Scale(self.scale%i_frame, from_=%i, to=%i, value=%i)', id, id, min, max, value), 8); 798 | owner.write(..string.format('self.scale%i.place(x=0, y=0, width=%i, height=%i)', id, width, height), 8); 799 | if hide { owner.write(..string.format('self.scale%i.place_forget()', id), 8); }; 800 | if disabled { owner.write(..string.format('self.scale%i.configure(state="disabled")', id), 8); }; 801 | owner.write(..string.format('self.scale%i_frame.place(x=%i, y=%i)', id, x, y), 8); 802 | }; 803 | //GroupBox 804 | if winctrol.cls == "groupbox" { 805 | var id = ctrlNameList.groupbox + 1; 806 | ctrlNameList.groupbox = id; 807 | this.translateNamelist[ctrl.z] = "labelframe"++id; 808 | owner.write(..string.format('self.labelframe%i = ttk.Labelframe(text="%s", width=%i, height=%i)', id, text, width, height), 8); 809 | owner.write(..string.format('self.labelframe%i.place(x=%i, y=%i, width=%i, height=%i)', id, x, y, width, height), 8); 810 | if hide { owner.write(..string.format('self.labelframe%i.place_forget()', id), 8); }; 811 | if font { 812 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 813 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 814 | var family = 'family="'+font.name+'"'; 815 | var underline = font.underline ? 'underline=True' : 'underline=False'; 816 | var size = 'size='++..math.round(font.h*(-3)/4); 817 | owner.write(..string.format('self.labelframe%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", ")), 8); 818 | owner.write(..string.format('self.labelframe%i.configure(font=self.labelframe%i_font)', id, id), 8); 819 | }; 820 | }; 821 | //Frame 822 | if winctrol.cls == "custom" { 823 | var id = ctrlNameList.frame + 1; 824 | ctrlNameList.frame = id; 825 | this.translateNamelist[ctrl.z] = "frame"++id; 826 | owner.write(..string.format('self.frame%i = ttk.Frame(width=%i, height=%i)', id, width, height), 8); 827 | owner.write(..string.format('self.frame%i.place(x=%i, y=%i, width=%i, height=%i)', id, x, y, width, height), 8); 828 | if hide { owner.write(..string.format('self.frame%i.place_forget()', id), 8); }; 829 | }; 830 | //Tab 831 | if winctrol.cls == "tab" { 832 | var id = ctrlNameList.tab + 1; 833 | ctrlNameList.tab = id; 834 | this.translateNamelist[ctrl.z] = "nb"++id; 835 | owner.write(..string.format('self.nb%i = ttk.Notebook(width=%i, height=%i)', id, width, height), 8); 836 | owner.write(..string.format('self.nb%i.place(x=%i, y=%i, width=%i, height=%i)', id, x, y, width, height), 8); 837 | if hide { owner.write(..string.format('self.nb%i.place_forget()', id), 8); }; 838 | if font { 839 | var italic = font.italic ? 'slant="italic"' : 'slant="roman"'; 840 | var weight = font.weight==700 ? 'weight="bold"' : 'weight="normal"'; 841 | var family = 'family="'+font.name+'"'; 842 | var underline = font.underline ? 'underline=True' : 'underline=False'; 843 | var size = 'size='++..math.round(font.h*(-3)/4); 844 | owner.write(..string.format('self.nb%i_font = tkFont.Font(%s)', id, ..string.join({family; size; weight; italic; underline}, ", ")), 8); 845 | owner.write(..string.format('self.nb%i.configure(font=self.nb%i_font)', id, id), 8); 846 | }; 847 | }; 848 | }; 849 | 850 | owner.write('self.mainframe.pack()', 8); 851 | 852 | owner.write('\r\n ### 功能逻辑部分 ###\r\n\r\n', 0); 853 | 854 | return this.pycode; 855 | }; 856 | 857 | translateName = function(){ 858 | var formStr = ..ide.getActiveCode(); 859 | var pattern = "(\w+)=\{.*?z=(\d\d?)\}"; 860 | var results = ..string.matches(formStr, pattern); 861 | for i, result in results { 862 | var name = result[1]; 863 | var z = result[2]; 864 | var theName = this.translateNamelist[tonumber(z)]; 865 | this.pycode = ..string.replace(this.pycode, theName, name) 866 | }; 867 | return owner.pycode; 868 | }; 869 | 870 | 871 | } 872 | 873 | /**intellisense() 874 | GUI2Py = 解析aardio界面生成Python Tkinter 875 | GUI2Py.GUI2Tk(.(winform界面窗体) = 返回解析对象 876 | ?GUI2Py.GUI2Tk = !GUI2Py_GUI2Tk. 877 | GUI2Py.GUI2Tk() = !GUI2Py_GUI2Tk. 878 | !GUI2Py_GUI2Tk.transfer2root( ) = 组件按place方式布局,返回的代码用于生成主界面 879 | !GUI2Py_GUI2Tk.transfer2place(.( "组件名称" ) = 组件按place方式布局,返回的代码用于生成组件类 880 | !GUI2Py_GUI2Tk.translateName(.( winform_DSG ) = 解析窗体设计器代码,并替换对应的控件名 881 | end intellisense**/ 882 | -------------------------------------------------------------------------------- /GUI2Py.tar.lzma: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerryxjr1220/aardioGUI2Python/829bd6614f7009044e8fc55aa70d7575d899a4eb/GUI2Py.tar.lzma -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2022, jerryxjr1220 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /Measurement/OptMeasure.py: -------------------------------------------------------------------------------- 1 | from demo1 import SA 2 | from demo2 import CA 3 | import tkinter as tk 4 | import tkinter.ttk as ttk 5 | 6 | 7 | root = tk.Tk() 8 | # 设置全局变量 scale_rate转换比例 9 | scale_rate = tk.DoubleVar(root, value=1) 10 | nb = ttk.Notebook(root) 11 | tab1 = ttk.Frame(nb) 12 | nb.add(tab1, text='光学测量') 13 | sa = SA(tab1, scale_rate) 14 | tab2 = ttk.Frame(nb) 15 | nb.add(tab2, text='测量校准') 16 | ca = CA(tab2, scale_rate) 17 | nb.pack() 18 | root.mainloop() 19 | -------------------------------------------------------------------------------- /Measurement/__pycache__/demo1.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerryxjr1220/aardioGUI2Python/829bd6614f7009044e8fc55aa70d7575d899a4eb/Measurement/__pycache__/demo1.cpython-38.pyc -------------------------------------------------------------------------------- /Measurement/__pycache__/demo2.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jerryxjr1220/aardioGUI2Python/829bd6614f7009044e8fc55aa70d7575d899a4eb/Measurement/__pycache__/demo2.cpython-38.pyc -------------------------------------------------------------------------------- /Measurement/demo1.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | import tkinter.ttk as ttk 3 | import tkinter.font as tkFont 4 | import cv2 5 | from PIL import Image, ImageTk, ImageDraw 6 | import pyautogui as auto 7 | from system_hotkey import SystemHotkey 8 | 9 | class SA(): 10 | ### 界面设计部分 ### 11 | 12 | def __init__(self, master, globalVar): # 增加一个全局变量接收参数globalVar = scale_rate 13 | self.globalVar = globalVar 14 | self.mainframe = ttk.Frame(master, width=716, height=569) 15 | # Z=1 16 | self.label1_frame = ttk.Frame(self.mainframe, width=158, height=24) 17 | self.label1 = ttk.Label(self.label1_frame, text="尺寸测量", justify="left") 18 | self.label1.place(x=0, y=0, width=158, height=24) 19 | self.label1_font = tkFont.Font(family="微软雅黑", size=12, weight="bold", slant="roman", underline=False) 20 | self.label1.configure(font=self.label1_font) 21 | self.label1.config(foreground="#000080") 22 | self.label1_frame.place(x=39, y=6) 23 | # Z=2 24 | self.pic1_frame = ttk.Frame(self.mainframe, width=640, height=480) 25 | self.pic1 = ttk.Label(self.pic1_frame, justify="left") 26 | self.pic1.place(x=0, y=0, width=640, height=480) 27 | self.pic1_frame.place(x=30, y=39) 28 | # Z=3 29 | self.button1_frame = ttk.Frame(self.mainframe, width=124, height=24) 30 | self.button1 = ttk.Button(self.button1_frame, text="打开摄像头", command=self.detect) 31 | self.button1.place(x=0, y=0, width=124, height=24) 32 | self.button1_frame.place(x=212, y=4) 33 | # Z=4 34 | self.button2_frame = ttk.Frame(self.mainframe, width=124, height=24) 35 | self.button2 = ttk.Button(self.button2_frame, text="关闭摄像头", command=self.close, state='disabled') 36 | self.button2.place(x=0, y=0, width=124, height=24) 37 | self.button2_frame.place(x=352, y=4) 38 | # Z=5 39 | self.scale1_frame = ttk.Frame(self.mainframe, width=200, height=24) 40 | self.scale1 = ttk.Scale(self.scale1_frame, orient='horizontal', from_=24, to=120, value=30, command=self.set_FPS) 41 | self.scale1.place(x=0, y=0, width=124, height=24) 42 | self.scale1_frame.place(x=502, y=4) 43 | self.mainframe.pack() 44 | # Global 45 | self.Running = False 46 | self.FPS = 30 47 | self.x = 0 48 | self.y = 0 49 | self.draw = False 50 | self.hotkey = SystemHotkey() 51 | self.hotkey.register(('f11',), callback=self.set_xy) 52 | 53 | ### 功能逻辑部分 ### 54 | def detect(self, *args): 55 | self.pic1.place(x=0, y=0, width=640, height=480) 56 | cap = cv2.VideoCapture(0) 57 | self.Running = True 58 | self.button2.configure(state='normal') 59 | self.capture(cap) 60 | 61 | 62 | def capture(self, cap): 63 | _, frame = cap.read() 64 | cwindow = auto.getActiveWindow() 65 | mx, my = auto.position() 66 | x = mx-cwindow.left-40 67 | y = my-cwindow.top-98 68 | d = ((self.x - x)**2 + (self.y - y)**2)**0.5 69 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 70 | im = Image.fromarray(frame) 71 | imtext = ImageDraw.Draw(im) 72 | imtext.text(xy=(5, 5), text=f'FPS: { self.FPS }') 73 | imtext.text(xy=(5, 15), text=f'({self.x}, {self.y}) to ({x}, {y}): { d }') 74 | if self.draw: 75 | imtext.line(xy=[(self.x, self.y), (x, y)], width=2) 76 | imtext.text(xy=(5, 25), text=f'Distance: {d/self.globalVar.get()} mm') 77 | img = ImageTk.PhotoImage(im) 78 | self.pic1.img = img 79 | self.pic1.configure(image=img) 80 | if self.Running: 81 | self.pic1.after(int(1000/self.FPS), lambda:self.capture(cap)) 82 | else: 83 | cap.release() 84 | 85 | def set_xy(self, *args): 86 | cwindow = auto.getActiveWindow() 87 | mx, my = auto.position() 88 | x = mx - cwindow.left - 40 89 | y = my - cwindow.top - 98 90 | self.x = x 91 | self.y = y 92 | self.draw = not self.draw 93 | 94 | def close(self, *args): 95 | self.Running = False 96 | self.pic1.place_forget() 97 | 98 | def set_FPS(self, *args): 99 | self.FPS = int(self.scale1.get()) 100 | 101 | -------------------------------------------------------------------------------- /Measurement/demo2.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | import tkinter.ttk as ttk 3 | import tkinter.font as tkFont 4 | import cv2 5 | from PIL import Image, ImageTk, ImageDraw 6 | import pyautogui as auto 7 | from system_hotkey import SystemHotkey 8 | import math 9 | 10 | class CA(): 11 | ### 界面设计部分 ### 12 | 13 | def __init__(self, master, globalVar): # 增加一个全局变量接收参数globalVar = scale_rate 14 | self.globalVar = globalVar 15 | self.mainframe = ttk.Frame(master, width=716, height=569) 16 | # Z=1 17 | self.label1_frame = ttk.Frame(self.mainframe, width=158, height=24) 18 | self.label1 = ttk.Label(self.label1_frame, text="尺寸校准", justify="left") 19 | self.label1.place(x=0, y=0, width=158, height=24) 20 | self.label1_font = tkFont.Font(family="微软雅黑", size=12, weight="bold", slant="roman", underline=False) 21 | self.label1.configure(font=self.label1_font) 22 | self.label1.config(foreground="#000080") 23 | self.label1_frame.place(x=39, y=6) 24 | # Z=4 25 | self.label2_frame = ttk.Frame(self.mainframe, width=184, height=21) 26 | self.label2 = ttk.Label(self.label2_frame, text="测量10mm的标准长度", justify="left") 27 | self.label2.place(x=0, y=0, width=184, height=21) 28 | self.label2_font = tkFont.Font(family="微软雅黑", size=11, weight="normal", slant="roman", underline=False) 29 | self.label2.configure(font=self.label2_font) 30 | self.label2_frame.place(x=372, y=4) 31 | # Z=2 32 | self.pic1_frame = ttk.Frame(self.mainframe, width=640, height=480) 33 | self.pic1 = ttk.Label(self.pic1_frame, justify="left") 34 | self.pic1.place(x=0, y=0, width=640, height=480) 35 | self.pic1_frame.place(x=30, y=39) 36 | # Z=3 37 | self.button1_frame = ttk.Frame(self.mainframe, width=124, height=24) 38 | self.button1 = ttk.Button(self.button1_frame, text="校 准", command=self.detect) 39 | self.button1.place(x=0, y=0, width=124, height=24) 40 | self.button1_frame.place(x=212, y=4) 41 | self.mainframe.pack() 42 | # Global 43 | self.Running = False 44 | self.FPS = 30 45 | self.x = 0 46 | self.y = 0 47 | self.draw = False 48 | self.hotkey = SystemHotkey() 49 | self.hotkey.register(('f10',), callback=self.set_xy) 50 | 51 | ### 功能逻辑部分 ### 52 | def detect(self, *args): 53 | self.pic1.place(x=0, y=0, width=640, height=480) 54 | cap = cv2.VideoCapture(0) 55 | self.Running = True 56 | self.capture(cap) 57 | 58 | def capture(self, cap): 59 | _, frame = cap.read() 60 | cwindow = auto.getActiveWindow() 61 | mx, my = auto.position() 62 | x = mx - cwindow.left - 40 63 | y = my - cwindow.top - 98 64 | d = ((self.x - x) ** 2 + (self.y - y) ** 2) ** 0.5 65 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) 66 | im = Image.fromarray(frame) 67 | imtext = ImageDraw.Draw(im) 68 | imtext.text(xy=(5, 5), text=f'FPS: {self.FPS}') 69 | imtext.text(xy=(5, 15), text=f'({self.x}, {self.y}) to ({x}, {y}): {d}') 70 | if self.draw: 71 | imtext.line(xy=[(self.x, self.y), (x, y)], width=2) 72 | img = ImageTk.PhotoImage(im) 73 | self.pic1.img = img 74 | self.pic1.configure(image=img) 75 | if self.Running: 76 | self.pic1.after(int(1000 / self.FPS), lambda: self.capture(cap)) 77 | else: 78 | cap.release() 79 | 80 | def set_xy(self, *args): 81 | cwindow = auto.getActiveWindow() 82 | mx, my = auto.position() 83 | x = mx - cwindow.left - 40 84 | y = my - cwindow.top - 98 85 | if self.draw: 86 | d = ((self.x - x) ** 2 + (self.y - y) ** 2) ** 0.5 87 | self.label2.configure(text=f'Scale : { int(d*10000)/100000 } px / mm') 88 | self.close() 89 | self.globalVar.set(d/10) 90 | self.x = x 91 | self.y = y 92 | self.draw = not self.draw 93 | 94 | def close(self, *args): 95 | self.Running = False 96 | self.pic1.place_forget() 97 | 98 | def set_FPS(self, *args): 99 | self.FPS = int(self.scale1.get()) 100 | 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GUI2Python for aardio 2 | 3 | 4 | GUI2Python Lib - use aardio to create UI of Tkinter and generate Python code. - *As a Tkinter Designer* 5 | 6 | >TKinter is a native Python Lib to easily create GUI of Python program,but there is no visual interface to use. Not friendly at all! 7 | 8 | Not too complicated, just like a "Qt Designer". 9 | 10 | >aardio is very easy to use to create UI so that it can be nice to create UI in aardio and transfer to tkinter in Python automatically! 11 | 12 | * aardio can be downloaded at [https://www.aardio.com/](https://www.aardio.com/) for the latest version for free. 13 | 14 | --- 15 | 16 | GUI2Python库 - 用aardio画Tkinter界面并生成Python代码 - *As a Tkinter Designer* 17 | 18 | >TKinter是Python的原生GUI库,用来创建一些简单的GUI界面还是很方便的。但是,缺点是没有提供一套图形化的设计界面,这样创建界面的时候就非常不直观。 19 | 20 | 思路是搞一个类似QtDesigner类似的工具,但是又不想搞得太复杂。 21 | 22 | >aardio的图形化设计非常便捷,这样在aardio里画好界面自动生成tkinter的python代码就是再好不过的事情了。 23 | 24 | * aardio 可以至 [https://www.aardio.com/](https://www.aardio.com/) 下载最新版,可免费下载使用。 25 | 26 | --- 27 | 28 | - 视频教程: [https://space.bilibili.com/382613220/channel/seriesdetail?sid=2503337](https://space.bilibili.com/382613220/channel/seriesdetail?sid=2503337) 29 | 30 | ## GUI2Py VB.Net版发布 31 | 32 | 详见VB.Net分支的GUI2Py.vb 33 | 34 | ## 目前可以实现的功能: 35 | 36 | - 20220823更新: 37 | 1. 修正picturebox图片显示问题,由于aardio遍历的时候无法识别image属性,需要自行显式添加```winform.picturebox.background=io.fullpath( )``` 38 | 2. Tkinter的图片格式必须为png格式,路径需为完整路径,不然可能无法显示。 39 | 40 | - 20220822更新: 41 | 1. 上传GUI2Py.tar.lzma库打包文件 42 | 2. 只需在代码页第一行插入 ```_IMPORTURL["GUI2Py"] = "https://github.com/jerryxjr1220/aardioGUI2Python/raw/aardio/GUI2Py.tar.lzma"``` 程序会自动下载GUI2Py库并进行安装。 43 | 44 | - 20220821更新: 45 | 1. 改进translateName方法,解析窗体设计器代码,并自动替换对应的控件名。具体见GUI2Py.aardio 46 | 2. 以后主要更新GUI2Py.aardio文件(原GUI2Py_simple.aardio),pack方法和grid方法可以自行修改。 47 | 48 | - 20220815更新: 49 | 1. 修正一处错误:GroupBox和NoteBook不支持font参数 50 | 51 | - 20220810更新: 52 | 1. 修正一处错误:radiobutton和checkbox不支持justify参数,也不支持font参数 53 | 2. radiobutton添加value参数,配合variable参数控制选项,详见Test实例 54 | 3. 添加一个新的Test实例“Python习题集” 55 | 56 | - 20220809更新: 57 | 1. 优化代码,用格式化字符串替换字符串拼接,增强可读性。 58 | 2. 精简布局,移除transfer2pack和transfer2grid方法(有需要可以自行更改transfer2place的最后一行布局代码),仅保留transfer2root和transfer2place。 59 | 3. 详见GUI2Py_simple.aardio,下载后改名替换原有GUI2Py.aardio 60 | 61 | - 20220807更新: 62 | 1. 优化代码增强可读性,功能不变。 63 | 64 | - 20220731更新: 65 | 1. 增加了一个实例:光学测量仪,源码在Measurement文件夹中。demo1.py和demo2.py的界面设计都是在aardio中完成并自动生成的,在添加逻辑功能后,放到主程序界面运行。 66 | 67 | - 20220728更新: 68 | 1. 标签、文本框等有字符布局的控件新增左对齐、居中、右对齐布局 69 | 2. 多行文本框、画板、Listbox增加水平和垂直滚动条 70 | 3. 新增translateName函数,解析窗体设计器代码,返回的Z序与对应控件名称,可用来替换python中的控件名 71 | >由于遍历控件时each返回的控件顺序是随机的,所以控件名和序号不好对应。但由于控件的Z序是固定的,所以新增了translateName函数,用于解析窗体设计器代码,返回的Z序与对应控件名称,可用来在python中替换控件名(可选功能) 72 | 73 | - 20220727更新: 74 | 75 | 1. 新增字体属性设置,可按照aardio中的字体自动设置到Tkinter中 76 | 2. 修改transfer2assembly名称 为 transfer2place,更好地对应place方法 77 | 78 | - 20220725更新: 79 | 80 | 1. 所有可禁用控件,增加禁用属性 81 | 2. 文本框增加密码属性 82 | 3. 增加pack布局 83 | 4. 增加grid布局 84 | 85 | - 20220724更新: 86 | 87 | 1. 基本控件都已经完善,包括Label, Button, Text/Entry, RadioButton, CheckBox, PictureBox, Canvas, ListBox, ComboBox, Treeview, ProgressBar, Scale, LabelFrame, Frame, Notebook等,基本满足常规使用。其余Tkinter支持的控件也可以通过手动方式添加使用。 88 | 2. 可以把界面直接转换为主界面 89 | 3. 更新组件化界面功能,这样可以像aardio一样把不同的界面拆成单独的组件,然后在Tabs高级选项卡(python中对应的就是Notebook)进行调用。也可以嵌入到其他Frame、Notebook、LabelFrame等容器中,当然也可以是主窗口Tk容器。 90 | 4. 新增了“隐藏”属性支持和背景色、前景色设置支持(仅对标签、文本框等控件有效) 91 | 5. 新增Canvas控件,对应aardio的plus 92 | 93 | ## Quick Start 94 | 95 | 1. 安装 96 | 直接把下载的GUI2Py.aardio文件复制到aardio项目文件夹的lib目录下(lib目录下存放着用户自制库,可以直接import到程序中)即可。 97 | 98 | 2. 在aardio中画界面 99 | ```aardio 100 | import win.ui; 101 | /*DSG{{*/ 102 | mainForm = win.form(text="Window Title";right=596;bottom=383) 103 | mainForm.add( 104 | button2={cls="button";text="Button";left=242;top=261;right=369;bottom=293;z=3}; 105 | edit2={cls="edit";text="Text";left=217;top=117;right=399;bottom=234;edge=1;multiline=1;z=2}; 106 | static2={cls="static";text="Hello, Python!";left=218;top=74;right=373;bottom=103;transparent=1;z=1} 107 | ) 108 | /*}}*/ 109 | 110 | mainForm.show(); 111 | return win.loopMessage(); 112 | ``` 113 | 114 | 3. 调用 115 | ```aardio 116 | import GUI2Py; 117 | g2t = GUI2Py.GUI2Tk(mainForm); 118 | code = g2t.transfer2root(); 119 | ``` 120 | 把这段代码放到主程序的```return win.loopMessage()```之前,不然无法运行。 121 | 现在生成的code就是我们所需要的python代码,可以直接复制到python运行,也可以用```string.save('example.py',code)```函数保存为py文件。 122 | 123 | 4. python代码 124 | ```python 125 | import tkinter as tk 126 | import tkinter.ttk as ttk 127 | 128 | root = tk.Tk() 129 | 130 | ### 界面设计部分 ### 131 | 132 | root.geometry("601x390") 133 | root.title("Window Title") 134 | button1_frame = ttk.Frame(width=127, height=32) 135 | button1 = ttk.Button(button1_frame, text="Button") 136 | button1.place(x=0, y=0) 137 | button1_frame.place(x=242, y=261) 138 | label1_frame = ttk.Frame(width=155, height=29) 139 | label1 = ttk.Label(label1_frame, text="Hello, Python!") 140 | label1.place(x=0, y=0) 141 | label1_frame.place(x=218, y=74) 142 | editVar1 = tk.StringVar(value='Text') 143 | edit1_frame = ttk.Frame(width=182, height=117) 144 | edit1 = tk.Text(edit1_frame) 145 | edit1.insert("end", "Text") 146 | edit1.place(x=0, y=0) 147 | edit1_frame.place(x=217, y=117) 148 | 149 | 150 | ### 功能逻辑部分 ### 151 | 152 | root.mainloop() 153 | ``` 154 | aardioGUI2Python库可以转换大部分的常用控件至Python的Tkinter中,界面可以直接运行。当然“功能逻辑部分”需要自行添加,可以实现预想的功能。 155 | 156 | ## 进阶应用 157 | 158 | 把界面组件化,这样可以像aardio一样把不同的界面拆成单独的组件,然后在Tabs高级选项卡(python中对应的就是Notebook)进行调用。也可以嵌入到其他Frame、Notebook、LabelFrame等容器中,当然也可以是主窗口Tk容器。 159 | ```aardio 160 | import GUI2Py; 161 | g2t = GUI2Py.GUI2Tk(mainForm); 162 | code = g2t.transfer2assembly(); 163 | ``` 164 | 165 | 生成的python代码 166 | ```python 167 | import tkinter as tk 168 | import tkinter.ttk as ttk 169 | 170 | class SubAssembly(): 171 | ### 界面设计部分 ### 172 | 173 | def __init__(self, master): 174 | self.mainframe = ttk.Frame(master, width=601, height=390) 175 | self.label1_frame = ttk.Frame(self.mainframe, width=155, height=29) 176 | self.label1 = ttk.Label(self.label1_frame, text="Hello, Python!") 177 | self.label1.place(x=0, y=0) 178 | self.label1_frame.place(x=218, y=74) 179 | self.editVar1 = tk.StringVar(value='Text') 180 | self.edit1_frame = ttk.Frame(self.mainframe, width=182, height=117) 181 | self.edit1 = tk.Text(self.edit1_frame) 182 | self.edit1.insert("end", "Text") 183 | self.edit1.place(x=0, y=0) 184 | self.edit1_frame.place(x=217, y=117) 185 | self.button1_frame = ttk.Frame(self.mainframe, width=127, height=32) 186 | self.button1 = ttk.Button(self.button1_frame, text="Button") 187 | self.button1.place(x=0, y=0) 188 | self.button1_frame.place(x=242, y=261) 189 | self.mainframe.pack() 190 | 191 | ### 功能逻辑部分 ### 192 | ``` 193 | 194 | 在python中调用,只需要实例化即可,当然如果需要实现额外功能,需要自行添加功能代码。 195 | ```python 196 | root = tk.Tk() 197 | sa = SubAssembly(root) 198 | root.mainloop() 199 | ``` 200 | 201 | ### 应用实例 202 | - aardio创建界面,用matplotlib画图,实时动态显示在Tkinter中 203 | 204 | ![https://www.htmlayout.cn/upload/image/20220726/1658814090451434.gif](https://www.htmlayout.cn/upload/image/20220726/1658814090451434.gif) 205 | 206 | ```python 207 | import tkinter as tk 208 | import tkinter.ttk as ttk 209 | import matplotlib.pyplot as plt 210 | import numpy as np 211 | from io import BytesIO 212 | from PIL import Image, ImageTk 213 | 214 | class SA(): 215 | ### 界面设计部分 ### 216 | 217 | def __init__(self, master): 218 | self.mainframe = ttk.Frame(master, width=601, height=390) 219 | self.label1_frame = ttk.Frame(self.mainframe, width=209, height=27) 220 | self.label1 = ttk.Label(self.label1_frame, text="y = sin(x) / log(x)") 221 | self.label1.place(x=0, y=0) 222 | self.label1_frame.pack() 223 | self.pic1_frame = ttk.Frame(self.mainframe, width=640, height=480) 224 | self.pic1 = ttk.Label(self.pic1_frame) 225 | self.pic1.place(x=0, y=0) 226 | self.pic1_frame.pack() 227 | self.scale1_frame = ttk.Frame(self.mainframe, width=529, height=30) 228 | self.scale1 = ttk.Scale(self.scale1_frame, from_=21, to=100, value=21, command=self.drawImage) 229 | self.scale1.place(x=0, y=0) 230 | self.scale1_frame.pack() 231 | self.label2_frame = ttk.Frame(self.mainframe, width=209, height=27) 232 | self.label2_str = tk.StringVar(value='start point: x = 2.1') 233 | self.label2 = ttk.Label(self.label2_frame, textvariable=self.label2_str) 234 | self.label2.place(x=0, y=0) 235 | self.label2_frame.pack() 236 | self.mainframe.pack() 237 | 238 | ### 功能逻辑部分 ### 239 | def drawImage(self, *args): 240 | start = self.scale1.get() 241 | x = np.linspace(start, start+50, 50) 242 | x = x / 10 243 | self.label2_str.set('start point: x = {0}'.format(start/10)) 244 | y = np.sin(x) / np.log(x) 245 | plt.clf() 246 | plt.plot(x, y, 'b') 247 | buff = BytesIO() 248 | plt.savefig(buff) 249 | buff.seek(0) 250 | im = Image.open(buff) 251 | image = ImageTk.PhotoImage(im) 252 | self.pic1.image = image 253 | self.pic1.configure(image=image) 254 | 255 | 256 | 257 | 258 | root = tk.Tk() 259 | 260 | sa = SA(root) 261 | sa.drawImage() 262 | root.mainloop() 263 | ``` 264 | 265 | -------------------------------------------------------------------------------- /Test/main.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | /*DSG{{*/ 3 | mainForm = win.form(text="Window Title";right=879;bottom=541) 4 | mainForm.add( 5 | btnFinish={cls="button";text="完 成";left=529;top=490;right=711;bottom=521;font=LOGFONT(h=-19;weight=700);z=10}; 6 | btnRandom={cls="button";text="随机选题";left=745;top=44;right=854;bottom=71;z=7}; 7 | btnSelect={cls="button";text="指定选题";left=624;top=44;right=733;bottom=71;z=8}; 8 | btnSubmit={cls="button";text="提 交";left=135;top=490;right=317;bottom=521;font=LOGFONT(h=-19;weight=700);z=9}; 9 | edit={cls="edit";left=26;top=76;right=857;bottom=422;edge=1;font=LOGFONT(h=-19;name='Consolas');multiline=1;vscroll=1;z=2}; 10 | rA={cls="radiobutton";text="A";left=21;top=441;right=197;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=3}; 11 | rB={cls="radiobutton";text="B";left=244;top=441;right=420;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=4}; 12 | rC={cls="radiobutton";text="C";left=467;top=441;right=643;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=5}; 13 | rD={cls="radiobutton";text="D";left=690;top=441;right=866;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=6}; 14 | static={cls="static";text="Python习题集";left=22;top=15;right=198;bottom=46;color=16711680;font=LOGFONT(h=-21;name='微软雅黑';weight=700);transparent=1;z=1} 15 | ) 16 | /*}}*/ 17 | 18 | import console; 19 | import GUI2Py; 20 | g2t = GUI2Py.GUI2Tk(mainForm); 21 | g2t.transfer2place('Calib'); 22 | 23 | namestr = g2t.translateName(` 24 | btnFinish={cls="button";text="完 成";left=529;top=490;right=711;bottom=521;font=LOGFONT(h=-19;weight=700);z=10}; 25 | btnRandom={cls="button";text="随机选题";left=745;top=44;right=854;bottom=71;z=7}; 26 | btnSelect={cls="button";text="指定选题";left=624;top=44;right=733;bottom=71;z=8}; 27 | btnSubmit={cls="button";text="提 交";left=135;top=490;right=317;bottom=521;font=LOGFONT(h=-19;weight=700);z=9}; 28 | edit={cls="edit";left=26;top=76;right=857;bottom=422;edge=1;font=LOGFONT(h=-19;name='Consolas');multiline=1;vscroll=1;z=2}; 29 | rA={cls="radiobutton";text="A";left=21;top=441;right=197;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=3}; 30 | rB={cls="radiobutton";text="B";left=244;top=441;right=420;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=4}; 31 | rC={cls="radiobutton";text="C";left=467;top=441;right=643;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=5}; 32 | rD={cls="radiobutton";text="D";left=690;top=441;right=866;bottom=468;color=8388608;font=LOGFONT(h=-19;name='微软雅黑');z=6}; 33 | static={cls="static";text="Python习题集";left=22;top=15;right=198;bottom=46;color=16711680;font=LOGFONT(h=-21;name='微软雅黑';weight=700);transparent=1;z=1} 34 | `) 35 | 36 | console.log(namestr); 37 | 38 | string.save("/res/demo.py", g2t.pycode); 39 | 40 | mainForm.show(); 41 | return win.loopMessage(); -------------------------------------------------------------------------------- /Test/test.py: -------------------------------------------------------------------------------- 1 | import tkinter as tk 2 | from tkinter.messagebox import showinfo 3 | import tkinter.ttk as ttk 4 | import tkinter.font as tkFont 5 | from random import randint 6 | 7 | TM = { 8 | 1 : { 9 | 'ques' : "1 + 1 = ?", 10 | 'ra' : "1", 11 | 'rb' : "2", 12 | 'rc' : "3", 13 | 'rd' : "4", 14 | 'ans' : "2" 15 | 16 | }, 17 | 18 | 2 : { 19 | 'ques' : "2 + 2 = ?", 20 | 'ra' : "4", 21 | 'rb' : "3", 22 | 'rc' : "2", 23 | 'rd' : "1", 24 | 'ans' : "4" 25 | 26 | }, 27 | } 28 | 29 | class Tiku(): 30 | ### 界面设计部分 ### 31 | 32 | def __init__(self, master): 33 | # global Var 34 | self.radioSelect = tk.IntVar() 35 | self.num = 0 36 | self.total = 0 37 | self.correct = 0 38 | 39 | self.mainframe = ttk.Frame(master, width=896, height=581) 40 | # Z=3 41 | self.rA_frame = ttk.Frame(width=176, height=27) 42 | self.rA = ttk.Radiobutton(self.rA_frame, text="A", value=1, variable=self.radioSelect) 43 | self.rA.place(x=0, y=0, width=176, height=27) 44 | self.rA_frame.place(x=21, y=441) 45 | # Z=1 46 | self.label1_frame = ttk.Frame(width=176, height=31) 47 | self.label1 = ttk.Label(self.label1_frame, text="Python习题集", justify="left") 48 | self.label1.place(x=0, y=0, width=176, height=31) 49 | self.label1_font = tkFont.Font(family="微软雅黑", size=16, weight="bold", slant="roman", underline=False) 50 | self.label1.configure(font=self.label1_font) 51 | self.label1.config(foreground="#0000FF") 52 | self.label1_frame.place(x=22, y=15) 53 | # Z=2 54 | self.editVar1 = tk.StringVar(value="") 55 | self.edit1_frame = ttk.Frame(width=831, height=346) 56 | self.edit1 = tk.Text(self.edit1_frame) 57 | self.edit1.insert("end", "") 58 | self.edit1.place(x=0, y=0, width=831, height=346) 59 | self.edit1_vscroll = tk.Scrollbar(self.edit1, orient="vertical", command=self.edit1.yview) 60 | self.edit1.configure(yscrollcommand=self.edit1_vscroll.set) 61 | self.edit1_vscroll.pack(side="right", fill="y") 62 | self.edit1_font = tkFont.Font(family="Consolas", size=14, weight="normal", slant="roman", underline=False) 63 | self.edit1.configure(font=self.edit1_font) 64 | self.edit1_frame.place(x=26, y=76) 65 | # Z=5 66 | self.rC_frame = ttk.Frame(width=176, height=27) 67 | self.rC = ttk.Radiobutton(self.rC_frame, text="C", value=3, variable=self.radioSelect) 68 | self.rC.place(x=0, y=0, width=176, height=27) 69 | self.rC_frame.place(x=467, y=441) 70 | # Z=4 71 | self.rB_frame = ttk.Frame(width=176, height=27) 72 | self.rB = ttk.Radiobutton(self.rB_frame, text="B", value=2, variable=self.radioSelect) 73 | self.rB.place(x=0, y=0, width=176, height=27) 74 | self.rB_frame.place(x=244, y=441) 75 | # Z=8 76 | self.btnSelect_frame = ttk.Frame(width=109, height=27) 77 | self.btnSelect = ttk.Button(self.btnSelect_frame, text="指定选题", command=self.selectquestion) 78 | self.btnSelect.place(x=0, y=0, width=109, height=27) 79 | self.btnSelect_frame.place(x=624, y=44) 80 | # Z=7 81 | self.btnRandom_frame = ttk.Frame(width=109, height=27) 82 | self.btnRandom = ttk.Button(self.btnRandom_frame, text="随机选题", command=self.randquestion) 83 | self.btnRandom.place(x=0, y=0, width=109, height=27) 84 | self.btnRandom_frame.place(x=745, y=44) 85 | # Z=10 86 | self.btnFinish_frame = ttk.Frame(width=182, height=31) 87 | self.btnFinish = ttk.Button(self.btnFinish_frame, text="完 成", command=self.finish) 88 | self.btnFinish.place(x=0, y=0, width=182, height=31) 89 | self.btnFinish_frame.place(x=529, y=490) 90 | # Z=6 91 | self.rD_frame = ttk.Frame(width=176, height=27) 92 | self.rD = ttk.Radiobutton(self.rD_frame, text="D", value=4, variable=self.radioSelect) 93 | self.rD.place(x=0, y=0, width=176, height=27) 94 | self.rD_frame.place(x=690, y=441) 95 | # Z=9 96 | self.btnSubmit_frame = ttk.Frame(width=182, height=31) 97 | self.btnSubmit = ttk.Button(self.btnSubmit_frame, text="提 交", command=self.answer) 98 | self.btnSubmit.place(x=0, y=0, width=182, height=31) 99 | self.btnSubmit_frame.place(x=135, y=490) 100 | 101 | self.editVar2 = tk.StringVar(value="") 102 | self.edit2_frame = ttk.Frame(width=50, height=27) 103 | self.edit2 = tk.Entry(self.edit2_frame, textvariable=self.editVar2) 104 | self.edit2.place(x=0, y=0) 105 | self.edit2_frame.place(x=550, y=44) 106 | self.mainframe.pack() 107 | 108 | ### 功能逻辑部分 ### 109 | 110 | def selectquestion(self): 111 | n = self.editVar2.get() 112 | n = int(n) 113 | self.num = n 114 | self.edit1.delete(0.0, 'end') 115 | self.edit1.insert("end", TM[n]['ques']) 116 | self.rA.configure(text=TM[n]['ra']) 117 | self.rB.configure(text=TM[n]['rb']) 118 | self.rC.configure(text=TM[n]['rc']) 119 | self.rD.configure(text=TM[n]['rd']) 120 | 121 | def randquestion(self): 122 | n = randint(1, len(TM)) 123 | self.num = n 124 | self.edit1.delete(0.0, 'end') 125 | self.edit1.insert("end", TM[n]['ques']) 126 | self.rA.configure(text=TM[n]['ra']) 127 | self.rB.configure(text=TM[n]['rb']) 128 | self.rC.configure(text=TM[n]['rc']) 129 | self.rD.configure(text=TM[n]['rd']) 130 | 131 | def answer(self): 132 | ans = self.radioSelect.get() 133 | if ans == 1: ans = 'ra' 134 | if ans == 2: ans = 'rb' 135 | if ans == 3: ans = 'rc' 136 | if ans == 4: ans = 'rd' 137 | if TM[self.num]['ans'] == TM[self.num][ans]: 138 | self.correct += 1 139 | self.total += 1 140 | self.randquestion() 141 | m = tk.Tk() 142 | m.geometry('300x50+800+400') 143 | msg = tk.Message(m, text="Correct!", width=300) 144 | msg.pack() 145 | m.resizable(width=False, height=False) 146 | m.mainloop() 147 | else: 148 | self.total += 1 149 | m = tk.Tk() 150 | m.geometry('300x50+800+400') 151 | msg = tk.Message(m, text="Wrong!", width=300) 152 | msg.pack() 153 | m.resizable(width=False, height=False) 154 | m.mainloop() 155 | 156 | def finish(self): 157 | m = tk.Tk() 158 | m.geometry('300x50+800+400') 159 | msg = tk.Message(m, text=f'Total: {self.total}\nCorrect: {self.correct}\nScore: {int((self.correct/self.total)*100)}', width=300) 160 | self.total = 0 161 | self.correct = 0 162 | self.randquestion() 163 | msg.pack() 164 | m.resizable(width=False, height=False) 165 | m.mainloop() 166 | 167 | 168 | root = tk.Tk() 169 | tiku = Tiku(root) 170 | root.title("Python习题集 v0.0.1") 171 | root.resizable(width=False, height=False) 172 | root.mainloop() 173 | -------------------------------------------------------------------------------- /main.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | /*DSG{{*/ 3 | mainForm = win.form(text="Window Title";right=596;bottom=383) 4 | mainForm.add( 5 | button2={cls="button";text="Button";left=242;top=261;right=369;bottom=293;z=3}; 6 | edit2={cls="edit";text="Text";left=217;top=117;right=399;bottom=234;edge=1;multiline=1;z=2}; 7 | static2={cls="static";text="Hello, Python!";left=218;top=74;right=373;bottom=103;transparent=1;z=1} 8 | ) 9 | /*}}*/ 10 | 11 | import console; 12 | console.open(); 13 | 14 | import GUI2Py; 15 | g2t = GUI2Py.GUI2Tk(mainForm); 16 | code = g2t.transfer2root(); 17 | mainForm.edit2.text = code; 18 | 19 | console.log(code); 20 | 21 | mainForm.show(); 22 | return win.loopMessage(); 23 | --------------------------------------------------------------------------------