====== tkinter ======
===== links =====
Basics: https://likegeeks.com/python-gui-examples-tkinter-tutorial/
Layout: https://zetcode.com/tkinter/layout/
grid: https://blog.tecladocode.com/tkinters-grid-geometry-manager/
Mixed layout: https://stackoverflow.com/a/38154650/15030988
Radiobutton Gruppen:
https://riptutorial.com/tkinter/example/30286/create-a-group-of-radiobuttons
https://stackoverflow.com/a/47162318/15030988
Buttons mit gemeinsamer click-Funktion: https://stackoverflow.com/a/6921225/15030988
MessageBox: https://docs.python.org/3/library/tkinter.messagebox.html
Neues Fenster: https://www.delftstack.com/de/howto/python-tkinter/how-to-create-a-new-window-with-a-button-in-tkinter/
===== Bildschirmgröße =====
* winfo_screenwidth()
* winfo_screenheight()
Fenster in Bildschirmmitte ausrichten: https://m.youtube.com/watch?v=gjU3Lx8XMS8
* X=(screenwidth-windowwidth)/2
* Y=(screenheight-windowheight)/2
die Position kann wie die Größe mit der geometry Methode gesetzt werden
root = Tk()
root.geometry("300x200+300+300") #WxH+X+Y
es kann auch nur die position verändert werden:
root.geometry("+10+10")
===== Fenster als Klasse =====
import tkinter as tk
class App:
def __init__(self, window):
window.geometry('350x200')
frame = tk.Frame(window)
frame.pack()
self.button = tk.Button(frame,
text="QUIT", fg="red",
command=frame.quit)
self.button.pack(side=tk.LEFT)
self.slogan = tk.Button(frame,
text="Hello",
command=self.write_slogan)
self.slogan.pack(side=tk.LEFT)
def write_slogan(self):
print("Tkinter is easy to use!")
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
root.mainloop()
alternativ kann man auch direkt von der tk.Tk-Klasse ableiten, somit muss das Fenster nicht extern erzeugt werden
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.geometry('350x200')
frame = tk.Frame(self)
...
Das sollte aber nur bei Anwendungen gemacht werden die nur 1 Fenster nutzen. Bei mehreren Fenstern sollte die Fenstererstellung außerhalb der Klasse und nur das Füllen des Fensters innerhalb ablaufen.
===== Texteingabe =====
hier wird ein neuer Frame erzeugt um die Scrollbars an der Textbox auszurichten
ggf. mainframe (Eltern-Element) und txt_frm.grid anpassen (ggf. pack o.ä.)
import tkinter as tk
class scrolltext(tk.Frame):
def __init__(self,parent,width,height):
tk.Frame.__init__(self, parent, width=width, height=height)
# ensure a consistent GUI size
self.grid_propagate(False)
# implement stretchability
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.txt = tk.Text(self, borderwidth=3, relief="sunken")
self.txt.config(undo=True, wrap='none')#word
self.txt.grid(row=0, column=0, sticky="nsew", padx=2, pady=2)
#create vertical scrollbar
self.vscrollb = tk.Scrollbar(self, command=self.txt.yview)
self.vscrollb.grid(row=0, column=1, sticky='nsew')
self.txt['yscrollcommand'] = self.vscrollb.set
#create horizontal scrollbar
self.hscrollb = tk.Scrollbar(self, orient='horizontal',command=self.txt.xview)
self.hscrollb.grid(row=1, column=0, sticky='nsew')
self.txt['xscrollcommand'] = self.hscrollb.set
def focus(self):
self.txt.focus()
def getText(self):
return self.txt.get("1.0", tk.END)
def setText(self,text):
self.txt.delete(1.0,"end")
self.txt.insert(1.0, text)
if __name__ == "__main__":
def clicked():
print(txt.getText().splitlines())
txt.setText("this is a special text")
window = tk.Tk()
window.geometry('350x200')
window.title("Welcome to LikeGeeks app")
txt=scrolltext(window, width=250,height=200)
txt.pack(side = tk.LEFT,fill=tk.BOTH,expand=1)
btn = tk.Button(window, text="Click Me", command=clicked)
btn.pack(side=tk.RIGHT)
txt.focus()
window.mainloop()
https://stackoverflow.com/a/9662139/15030988
Beispiel mit yscrollcommand und zeilenweisem auslesen: https://stackoverflow.com/a/17747230/15030988
Horizontale scrollbar: https://stackoverflow.com/a/47954818/15030988
===== treeview =====
https://riptutorial.com/tkinter/example/31880/treeview--basic-example
https://www.askpython.com/python-modules/tkinter/tkinter-treeview-widget
===== PanedWindow =====
ein PanedWindow is ein Container für mindestens 2 Widgets mit einer verschiebbaren Begrenzung.
m1 = tk.PanedWindow(window)
m1.pack(fill = tk.BOTH, expand = 1)
button = tk.Button(m1,text="QUIT", fg="red")
m1.add(button, stretch="always") #always richtet automatisch aus, danach sind alle Felder gleich groß
button2 = tk.Button(m1,text="Hello")
m1.add(button2, stretch="always")
#setzen des Schiebereglers (optional, falls always nicht richtig ist)
m1.update()
m1.sash_place(0,400,0) #x-position 400 des ersten Widgets
https://stackoverflow.com/a/62032595/15030988
https://stackoverflow.com/a/27389064/15030988
===== Notebook =====
tc = ttk.Notebook(master)
t1 = ttk.Frame(tc)
t2 = ttk.Frame(tc)
tc.add(t1, text ='Notebook tab1')
tc.add(t2, text ='Notebook tab2')
tc.pack(expand = 1, fill ="both")
https://www.educba.com/tkinter-notebook/
===== Beispiel-Gui =====
from tkinter import Tk, RIGHT, BOTH, RAISED,X,Y,IntVar,BooleanVar,StringVar
from tkinter import messagebox
from tkinter.ttk import Label, Frame, Button, Entry, Checkbutton,Radiobutton, Notebook, Treeview, Style
class Example():
def __init__(self,window):
self.window=window
self.initUI(window)
def initUI(self,window):
self.tc=Notebook(window)
self.t1 = Frame(self.tc)
self.t2 = Frame(self.tc)
self.t3 = Frame(self.tc)
self.tc.add(self.t1, text ='Tab1')
self.tc.add(self.t2, text ='Tab2')
self.tc.add(self.t3, text ='Tab3')
self.tc.pack(fill=BOTH, expand=True)
closeButton = Button(window, text="Close",command=window.destroy)
closeButton.pack(side=RIGHT, padx=5, pady=5)
okButton = Button(window, text="OK",command=lambda:messagebox.showinfo("OK pressed","Hello, you have successful pressed the OK-Button!\n\nEntry: %s CHK:%d RD:%s" % (self.e1.get(),self.chkvar1.get(),self.radvar1.get())))
okButton.pack(side=RIGHT)
mvButton = Button(window,text="move",command=lambda:window.geometry("+10+10"))
mvButton.pack(side=RIGHT)
self.filltabs()
def filltabs(self):
l1=Label(self.t1, text="Entry:")
l1.grid(row=0,column=0)
self.e1=Entry(self.t1)
self.e1.grid(row=0,column=1)
l2=Label(self.t1, text="Checkbutton:")
l2.grid(row=1,column=0)
self.chkvar1 = IntVar()
self.chkvar1.set(1)
c1=Checkbutton(self.t1, text='Choose', variable=self.chkvar1) #, onvalue=1,offvalue=0)
c1.grid(row=1,column=1,sticky="W") #left justify
l3=Label(self.t2,text="Radiobuttons")
l3.grid(row=0,column=0,sticky="N")
rf=Frame(self.t2)
rf.grid(row=0,column=1)
self.radvar1=StringVar()
r1=Radiobutton(rf, text="Python", variable=self.radvar1, value="python")
r1.pack(anchor="w") #untereinander linksbündig
r2=Radiobutton(rf, text="PHP", variable=self.radvar1, value="php")
r2.pack(anchor="w")
self.tree1=Treeview(self.t3, columns=("Name", "Data")) # causes WIndow be bigger and hides buttonframe
self.tree1.pack(fill=BOTH, expand=True)
self.tree1.insert(parent='', index='end', iid=0, text="root", values=("First Col", "Second Col"))
self.tree1.insert(parent=0, index='end', iid=1, text="child", values=("Hello", "Again"))
def main():
root = Tk()
root.geometry("400x300+300+300")
root.title("testwindow")
root.style = Style().theme_use("alt") # to show checkmarks in checkbutton and round radiobuttons
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()