I'm making my first GUI application and I've run into a silly problem. Resizing the main window doesn't resize its contents and leaves blank space. I've read the TKDocs and they only say you should use sticky and column/row weight attributes but I don't really understand how they work.
Here's my code (only the part covering widgets, if you think problem isn't here I'll post the rest of it):
from tkinter import *
from tkinter import ttk
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
player1 = StringVar()
player2 = StringVar()
player1.set('Player 1')
player2.set('Player 1')
timer=StringVar()
running=BooleanVar()
running.set(0)
settimer = ttk.Entry(mainframe, width=7, textvariable=timer)
settimer.grid(column=2, row=1, sticky=(N, S))
ttk.Button(mainframe, text="Start", command=start).grid(column=2, row=2, sticky=(N, S))
ttk.Label(mainframe, textvariable=player1, font=TimeFont).grid(column=1, row=3, sticky=(W, S))
ttk.Label(mainframe, textvariable=player2, font=TimeFont).grid(column=3, row=3, sticky=(E, S))
for child in mainframe.winfo_children():
child.grid_configure(padx=80, pady=10)
root.mainloop()
Thanks for your time!
Maybe this will help you in the right direction. Be sure to configure column/row weights at each level.
import tkinter.ttk
from tkinter.constants import *
class Application(tkinter.ttk.Frame):
#classmethod
def main(cls):
tkinter.NoDefaultRoot()
root = tkinter.Tk()
app = cls(root)
app.grid(sticky=NSEW)
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
root.resizable(True, False)
root.mainloop()
def __init__(self, root):
super().__init__(root)
self.create_variables()
self.create_widgets()
self.grid_widgets()
self.grid_columnconfigure(0, weight=1)
def create_variables(self):
self.player1 = tkinter.StringVar(self, 'Player 1')
self.player2 = tkinter.StringVar(self, 'Player 2')
self.timer = tkinter.StringVar(self)
self.running = tkinter.BooleanVar(self)
def create_widgets(self):
self.set_timer = tkinter.ttk.Entry(self, textvariable=self.timer)
self.start = tkinter.ttk.Button(self, text='Start', command=self.start)
self.display1 = tkinter.ttk.Label(self, textvariable=self.player1)
self.display2 = tkinter.ttk.Label(self, textvariable=self.player2)
def grid_widgets(self):
options = dict(sticky=NSEW, padx=3, pady=4)
self.set_timer.grid(column=0, row=0, **options)
self.start.grid(column=0, row=1, **options)
self.display1.grid(column=0, row=2, **options)
self.display2.grid(column=0, row=3, **options)
def start(self):
timer = self.timer.get()
self.player1.set(timer)
self.player2.set(timer)
if __name__ == '__main__':
Application.main()
Related
I'm initiating in ttk and I keep getting this error while trying to add a LabelFrame inside a PanedWindow. Happens on line 46 (self.pwEntries.add(self.lfEntries)):
_tkinter.TclError: wrong # args: should be ".!frame.!panedwindow.!panedwindow add window"
As I've no idea how to solve it I would really appreciate some help, please...
My code goes like this:
from tkinter import *
from tkinter import ttk
class CalcVendGame:
def __init__(self, root):
root.title("Calcula Venda Games")
self.mainframe = ttk.Frame(root, padding="3 3 12 12")
self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
self.pwRoot = ttk.PanedWindow(self.mainframe, orient=VERTICAL)
self.pwEntries = ttk.PanedWindow(self.pwRoot, orient=HORIZONTAL)
self.lfEntries = ttk.LabelFrame(self.pwEntries, labelanchor='nw').grid(
column=0, row=0, sticky=(N, W))
ttk.Label(self.lfEntries, text="Valor em Dólar de cada cópia:", padding="5").grid(
column=2, row=1, sticky=E)
self.CopiaEmDolar = StringVar()
cpEmDol_entry = ttk.Entry(
self.lfEntries, width=7, textvariable=self.CopiaEmDolar)
cpEmDol_entry.grid(column=3, row=1, sticky=W)
ttk.Label(self.lfEntries, text="Ex: \"19.99\"", padding="5").grid(
column=4, row=1, sticky=W)
ttk.Label(self.lfEntries, text="Quantidade de cópias vendidas:", padding="5").grid(
column=2, row=2, sticky=E)
self.CopiasVendidas = StringVar()
cpVend_entry = ttk.Entry(
self.lfEntries, width=7, textvariable=self.CopiasVendidas)
cpVend_entry.grid(column=3, row=2, sticky=W)
ttk.Button(self.lfEntries, text="Calcular").grid(
column=4, row=3, sticky=W)
self.pwEntries.add(self.lfEntries)
self.pwPC = ttk.PanedWindow(self.pwRoot, orient=HORIZONTAL)
self.pwSteam = ttk.PanedWindow(self.pwPC, orient=VERTICAL)
self.lfSteam = ttk.LabelFrame(self.pwSteam, padding=(
5), text='Steam', labelanchor='nw')
ttk.Label(self.lfSteam, text="Cut 35%", padding="5").grid(
column=0, row=0, sticky=W)
ttk.Separator(self.lfSteam, orient=HORIZONTAL)
self.pwPatreon = ttk.PanedWindow(self.pwRoot, orient=VERTICAL)
self.pwPC.add(self.pwSteam)
self.pwPC.add(self.pwPatreon)
self.pwMobile = ttk.PanedWindow(self.pwRoot, orient=HORIZONTAL)
# self.pwRoot.add(self.lfEntries)
self.pwRoot.add(self.pwEntries)
self.pwRoot.add(self.pwPC)
self.pwRoot.add(self.pwMobile)
root = Tk()
CalcVendGame(root)
root.mainloop()
Also, this code give me no errors but results on a blank window:
from tkinter import *
from tkinter import ttk
master = Tk()
mainframe = ttk.Frame(master, padding="3 3 10 10")
p = ttk.Panedwindow(mainframe, orient=VERTICAL)
# two panes, each of which would get widgets gridded into it:
f1 = ttk.Labelframe(p, text='Pane1', width=100, height=100)
ttk.Label(f1, text="Valor em Dólar de cada cópia:", padding="5")
f2 = ttk.Labelframe(p, text='Pane2', width=100, height=100)
ttk.Label(f2, text="Quantidade de cópias vendidas:", padding="5")
p.add(f1)
p.add(f2)
master.mainloop()
You forgot to use any layout manager on the widgets. Below is an updated code using pack():
from tkinter import *
from tkinter import ttk
master = Tk()
mainframe = ttk.Frame(master, padding="3 3 10 10")
mainframe.pack()
p = ttk.Panedwindow(mainframe, orient=VERTICAL)
p.pack()
# two panes, each of which would get widgets gridded into it:
f1 = ttk.Labelframe(p, text='Pane1', width=100, height=100)
ttk.Label(f1, text="Valor em Dólar de cada cópia:", padding="5").pack()
f2 = ttk.Labelframe(p, text='Pane2', width=100, height=100)
ttk.Label(f2, text="Quantidade de cópias vendidas:", padding="5").pack()
p.add(f1)
p.add(f2)
master.mainloop()
I'm new using Tkinter, I already have this problem, I was thinking the problem was the column and row configure, but that doesn't change anything.
This is what I get:
This is my code:
class Application(Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.grid()
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(1, weight=1)
self.grid_rowconfigure(2, weight=1)
self.grid_rowconfigure(3, weight=1)
self.grid_rowconfigure(4, weight=1)
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
self.create_widgets()
def create_widgets(self):
self.label = Label(self, justify=LEFT)
self.label["text"] = "Número:"
self.label.grid(column=0, row=0, sticky="e")
self.input = Entry(self)
self.input.grid(column=1, row=0, sticky="we")
self.baseValue = StringVar()
self.baseValue.set(basesNames[0]) # default value
self.label2 = Label(self)
self.label2["text"] = "Base:"
self.label2.grid(column=0, row=1, sticky="e")
self.menuNumber = ttk.Combobox(self, textvariable=self.baseValue)
self.menuNumber['values'] = basesNames
self.menuNumber.grid(column=1, row=1)
self.label2 = Label(self)
self.label2["text"] = "Base de resultado: "
self.label2.grid(column=0, row=2, sticky="e")
self.baseValueResult = StringVar()
self.baseValueResult.set(basesNames[0]) # default value
self.menuNumberResult = ttk.Combobox(self, textvariable=self.baseValueResult)
self.menuNumberResult['values'] = basesNames
self.menuNumberResult.grid(column=1, row=2)
self.convert = ttk.Button(self, text="Convertir", command=self.convertNumber)
self.convert.grid(row = 4, columnspan=2, sticky="sn")
self.result = Label(self)
self.result["text"] = "Your result is: "
self.result.grid(row=3, columnspan=2, sticky="ew")
root = Tk()
app = Application(master=root)
app.master.title("Conversor de bases")
app.master.maxsize(1000, 400)
app.mainloop()
Also, I checked if the sticky param was necessary but that doesn't change neither
Your widgets are wrapped inside the frame Application. So you need to make the frame expands as well.
from tkinter import *
from tkinter import ttk
basesNames = ["a","b","c","d","e"]
class Application(Frame):
def __init__(self, master=None):
...
root = Tk()
app = Application(master=root)
app.master.title("Conversor de bases")
app.master.maxsize(1000, 400)
root.rowconfigure(0,weight=1)
root.columnconfigure(0,weight=1)
root.mainloop()
I have implemented a code to make GUI using Tkinter and I'm new in this. The problem which I'm facing is that there is lots of spacing between two buttons in column 3 ( select object and play button).
I want to know that why this is happening.
my code is here:
from tkinter import Tk, Text, BOTH, W, N, E, S
from tkinter.ttk import Frame, Button, Label, Style
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Nav Track app")
self.pack(fill=BOTH, expand=True)
self.style = Style()
self.style.theme_use("default")
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
lbl = Label(self, text="Keep your eyes on screen")
lbl.grid(sticky=W, pady=4, padx=5)
area = Text(self)
area.grid(row=1, column=0, columnspan=2, rowspan=5,
padx=8, sticky=E + W + S + N)
abtn = Button(self, text="Start Camera")
abtn.grid(row=1, column=3, padx=4)
cbtn = Button(self, text="Select Object")
cbtn.grid(row=2, column=3, padx=4, pady=4)
dbtn = Button(self, text="Play")
dbtn.grid(row=3, column=3, padx=4, pady=4)
hbtn = Button(self, text="Help")
hbtn.grid(row=7, column=0, padx=5)
obtn = Button(self, text="Exit")
obtn.grid(row=7, column=3)
def main():
root = Tk()
root.geometry("500x450+300+500")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()
My program creates different widgets depending on the selection from a radio button. Everything works great except I can't seem to clear the old widget if the other radio button is selected. The suggestion here: (https://stackoverflow.com/a/15995920/3924118) isn't working. Here's the relevant code.
From the main program:
root = Tk()
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
secondframe = ttk.Frame(mainframe)
secondframe.grid(column=4, row=3)
secondframe.columnconfigure(0, weight=1)
secondframe.columnconfigure(0, weight=1)
And then the function:
def pct_from_duration():
""" Calculate needed pct from target duration"""
tgt_dur_entry = ttk.Entry(mainframe, width=4, textvariable=tgt_dur_inp)
tgt_dur_entry.grid(column=5, row=3, sticky=(W, E))
for widget in secondframe.winfo_children():
widget.destroy()
ttk.Label(secondframe, textvariable=pct_bond_end).grid(column=1, row=1)
ttk.Button(mainframe, text="Calculate", command=calculate).grid(column=5, row=4, sticky=W)
FWIW, I get no error message, it just doesn't actually delete the widgets. This is all python 3.6.
Maybe this will help...I'ts an example of your function and it is working(Python 3.5)
import tkinter as tk
from tkinter import *
from tkinter import ttk
class GUI:
def __init__(self, master):
def pct_from_duration():
tgt_dur_entry = ttk.Entry(mainframe, width=4)
tgt_dur_entry.grid(column=5, row=3, sticky=(W, E))
for widget in secondframe.winfo_children():
widget.destroy()
l3 = ttk.Label(secondframe, text = 'Label').grid(column=1, row=1)
b2 = ttk.Button(mainframe, text="Calculate").grid(column=5, row=4, sticky=W)
self.master = master
mainframe = ttk.Frame(master)
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
secondframe = ttk.Frame(mainframe)
secondframe.grid(column=4, row=3)
secondframe.columnconfigure(0, weight=1)
secondframe.columnconfigure(0, weight=1)
l = Label(secondframe, text = 'Child_mainframe')
l.grid()
l2 = Label(mainframe, text = 'Child_secondframe')
l2.grid()
r1 = Radiobutton(master, text="Radiobutton", value=1, command = pct_from_duration).grid()
root = Tk()
root.rowconfigure(0, weight = 1)
root.columnconfigure(1, weight=1)
root.columnconfigure(0, weight=1)
root.columnconfigure(0, weight=2)
my_gui = GUI(root)
root.mainloop()
After tinkering around with tkinter I can't seem to make my window look
quite how I want it to look. But overall, I'm not sure what the File Edit View
layout is referred to. Is this is a toolbar or a menu?
So far my gui looks much less native osx than I would like. Should I just ditch
tkinter all together?
Does anyone have a code snipped that gives the general osx layout? That would be a big help.
Maybe I'm just not grasping the gui programming aspect conceptually.
thanks
I want to add menus to the following code
from tkinter import *
from tkinter import ttk
def undef(*args):
pass
def undef2(*args):
pass
root = Tk()
root.title("KDM Checker Beta ")
mainframe = ttk.Frame(root, padding="5 5 5 5")
mainframe.grid(column=12, row=12, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
countryvar = StringVar()
country = ttk.Combobox(mainframe, textvariable=countryvar)
country['values'] = ('dolby', 'sony', 'doremi')
country.grid(column=1, row = 1)
DATE = StringVar()
VENUE = StringVar()
UUID = StringVar()
SERVER_SERIAL = StringVar()
DATE_entry = ttk.Entry(mainframe, width=8, textvariable=DATE)
DATE_entry.grid(column=3, row=4, sticky=(W, E))
VENUE_entry = ttk.Entry(mainframe, width=8, textvariable=VENUE)
VENUE_entry.grid(column=3, row=8, sticky=(W, E))
UUID_entry = ttk.Entry(mainframe, width=8, textvariable=UUID)
UUID_entry.grid(column=3, row=16, sticky=(W, E))
state = StringVar()
mount = ttk.Radiobutton(mainframe, text='dolby', variable=state, value='dolby')
ttk.Label(mainframe, textvariable=DATE).grid(column=1, row=4, sticky=(W, E))
ttk.Label(mainframe, textvariable=VENUE).grid(column=1, row=8, sticky=(W, E))
ttk.Label(mainframe, textvariable=UUID).grid(column=1, row=16, sticky=(W, E))
ttk.Label(mainframe, text="KDM Window").grid(column=1, row=4, sticky=E)
ttk.Label(mainframe, text="Venue").grid(column=1, row=8, sticky=E)
ttk.Label(mainframe, text="UUID").grid(column=1, row=16, sticky=E)
for child in mainframe.winfo_children(): child.grid_configure(padx=3, pady=9)
DATE_entry.focus()
root.bind('<Return>', undef)
root.mainloop()
To create a menubar you need to create an instance of the Menu class, then use it as the value of the menubar attribute of your main application. From there you can create other menus and attach them to the menubar with add_cascade.
For example:
import tkinter as tk
import sys
class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._create_menubar()
self.text = tk.Text()
self.text.pack(side="top", fill="both", expand=True)
def _create_menubar(self):
# create a menu for the menubar and associate it
# with the window
self.menubar = tk.Menu()
self.configure(menu=self.menubar)
# create a File menu and add it to the menubar
file_menu = tk.Menu(self.menubar, tearoff=False)
self.menubar.add_cascade(label="File", menu=file_menu)
file_menu.add_command(label="Quit", command=self.on_quit)
# create a Edit menu and add it to the menubar
edit_menu = tk.Menu(self.menubar, tearoff=False)
self.menubar.add_cascade(label="Edit", menu=edit_menu)
edit_menu.add_command(label="Cut", underline=2, command=self.on_cut)
edit_menu.add_command(label="Copy", underline=0, command=self.on_copy)
edit_menu.add_command(label="Paste", underline=0, command=self.on_paste)
# create a View menu and add it to the menubar
view_menu = tk.Menu(self.menubar, tearoff=False)
self.menubar.add_cascade(label="View", menu=view_menu)
view_menu.add_cascade(label="Whatever", command=self.on_whatever)
def log(self, s):
self.text.insert("end", s + "\n")
self.text.see("end")
# not good programming style, but I'm trying to keep
# the example short
def on_cut(self): self.log("cut...")
def on_copy(self): self.log("copy...")
def on_paste(self): self.log("paste...")
def on_quit(self): sys.exit(0)
def on_whatever(self): self.log("whatever...")
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()