I decided to make a GUI application with Python, and it was quick to use Tkinter, so this is a memorandum for the next use.
import Tkinter as Tk
class Application(Tk.Frame):
def __init__(self, master=None):
Tk.Frame.__init__(self, master)
self.pack()
root = Tk.Tk()
app = Application(master=root)
app.mainloop()
Various widgets will be attached here.
Widget[^1]
name | role |
---|---|
Button | button |
Canvas | Paste and draw images |
Checkbutton | Check button |
Entry | One-line text area. Multiple lines are Text |
Frame | A frame that holds other widgets together |
Label | label. Images can also be displayed |
Listbox | list box |
Menu | Creating a menu bar |
Message | Multi-line label |
OptionMenu | combo box |
Radiobutton | Radio buttons |
Scale | slider |
Scrollbar | scroll bar |
Text | Multi-line text area |
Toplevel | For making pop-up windows etc. |
[^ 1]: Not all are covered
Use one of the pack, place, and grid methods to place the widget. pack arranges widgets in one column or one line. place specifies the location of each widget and places it. grid arranges widgets on 2D coordinates (it looks like Excel graph paper). After that, we basically use grid.
def __init__(self, master=None):
#abridgement
self.create_widgets()
def create_widgets(self):
self.label = Tk.Label(self, text=u'Input file')
self.entry = Tk.Entry(self)
self.button = Tk.Button(self, text=u'open')
self.check = Tk.Checkbutton(self, text=u'Limited extension to txt')
self.text = Tk.Text(self)
self.label.grid(column=0, row=0)
self.entry.grid(column=1, row=0)
self.button.grid(column=2, row=0)
self.check.grid(column=0, row=1)
self.text.grid(column=0, columnspan=3, row=2)
First, set expand, fill, and anchor to make the parent frame compatible with expansion and contraction. The position of Tk.XX that appears with anchor and sticky described later can be specified by north, south, east and west (NSEW).
def __init__(self, master=None):
Tk.Frame.__init__(self, master)
self.pack(expand=1, fill=Tk.BOTH, anchor=Tk.NW)
self.create_widgets()
Then, when arranging each widget with grid, specify where to expand and contract with sticky. Another important thing is that when you place a widget with grid, you need to specify which row / column expands and contracts at what ratio with column configure and row configure. By default, the weight parameter is 0 (does not stretch), so simply set the weight of the row / column you want to stretch to 1. In the following example, only the second line with Text corresponds to the expansion and contraction of the first column with Entry that is supposed to contain the selected file name.
self.label.grid(column=0, row=0, sticky=Tk.W)
self.entry.grid(column=1, row=0, sticky=Tk.EW)
self.button.grid(column=2, row=0, sticky=Tk.E)
self.check.grid(column=0, columnspan=2, row=1, sticky=Tk.W)
self.text.grid(column=0, columnspan=3, row=2, sticky=Tk.NSEW)
self.columnconfigure(1, weight=1)
self.rowconfigure(2, weight=1)
The contents of Entry and the check status of Checkbutton can be obtained by setting a variable in the (text) variable option.
self.var_entry = Tk.StringVar()
self.entry = Tk.Entry(self, textvariable=self.var_entry)
self.var_check = Tk.BooleanVar()
self.check = Tk.Checkbutton(self, text=u'Limited extension to txt',
variable=self.var_check)
Use set () and get () to set and get the values of Tk.StringVar () and Tk.BooleanVar ().
The method to be executed when the button is pressed is specified by the command option.
def create_widgets(self):
self.var_entry = Tk.StringVar()
self.entry = Tk.Entry(self, textvariable=self.var_entry)
self.button = Tk.Button(self, text=u'open', command=self.button_pushed)
def button_pushed(self):
self.var_entry.set(u'The button was pressed.')
To open the file dialog, import tkFileDialog and use askopenfilename. You can specify the file types by using the filetypes option. In addition, tkFileDialog includes askopenfile, askopenfiles, askopenfilenames, asksaveasfile, asksaveasfilename, askdirectory, etc.
import tkFileDialog as tkFD
def button_pushed(self):
ft = [('text files', '.txt')] if self.var_check.get() else []
self.var_entry.set(tkFD.askopenfilename(filetypes=ft))
To monitor a variable and call a method when it changes, use the trace method.
def create_widgets(self):
self.var_entry = Tk.StringVar()
self.var_entry.trace('w', self.entry_changed)
def entry_changed(self, *args):
if os.path.exists(self.var_entry.get()):
self.text.delete('1.0', Tk.END)
self.text.insert('1.0', open(self.var_entry.get()).read())
entry_changed is called when the value of var_entry is rewritten. First, erase all the contents of Text, and then display the contents of the file.
You can add a scroll bar to Text. [^ 2] There seems to be a widget called ScrolledText that has a vertical scroll bar from the beginning.
self.text = Tk.Text(self, wrap=Tk.NONE)
self.yscroll = Tk.Scrollbar(self, command=self.text.yview)
self.xscroll = Tk.Scrollbar(self, command=self.text.xview,
orient=Tk.HORIZONTAL)
self.text['yscrollcommand'] = self.yscroll.set
self.text['xscrollcommand'] = self.xscroll.set
self.text.grid(column=0, columnspan=3, row=2, rowspan=2, sticky=Tk.NSEW)
self.yscroll.grid(column=2, row=2, sticky=Tk.NS + Tk.E)
self.xscroll.grid(column=0, columnspan=3, row=3, sticky=Tk.EW + Tk.S)
[^ 2]: The intersection of the scroll bars, I feel like I can do a little more
It seems that Tkinter basically assumes gif. On the other hand, for example, savefig of matplotlib (pyplot) cannot save images as gif (isn't it?). So I converted it as follows and then pasted it, but is there a smarter way?
from PIL import Image
def create_widgets(self):
self.canvas = Tk.Canvas(self)
self.canvas.grid(column=0, columnspan=3, row=4, sticky=Tk.NSEW)
def set_image(self):
img = Image.open('foo.png')
img.save('_tmp.gif')
self.image_data = Tk.PhotoImage(file='_tmp.gif')
self.canvas.create_image(200, 100, image=self.image_data)
It's a copy and paste from stackoverflow. .. .. You can output the contents of standard output to Text etc.
import sys
def __init__(self, master=None):
Tk.Frame.__init__(self, master)
self.pack(expand=1, fill=Tk.BOTH, anchor=Tk.NW)
self.create_widgets()
sys.stdout = self.StdoutRedirector(self.text)
sys.stderr = self.StderrRedirector(self.text)
class IORedirector(object):
def __init__(self, text_area):
self.text_area = text_area
class StdoutRedirector(IORedirector):
def write(self, st):
self.text_area.insert(Tk.INSERT, st)
class StderrRedirector(IORedirector):
def write(self, st):
self.text_area.insert(Tk.INSERT, st)
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
It seems that Tkinter has been renamed to tkinter and tkFileDialog has been renamed to filedialog.
Recommended Posts