I need to center two buttons, and I may need to center more buttons, but I can't center more than one button, so I need help...
Here's the code:
from tkinter import *
from tkinter.ttk import *
import os
root = Tk()
root.geometry("325x100")
def click():
pass
def click2():
pass
button = Button(root, text="Button 1", command=click, width=25)
button.grid(row=0, column=0)
button2 = Button(root, text="Button 2", command=click2, width=25)
button2.grid(row=1, column=0)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
I did a bit of testing and here is what i have come up with. I have used the .pack() method instead of the .grid() method and i have also used a frame. I am kind of new to Python, but here it is :)
from tkinter import *
from tkinter.ttk import *
import os
root = Tk()
root.geometry("325x100")
def click():
pass
def click2():
pass
frame = Frame(root)
frame.pack(padx = 20, pady = 12)
button = Button(root, text="Button 1", command=click, width=25)
button.pack()
button2 = Button(root, text="Button 2", command=click2, width=25)
button2.pack()
root.mainloop()
Here is what it looks like:
Don't add weight to the first row. It is forcing it to expand. You may want to consider something else, though. You may eventually put something else on that row, and you may need that thing to expand the row. In it's current state this will cause a "catch 22" for you. You may want to consider creating a frame to hold all of the buttons, and put that entire frame on the root.
immediate fix:
from tkinter import *
from tkinter.ttk import *
import os
root = Tk()
root.geometry("325x100")
def click():
pass
def click2():
pass
button = Button(root, text="Button 1", command=click, width=25)
button.grid(row=0, column=0)
button2 = Button(root, text="Button 2", command=click2, width=25)
button2.grid(row=1, column=0)
#this is forcing the top row to expand
#root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
possibly a better way:
from tkinter import *
from tkinter.ttk import *
import os
root = Tk()
root.geometry("325x100")
def click():
pass
def click2():
pass
#by not defining row and column in grid()
#~ row will be the next available one and column will be 0
button_frame = Frame(root)
button_frame.grid(sticky='nswe')
button_frame.grid_columnconfigure(0, weight=1)
#you only need to store a reference if you intend to change/reference/destroy/forget these
#if they are going to always be a button, as initially defined, a reference is dead weight
Button(button_frame, text="Button 1", command=click, width=25).grid()
Button(button_frame, text="Button 2", command=click2, width=25).grid()
#now you can use grid_rowconfigure without it destroying your button layout
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root.mainloop()
Related
The 2 buttons should take each of the half of the window, one on the left, one on the right. The height is fixed all time. With .grid() nor .place() I can come to that result. The red bar is the color of the frame where the buttons are placed on. The buttons resize in width with the window, but keep their constant height.
How to?
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red')
frame.pack(fill='both', expand=True)
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.grid(row=0, column=0, sticky='nsew')
button2.grid(row=0, column=1, sticky='nsew')
frame.columnconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)
root.mainloop()
Thx.
In the mean time I got this:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(fill='both')
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.place(relwidth=0.5, relx=0, relheight=1)
button2.place(relwidth=0.5, relx=0.5, relheight=1)
root.mainloop()
Assuming that the buttons are the only widgets in the frame (ie: you are making a toolbar), I would use pack. grid will also work, but it requires one extra line of code.
Using pack
Here's a version with pack. Notice that the frame is packed along the top and fills the window in the "x" direction. The buttons each are instructed to expand (ie: receive extra, unused space) and to fill the space allocated to them in the "x" direction.
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(side="top", fill="x")
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.pack(side="left", fill="x", expand=True)
button2.pack(side="right", fill="x", expand=True)
root.mainloop()
Using Grid
A version with grid is similar, but you must use columnconfigure to give a non-zero weight to the two columns:
import tkinter as tk
root = tk.Tk()
frame = tk.Frame(root, bg='red',height=30)
frame.pack(side="top", fill="x")
button1 = tk.Button(frame, text="<<")
button2 = tk.Button(frame, text=">>")
button1.grid(row=0, column=0, sticky="ew")
button2.grid(row=0, column=1, sticky="ew")
frame.grid_columnconfigure((0, 1), weight=1)
root.mainloop()
I'm making a GUI with Tkinter (Tcl/Tk version 8.6.12) on Python 3.9. Up until now, I mostly had experience with pure Tk, but wanted to try Ttk out. My problem is that running:
someText = tk.StringVar(value="Some Text")
ttk.Label(mainframe, textvariable=someText).grid(column=0, row=0, sticky=(W, E))
does reserve some space for the string, but doesn't display it. When using the tk.Label class, it works like a charm...
What am I doing wrong, or is the ttk.Label class broken?
EDIT: here is my full MNWE (I wrapped everything in a function because I will need to integrate everything with some other code I have already written and this is the best way I've found to do it):
from tkinter import *
from tkinter import ttk
def generateGUI():
# Generates the main window
root = Tk()
root.title("Some interesting title")
root.resizable(FALSE, FALSE)
# Adds a frame for themed tk
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1) # setup the frame to scale with the window horizontally
root.rowconfigure(0, weight=1) # setup the frame to scale with the window vertically
# Creates a canvas
canv = Canvas(mainframe, bg="green")
canv.grid(column=0, row=0, sticky=(N, E, S, W))
# Sets some information panel up
info = ttk.Frame(mainframe)
info.grid(column=1, row=0, sticky=(N, E))
title = StringVar(value="<title>")
text1 = StringVar(value="<text1>")
text2 = StringVar(value="<text2>")
text3 = StringVar(value="<text3>")
# Adds the different labels
ttk.Label(info, font=25, textvariable=title).grid(column=0, row=0, sticky=N, columnspan=2)
ttk.Label(info, text="Info 1: ").grid(column=0, row=1, sticky=W)
ttk.Label(info, text="Info 2: ").grid(column=0, row=2, sticky=W)
ttk.Label(info, text="Info 3: ").grid(column=0, row=3, sticky=W)
ttk.Label(info, textvariable=text1).grid(column=1, row=1, sticky=E)
ttk.Label(info, textvariable=text2).grid(column=1, row=2, sticky=E)
ttk.Label(info, textvariable=text3).grid(column=1, row=3, sticky=E)
for child in mainframe.winfo_children():
child.grid_configure(padx=5, pady=5)
return root
gui = generateGUI()
gui.mainloop()
Your instance of StringVar is a local variable. Make it/them an instance variable if you're using classes, or a global variable if not.
def generateGUI():
global title
...
title = StringVar(value="<title>")
ttk.Label(info, font=25, textvariable=title)
This example code is working. You need to import ttk and change remove sticky.
why_no_sticky - good example on the link how grid works.
from tkinter import ttk
import tkinter as tk
mainframe = tk.Tk()
someText = tk.StringVar(value="Some Text")
label1 = ttk.Label(mainframe, textvariable=someText)
label1.grid(column=0, row=0)
mainframe.mainloop()
I'm trying to create a GUI that opens up a new window after pressing a button while destroying the last window. I'm not getting any errors but when I run my program nothing comes up.
from Tkinter import *
def team():
def table():
table = Toplevel(contributers)
contributers.destroy()
def contributers():
contributers = Toplevel(table)
table.destroy()
def firstpage():
firstpage = Toplevel(letsbegin)
letsbegin.destroy()
def secondpage():
secondpage = Toplevel(firstpage)
firstpage.destroy()
def leave():
exit()
root = Tk()
root.title("Team Blue")
label1 = label(menu, text="Team Blue", bg = "Yellow", fg="Black")
button1 = button(menu, text="ENTER", width=15, bg="yellow", fg="Black", command =contributers)
button2 = button(menu, text="Exit", bg="red", fg="white", command=leave)
root.mainloop()
I just want this code to run
You have many mistakes which I mentioned in comments.
If you want to close one window and open new one then destroy first window - root.destroy() - and later use again Tk() to create new window and use again mainloop().
I assign new window to global variable root so I can use almost the same code to close second window and open third one.
I use global root so variable root is not local variable but it is global and I have access (to window assigned to root) in other functions.
from Tkinter import *
# --- functions ---
def open_first_window():
global root
root = Tk()
label1 = Label(root, text="Team Brake 'Em")
label1.pack()
button1 = Button(root, text="Open Second Window", command=open_second_window)
button1.pack()
button2 = Button(root, text="Exit", command=root.destroy)
button2.pack()
root.mainloop()
def open_second_window():
global root
root.destroy()
root = Tk()
label1 = Label(root, text="Second Window")
label1.pack()
button1 = Button(root, text="Open Third Window", command=open_third_window)
button1.pack()
button2 = Button(root, text="Exit", command=root.destroy)
button2.pack()
root.mainloop()
def open_third_window():
global root
root.destroy()
root = Tk()
label1 = Label(root, text="Third Window")
label1.pack()
button2 = Button(root, text="Exit", command=root.destroy)
button2.pack()
root.mainloop()
# --- main ---
open_first_window()
There is other popular method - don't destry window but remove all widgets and put new one. Widget Frame can be usful because you can put all widget in Frame and Frame put in Window and later you have to only remove Frame and put new Frame with new widgets.
from Tkinter import *
# --- function ---
def create_first_frame():
global root
global frame
#frame.destroy()
frame = Frame()
frame.pack()
label1 = Label(frame, text="Team Brake 'Em")
label1.pack()
button1 = Button(frame, text="Open Second Window", command=create_second_frame)
button1.pack()
button2 = Button(frame, text="Exit", command=root.destroy)
button2.pack()
def create_second_frame():
global root
global frame
frame.destroy()
frame = Frame()
frame.pack()
label1 = Label(frame, text="Second Window")
label1.pack()
button1 = Button(frame, text="Open Third Window", command=create_third_frame)
button1.pack()
button2 = Button(frame, text="Exit", command=root.destroy)
button2.pack()
def create_third_frame():
global root
global frame
frame.destroy()
frame = Frame()
frame.pack()
label1 = Label(frame, text="Third Window")
label1.pack()
button2 = Button(frame, text="Exit", command=root.destroy)
button2.pack()
# --- main ---
root = Tk()
create_first_frame()
root.mainloop()
this is because as you wrapped your whole code inside the fuction name team().
so, you have to call that method at appropriate position in order to run the program.
and please make sure the letter case as label fuction is written as Label() so does button() is Button().
and also you have to use root in place of menu, then hopefully you see window.
pack the content according.
I did search for a lot of examples before posting but still can't properly use the tkinter grid.
What I want:
my code:
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
b1 = ttk.Button(root, text='b1')
b1.grid(row=0, column=0, sticky=tk.W)
e1 = ttk.Entry(root)
e1.grid(row=0, column=1, sticky=tk.EW)
t = ttk.Treeview(root)
t.grid(row=1, column=0, sticky=tk.NSEW)
scroll = ttk.Scrollbar(root)
scroll.grid(row=1, column=1, sticky=tk.E+tk.NS)
scroll.configure(command=t.yview)
t.configure(yscrollcommand=scroll.set)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.rowconfigure(1, weight=1)
root.mainloop()
The quick and simple solution is to define the columnspan of the treeview. This will tell the treeview to spread across 2 columns and allow the entry field to sit next to your button.
On an unrelated note you can use strings for your sticky so you do not have to do things like tk.E+tk.NS. Instead simply use "nse" or whatever directions you need. Make sure thought you are doing them in order of "nsew".
import tkinter as tk
from tkinter import ttk
root = tk.Tk()
b1 = ttk.Button(root, text='b1')
b1.grid(row=0, column=0, sticky="w")
e1 = ttk.Entry(root)
e1.grid(row=0, column=1, sticky="ew")
t = ttk.Treeview(root)
t.grid(row=1, column=0, columnspan=2, sticky="nsew") # columnspan=2 goes here.
scroll = ttk.Scrollbar(root)
scroll.grid(row=1, column=2, sticky="nse") # set this to column=2 so it sits in the correct spot.
scroll.configure(command=t.yview)
t.configure(yscrollcommand=scroll.set)
# root.columnconfigure(0, weight=1) Removing this line fixes the sizing issue with the entry field.
root.columnconfigure(1, weight=1)
root.rowconfigure(1, weight=1)
root.mainloop()
Results:
To fix your issue you mention in the comments you can delete root.columnconfigure(0, weight=1) to get the entry to expand properly.
I am trying to learn Tkinter and python. How can I open multiple images and save it on multiple canvas in Python 3? I also want the image to fit just perfect on to the size of the canvas.
Could someone show me to do this using simple code.
import tkinter
from tkinter import filedialog
import os
#from PIL import ImageTk, Image
from tkinter import *
import PIL.Image
from tkinter.filedialog import askopenfilename
import py_compile
mainWindow =tkinter.Tk()
mainWindow.title("Image")
mainWindow.geometry('640x480+800+200')
mainWindow.columnconfigure(0, weight=3)
mainWindow.columnconfigure(1, weight=1)
mainWindow.columnconfigure(2, weight=1)
mainWindow.rowconfigure(0, weight=3)
mainWindow.rowconfigure(1, weight=3)
mainWindow.rowconfigure(2, weight=5)
mainWindow.rowconfigure(3, weight=3)
leftFrame = tkinter.LabelFrame(mainWindow, text='PICTURE')
leftFrame.grid()
canvas = tkinter.Canvas(leftFrame, relief='sunken', borderwidth=5, bg= 'white', width=100, height=100)
canvas.grid(row=1, column=0)
canvas2 = tkinter.Canvas(leftFrame, relief='sunken', borderwidth=5, bg= 'white', width=100, height=100)
canvas2.grid(row=2, column=0)
canvas3 = tkinter.Canvas(leftFrame, relief='sunken', borderwidth=5, bg= 'white', width=100, height=100)
canvas3.grid(row=1, column=1)
canvas4 = tkinter.Canvas(leftFrame, relief='sunken', borderwidth=5, bg= 'white', width=100, height=100)
canvas4.grid(row=2, column=1)
def clicked():
print('hello')
open_img()
def open_img():
global photo
filename = filedialog.askopenfilename(initialdir = "E:/Images", filetypes = ())
photo = tkinter.PhotoImage(file=filename)
photo = photo.subsample(3,3)
canvas.create_image(0,0, anchor=CENTER, image=photo)
rightFrame = tkinter.LabelFrame(mainWindow, text='MENU')
rightFrame.grid()
button1 = tkinter.Button(rightFrame , text="Open", command=clicked)
button1.grid(row=1, column=2)
mainWindow.mainloop()
You would use one class with each image creating an instance of that class, but since you have not used a class and so are probably not familiar with the class structure, the following code combines everything into one class. Since I don't have the images, this opens a new Toplevel with a related "close" button instead of an image, each time the "open" button is clicked.
try:
import Tkinter as tk ## Python 2.x
except ImportError:
import tkinter as tk ## Python 3.x
from functools import partial
class OpenToplevels():
""" open and close additional Toplevels with a button
"""
def __init__(self):
self.root = tk.Tk()
self.button_ctr=0
but=tk.Button(self.root, text="Open a Toplevel",
command=self.open_another)
but.grid(row=0, column=0)
tk.Button(self.root, text="Exit Tkinter", bg="red",
command=self.root.quit).grid(row=1, column=0, sticky="we")
self.root.mainloop()
def close_it(self, id):
id.destroy()
def open_another(self):
self.button_ctr += 1
id = tk.Toplevel(self.root)
id.title("Toplevel #%d" % (self.button_ctr))
tk.Button(id, text="Close Toplevel #%d" % (self.button_ctr),
command=partial(self.close_it, id),
bg="orange", width=20).grid(row=1, column=0)
Ot=OpenToplevels()