ゴールデンウィークにTkinterで遊んだ話。もう1ヶ月経つのか。
ゴールデンウィークに入る前にTkinterでテキストエディタを作りたいって記事読んで、「あ、作ってみよう」と作った。
結果、xmlから表示するロジックは作った。
機能が抽象化しきってないし、汚いコードだけど吐き出しとく。
ところで、PythonでGUI用のフレームワークってないのかな?
<?xml version="1.0" encoding="UTF-8"?> <master title="サンプルアプリケーション" minsize="400, 300" maxsize="800, 600"> <menus> <menu type="cascade" label="ファイル(F)" name="menu_file" underline="5"> <menu type="command" label="新規作成(N)" name="new" underline="5" accelerator="Ctrl-N" /> <menu type="command" label="開く(O)" name="open" underline="5" accelerator="Ctrl-O" /> <menu type="command" label="保存(S)" name="save" underline="5" accelerator="Ctrl-S" /> <menu type="command" label="名前をつけて保存(A)" name="save_as" underline="5" accelerator="Ctrl-A" /> <menu type="separator" /> <menu type="command" label="閉じる(C)" name="close" underline="5" accelerator="Ctrl-C" /> <menu type="command" label="終了(X)" name="quit" underline="5" command="quit()" accelerator="Ctrl-X" /> </menu> <menu type="cascade" label="編集(E)" name="menu_edit" underline="5"> <menu type="command" label="元に戻す(U)" name="undo" underline="5" accelerator="Ctrl-U" /> <menu type="command" label="やり直す(R)" name="redo" underline="5" accelerator="Ctrl-R" /> <menu type="separator" /> <menu type="command" label="切り取り(T)" name="cut" underline="5" accelerator="Ctrl-T" /> <menu type="command" label="コピー(C)" name="copy" underline="5" accelerator="Ctrl-C" /> <menu type="command" label="貼り付け(P)" name="paste" underline="5" accelerator="Ctrl-P" /> <menu type="command" label="削除(D)" name="delete" underline="5" accelerator="Ctrl-D" /> </menu> <menu type="cascade" label="ヘルプ(H)" name="menu_help" underline="5" /> </menus> <text height="7" width="40" bg="white" fg="red" /> </master>
main.py
# -*- coding: utf-8 -*- from Tkinter import * import xml.dom from xml.dom.minidom import parse from xml.parsers.expat import ExpatError #FONT = (u'Helvetica', '10', 'normal') #FONT = (u'MS 明朝', '10', 'normal') FONT = (u'MS ゴシック', '10', 'normal') properties = ( # color options "activebackground", "activeforeground", "backgroud", "bg", "backgroud", "foreground", "fg", "highlightbackground", "highlightcolor", "selectbackground", "selectforeground", # length options "borderwidth", "highlightthickness", "padx", "pady", "selectborderwidth", "wraplength", # font options "height", "underline", "width", # other options "anchor", "command", "font", "image", "justify", "relief", "state", "takefocus", "text", "textvariable", ) class Reader(object): u"""Reader class.""" pass class JSONReader(Reader): u"""JSON Reader class.""" pass class XMLReader(Reader): u"""XML Reader""" def __init__(self, xml=None): Reader.__init__(self) self._dom = parse(xml) def dom(self): return self._dom class Application(Frame): u"""Application class.""" class AttributeDict(dict): u"""custom attribute class""" def __getattr__(self, name): return None def __init__(self, master=None): Frame.__init__(self, master) self.pack() def set(self): pass def set_master(self, dict): u"""set master value.""" self.master.title(dict.get("title", u'')) self.master.minsize(dict.get("minsize-x"), dict.get("minsize-y")) self.master.maxsize(dict.get("maxsize-x"), dict.get("maxsize-y")) def create_menus(self, element): u"""create menus.""" values = self.attribute(element) if values.get("type") == "cascade": exec """self.%(menu_name)s = Menu(self.menu_bar, tearoff=%(tearoff)s)""" % dict( menu_name=values.get("name", 0), tearoff=values.get("tearoff", 0), ) exec """self.menu_bar.add_cascade(label=u"%(label)s", menu=self.%(menu_name)s, underline=%(underline)s, accelerator="%(accelerator)s", font=%(font)s)""" % dict( menu_name=values.get("name", 0), label=values.get("label", ""), underline=values.get("underline", 0), accelerator=values.get("accelerator", ""), font=FONT, ) for node in element.childNodes: if node.nodeType == xml.dom.Node.ELEMENT_NODE: self.create_menu(node, parent_name=values.get("name")) else: raise ValueError("element type cascade isn't exist.") class XMLApplication(Application): u"""xml file based Application class.""" def set(self, file): self._dom = XMLReader(file).dom() masters = self._dom.getElementsByTagName("master") master = masters[0] key = self.attribute(master) self.set_master(key) # menu self.menu_bar = Menu(self, tearoff=0) for element in self._dom.getElementsByTagName('menus'): for node in element.childNodes: if node.nodeType == xml.dom.Node.ELEMENT_NODE: self.create_menus(node) # add menu bar try: self.master.config(menu=self.menu_bar) # this required to show the menu bar except AttributeError: self.master.Tk.call(self.master, "config", "-menu", self.menu_bar) if __name__ == '__main__': application = XMLApplication() application.set("templates/gui.xml") application.mainloop()