I currently have this grid
https://imgur.com/a/ZELwflE
I want to make it like this:
https://imgur.com/a/SnBHW2S
Would it be possible? Heres my code:
import random
from tkinter import *
root = Tk()
root.title("TOMBOLA")
root.resizable(0, 0)
root.config(bg="WHITE")
entry= Entry(root, width= 40)
entry.focus_set()
entry.grid(column=1, row=0, padx=25)
texto=Label(root, text="Introduce el nombre para agregar a la tómbola:", font=("Courier")).grid(column=0, row=0, padx=(10,0))
boton_ok=Button(root, text="OK", width=10, height=2)
boton_ok.grid(row=0, column=3, padx=10, pady=(25,0))
listaindic = Label(root, text="Lista: ")
listaindic.grid(row=1, column=1, sticky=W)
display = Label(root, text="")
display.grid(row=1, column=2, columnspan=1, sticky=E)
boton_sig=Button(root, text="INICIAR TOMBOLA").grid(column=0, row=1, columnspan=1, pady=(0,15))
root.mainloop()
Thank you all so much
I tried making columnspan bigger, but didnt end well.
Tkinter relies on cells and rows to display widgets, without these there is no functionality. This being the case there is really no way of doing what you are asking in the first image. Everything has to be in a cell. So how I would try to fix your problem is by creating a tkinter.Frame and insert it into the cell you are trying to configure (1, 1). This creates another grid inside the frame so we can choose what to do with it. e.g: increasing the weight on the second column to make it seem much bigger.
newFrame = Frame(master=root)
newFrame.grid_rowconfigure(0, weight=1)
newFrame.grid_columnconfigure(0, weight=1)
newFrame.grid_columnconfigure(1, weight=3)
listaindic = Label(newFrame, text="Lista: ")
listaindic.grid(row=0, column=0, sticky=W)
This shows you how to create a basic frame, and putting the Label into the first cell.
Related
Following is my sample code containing three labels and three entry fields:
import tkinter as tk
from tkinter import *
root = Tk()
root.resizable(width=False, height=False)
root.geometry("1200x700")
root.iconbitmap(r'.\autocrest.ico')
root.title('Autocrest Job Card')
root.columnconfigure(0, weight=20)
topRowFrame= Frame(root,relief="ridge", width=1000)
topRowFrame.config(bd=1, relief=tk.SUNKEN)
topRowFrame.columnconfigure(0, weight=1)
topRowFrame.columnconfigure(1, weight=4)
topRowFrame.columnconfigure(2, weight=1)
topRowFrame.columnconfigure(3, weight=4)
topRowFrame.columnconfigure(4, weight=1)
topRowFrame.columnconfigure(5, weight=4)
topRowFrame.grid(column=0,row=0, padx=5, pady=5, sticky=W)
bookingIdLabel=tk.Label(topRowFrame, text="Booking ID")
bookingIdLabel.grid(column=0,columnspan=2, row=0, padx=5, pady=5)
bookingIdEntry=Entry(topRowFrame)
bookingIdEntry.grid(column=2,columnspan=2, row=0, padx=5, pady=5)
noLabel=tk.Label(topRowFrame, text="No")
noLabel.grid(column=4,columnspan=2, row=0, padx=5, pady=5)
noEntry=Entry(topRowFrame)
noEntry.grid(column=6,columnspan=2, row=0, padx=5, pady=5)
dateLabel=tk.Label(topRowFrame, text="Date")
dateLabel.grid(column=8,columnspan=2, row=0, padx=5, pady=5)
dateEntry=Entry(topRowFrame)
dateEntry.grid(column=10,columnspan=2, row=0, padx=5, pady=5)
root.mainloop()
All of widgets in following code occupy space equal to their width only. I want to increase space between them. Columnspan and weight has no impact.
To be able to make widgets resizable as the screen resizes you need to use Grid.rowconfigure(root, index=0, weight=1). Root is the name of window/frame, index is number of the row and weight should be set to 1. You need to copy and paste this line of code and change index for the next row or use a for loop like this:
number_of_rows = 5
for i in range(number_of_rows):
Grid.rowconfigure(root, index=i, weight=1)
and apply the same for columns with Grid.columnconfigure().
Once you have done that put sticky="NSEW" so it sticks to every side of the window and fills it.
Columnspan and weight has no impact.
That is because you told grid to make topRowFrame only sticky to the left side of the window. Therefore it won't stretch to fill the whole column. Your use of root.columnconfigure(0, weight=20) makes the column fill the window, but the widget doesn't fill the column.
Try the value "ew" (east, west) for the sticky attribute if you want topRowFrame to be as wide as the window:
topRowFrame.grid(column=0,row=0, padx=5, pady=5, sticky="ew")
I just got started using Tkinter and I'm facing a weird problem, basically, I want my app to look something like this
So in order to do that, I created two Frames, one for menu items and the other one to display the content. Strange thing, when I initialize the frames with the given width and height the program seems to work as expected, but when I put some widgets inside the window resizes, it looks like this
Could somebody please explain this weird behaviour to me? What am I missing? Also, I would like to mention that when I add the buttons to the menu frame the width changes to fit the button width, not vice versa as I would like
app = tk.Tk()
app.resizable(False, False)
menu_frame_users = tk.Frame(app, width=200, background='red')
content_frame = tk.Frame(app, height=600, width=600, background='blue')
hello_label = tk.Label(menu_frame_users, text='Hello, User').grid(column=0, row=0, sticky='we')
view_profile_button = tk.Button(menu_frame_users, text="View Profile").grid(column=0, row=1, sticky='we')
invoices_button = tk.Button(menu_frame_users, text="Invoices").grid(column=0, row=2, sticky='we')
bookings_button = tk.Button(menu_frame_users, text="View bookings").grid(column=0, row=3, sticky='we')
tools_button = tk.Button(menu_frame_users, text="Search tools").grid(column=0, row=4, sticky='we')
test_label = tk.Label(content_frame, text='View profile')
test_label.grid(column=0, row=0, sticky='we')
menu_frame_users.grid(column=0, row=0, sticky='nswe')
content_frame.grid(column=1, row=0, sticky='nswe')
The frames in tkinter will only be as big as the widgets contained within unless you add weight to row and columns to make them expand.
You can get the frame to expand by setting the size of the window and then adding weight to the appropriate row and column.
app.geometry('500x400')
app.grid_columnconfigure(1, weight=1)
app.grid_rowconfigure(0, weight=1)
You can play around with the size of the window and then resize and position your buttons until you get the layout you want.
You can also use:
app.grid_columnconfigure(1, minsize=300)
However this only applies when the column contains a widget.
I'm not sure if I fully understand the question, but maybe this will help. Note I removed the explicit frame dimensions for the sake of the example.
import tkinter as tk
app = tk.Tk()
app.resizable(False, False)
menu_frame_users = tk.Frame(app,background='red')
content_frame = tk.Frame(app, background='blue')
app.geometry("500x500")
app.rowconfigure(0, weight=1)
app.columnconfigure(0, weight=1)
menu_frame_users.columnconfigure(0, weight=1)
hello_label = tk.Label(menu_frame_users, text='Hello, User').grid(column=0, row=0, sticky='we')
view_profile_button = tk.Button(menu_frame_users, text="View Profile").grid(column=0, row=1, sticky='we')
invoices_button = tk.Button(menu_frame_users, text="Invoices").grid(column=0, row=2, sticky='we')
bookings_button = tk.Button(menu_frame_users, text="View bookings").grid(column=0, row=3, sticky='we')
tools_button = tk.Button(menu_frame_users, text="Search tools").grid(column=0, row=4, sticky='we')
test_label = tk.Label(content_frame, text='View profile')
test_label.grid(column=0, row=0, sticky='we', padx=20, pady=20)
menu_frame_users.grid(column=0, row=0, sticky='nswe')
content_frame.grid(column=1, row=0, sticky='nswe')
app.mainloop()
Documentation for tkinter is a bit limited but there's some great info regarding grid configuration on this page.
Generally speaking, the widgets in a given container are what give the container it's dimensions, unless explicitly coded otherwise. (In other words, the frame will grow as you add things into it, not the other way around)
In your example, I added an arbitrary window size (you can also specify an offset in that string argument). My guess is you're looking for rowconfigure() and columnconfigure(). Also, you can add some padding to space things out with .grid()
I almost exclusively use the grid geometry manager, but sometimes you might find it more pragmatic to use pack() or place(), just make sure you don't use both at the same time.
Cheers.
It's a little complicated, but I'll try my best to explain:
let's say that for example, I have a grid with 4 labels when I have 2 rows and 2 columns (see image below). I'm trying to make the vertical line between columns 1 and 2 (red line in the image) to be the line that splits the window into two equal halves.
You can see a sample of my initial code below.
Edit: note that the elements are labels just for example, but in my original code they are actually all different (some are frames, some images, some buttons, etc)
import tkinter as tk
root = tk.Tk()
label1 = tk.Label(root, text=1, width=8, height=2, bg="red")
label1.grid(row=0, column=0)
label2 = tk.Label(root, text=2, width=10, height=3, bg="green")
label2.grid(row=0, column=1)
label3 = tk.Label(root, text=3, width=5, height=4, bg="blue")
label3.grid(row=1, column=0)
label4 = tk.Label(root, text=4, width=6, height=2, bg="yellow")
label4.grid(row=1, column=1)
root.mainloop()
This code makes the vertical and horizontal center lines of each label perfect as I wanted, but the vertical line between columns 1 and 2 (red line in image) is nowhere near to be the center of the window.
Then, I have tried adding the grid_columnconfigure function to my code:
import tkinter as tk
root = tk.Tk()
root.grid_columnconfigure(0, weight=1) # the line I've added
label1 = tk.Label(root, text=1, width=8, height=2, bg="red")
label1.grid(row=0, column=0)
label2 = tk.Label(root, text=2, width=10, height=3, bg="green")
label2.grid(row=0, column=1)
label3 = tk.Label(root, text=3, width=5, height=4, bg="blue")
label3.grid(row=1, column=0)
label4 = tk.Label(root, text=4, width=6, height=2, bg="yellow")
label4.grid(row=1, column=1)
root.mainloop()
But now I have a different problem, where the columns don't touch each other.
I've also tried to fix the issue by adding the sticky arguments when I'm placing the elements in the grid, and also tried putting every row and every column in their own frame, but all of the solutions did not work out for me.
How can I get this to work? Hope my explanation was clear, and thanks in advance (;
You could just put the four images/labels together into a Frame (or any other container element) and then have that frame horizontally and vertically centered in your root frame with place.
c = tk.Frame(root, bg='white')
c.place(relx=0.5, rely=0.5, anchor='center')
Don't forget to change the parent of the labels from root to c, i.e. Label(c, ...).
Update: But this does not center the line between the red and the green block to the frame. You could combine this with uniform to make the columns equal width, but then there will be some padding between the center and the thinner column...
for n in (0, 1):
c.grid_columnconfigure(n, uniform="foo")
You can use a ttk.Separator widget.
You should use the following code part:
import tkinter.ttk
import tkinter as tk
root = tk.Tk()
---etc---
---etc---
---etc---
tkinter.ttk.Separator(master, orient=VERTICAL).grid(column=1, row=0, rowspan=2, sticky='ns')
root.mainloop()
You can get the grid info of a widget with "grid_info" method.
row = widget.grid_info()['row'] # Row of the widget
column = widget.grid_info()['column'] # Column of the widget
Since there are 2 columns, root.grid_columnconfigure(0, weight=1) only affects the first column.
Try
for n in range(2):
root.grid_columnconfigure(n, weight=1)
or
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
I am currently writing a simple piece of inventory management software for a school python assessment. My GUI involves listing out all of the items in stock, and giving the user the ability to stock/sell multiple items at once. This was achieved by placing an entry (amount to buy) and a scale widget (amount to sell) next to each item, and utilizing an "apply" button to enact the changes (For context, the scenario is a comic book store):
https://i.imgur.com/7cesQm5.png
This is the code that I have used to create the new widgets from each file (all of which are contained in a dictionary, pulled from a CSV file):
itteration = 2
labels = {}
nameTitle = Label(main, text="Title").grid(row=1, column=1, padx=5)
stockTitle = Label(main, text="Stock").grid(row=1, column=2, padx=5)
buyTitle = Label(main, text="Amount to Buy").grid(row=1, column=3, padx=5)
sellTitle = Label(main, text="Amount to Sell").grid(row=1, column=4, padx=5)
for item in comic_books:
name = item.replace(" ", "")
nameStock = "{}Stock".format(item).replace(" ", "")
nameBuy = "{}Buy".format(item).replace(" ", "")
nameSell = "{}Sell".format(item).replace(" ", "")
labels[name] = Label(main, text=item+":")
labels[name].grid(column=1, row=itteration, padx=5)
labels[nameStock] = Label(main, text=comic_books.get(item))
labels[nameStock].grid(column=2, row=itteration, padx=5)
labels[nameBuy] = Entry(main)
labels[nameBuy].grid(column=3, row=itteration, padx=20)
labels[nameSell] = Scale(main, from_=0, to=comic_books.get(item), orient=HORIZONTAL)
labels[nameSell].grid(column=4, row=itteration, padx=5)
itteration += 1
However, I am not a fan of how the the scales appear to be centering themselves in the row based on both the center of the slider, and the number on top. This makes the slider appear lower than the entry widget next to it.
https://i.imgur.com/9CQTvWS.png
My question is: how would I go about potentially offsetting the position of the scale widgets upwards by a given amount (maybe 5-10px?) from its original position, to push the actual slider in line with the entry widget before it?
Please let me know if you need any extra clarification
Cheers,
-Sean
Using sticky='s' and sticky='n' to stick to bottom (south) and top (north) of cell I got this
I didn't use different values in pady
import tkinter as tk
root = tk.Tk()
l = tk.Label(root, text='Label')
l.grid(column=1, row=0, padx=5, sticky='s', pady=10)
e = tk.Entry(root)
e.grid(column=2, row=0, padx=20, sticky='s', pady=10)
s = tk.Scale(root, from_=0, to=10, orient='horizontal')
s.grid(column=3, row=0, padx=5, sticky='n', pady=10)
root.mainloop()
Using sticky with pady=(0,20) for one widget I got this
import tkinter as tk
root = tk.Tk()
l = tk.Label(root, text='Label')
l.grid(column=1, row=0, padx=5, sticky='s', pady=10)
e = tk.Entry(root)
e.grid(column=2, row=0, padx=20, sticky='s', pady=10)
s = tk.Scale(root, from_=0, to=10, orient='horizontal')
s.grid(column=3, row=0, padx=5, sticky='n', pady=(0,20))
root.mainloop()
So i have some tkinter checkboxes in a frame widget, which should be aligned to each other. I thought with grid and then using sticky='w' should align them to most east as possible of the column. So to say, to have the checkbox-squares aligned. Instead this happens (the relief is just to see the boundaries of the checkbutton widgets):
Image of GUI
The documentation of the widget - in my opinion - does not provide a function to set this. With the sticky of grid i am not sure whether it should even be the function. Actually the relief shows its sticky in that column...
Here is my code example:
def init_checkboxes(self):
"""
Creates all checkboxes for this particular frame subclass.
"""
self.bvar_cbx_showplots = tk.BooleanVar(value=False)
self.cbx_showplots = tk.Checkbutton(self.lblframe, width=20,
text='Show Plots after run',
variable=self.bvar_cbx_showplots,
relief='groove')
self.cbx_showplots.grid(row=1, column=2, sticky='W')
self.bvar_cbx_saveres = tk.BooleanVar(value=True)
self.cbx_saveres = tk.Checkbutton(self.lblframe, width=20,
text='Save simulation results',
variable=self.bvar_cbx_saveres,
relief='groove')
self.cbx_saveres.grid(row=2, column=2, sticky='W')
edit: Second attempt from Reblochon
Use anchor.
anchor=
Controls where in the button the text (or image) should be located. Use one of N, NE, E, SE, S, SW, W, NW, or CENTER. Default is CENTER. If you change this, it is probably a good idea to add some padding as well, using the padx and/or pady options. (anchor/Anchor)
import tkinter as tk
root = tk.Tk()
bvar_cbx_showplots = tk.BooleanVar(value=False)
cbx_showplots = tk.Checkbutton(root, width=20,
text='Show Plots after run',
variable=bvar_cbx_showplots,
relief='groove', anchor='w')
cbx_showplots.grid(row=1, column=2, sticky='W')
bvar_cbx_saveres = tk.BooleanVar(value=True)
cbx_saveres = tk.Checkbutton(root, width=20,
text='Save simulation results',
variable=bvar_cbx_saveres,
relief='groove', anchor='w')
cbx_saveres.grid(row=2, column=2, sticky='W')
root.mainloop()