I have an issue with a label on tkinter. I would like to know if it's possible to "occupy space", when I insert long text my label become huge and I have a lot of blank around my text. Is it possible to delete this blank ?
action=customtkinter.CTkLabel(master=frame_right, width=400, height=150, text="", justify=tkinter.LEFT, text_font=("Roboto Medium", -10), fg_color="white")
action.grid(row=4, column=2, padx=15, pady=15, sticky='')
Label from custom tkinter
Here the code to reproduct what happen :
import customtkinter
from tkinter import *
class App(customtkinter.CTk):
WIDTH = 850
HEIGHT = 620
app = customtkinter.CTk() # create CTk window like you do with the Tk window (you can also use normal tkinter.Tk window)
app.geometry(f"{App.WIDTH}x{App.HEIGHT}")#taille de la fenetre graphique
app.grid_rowconfigure(0, weight=1)
app.grid_columnconfigure(1, weight=1)
frame_right = customtkinter.CTkFrame(master=app)
frame_right.grid(row=0, column=1, sticky="nswe", padx=20, pady=20)
# configure grid layout (3x7)
frame_right.rowconfigure((0, 1, 2, 3), weight=1)
frame_right.rowconfigure(7, weight=10)
frame_right.columnconfigure((0, 1), weight=1)
frame_right.columnconfigure(2, weight=0)
action=customtkinter.CTkLabel(master=frame_right, width=400, height=150, text="", justify="center", text_font=("Roboto Medium", -10), fg_color="white")
action.grid(row=4, column=2, padx=15, pady=15, sticky="n")
action.configure(text="CustomTkinter is a python UI-library based on Tkinter, which provides new, modern and fully customizable widgets.\nThey are created and used like normal Tkinter widgets and can also be used in combination with normal Tkinter")
app.mainloop()
You've given an explicit width and height to the label, so tkinter is trying to honor that size. Since your text doesn't fill the space, the extra space is going to appear blank.
If you remove width=400, height=150, from where you create the label, the label will be just big enough to fit the text.
The following screenshot shows what I get when I remove the explicit width and height:
I finally resolved my problem, I replaced this
frame_right.columnconfigure((0, 1), weight=1)
frame_right.columnconfigure(2, weight=0)
by this :
frame_right.grid_columnconfigure(0, weight=1)
frame_right.grid_columnconfigure(1, weight=10)
Related
Im trying to use a vertical scrollbar for my text box but am coming across some problems:
I cant get the scroll bar to be directly touching the right side of the text box (so they are connected)
It seems the scroll bar wont affect my text box
I looked through some solutions but none seemed to work.
Heres my code:
from tkinter import *
writtenQ = Tk()
writtenQ.title("Written Response Question")
writtenQ.resizable(0,0)
header = LabelFrame(writtenQ, bg="white")
content = LabelFrame(writtenQ, bg="white")
header.columnconfigure(0, weight=1) # Forces column to expand to fill all available space
homeButton=Button(content,width=50,height=50)
try:
homeIcon=PhotoImage(file="yes.png")
homeButton.config(image=homeIcon)
homeButton.image = homeIcon
except TclError:
print("Home")
homeButton.grid(row=1, sticky="w", padx=15, pady=2)
#the image of the question will be put here
titleHeader = Label(content, text="Question Image here",pady=15, padx=20, bg="white", font=("Ariel",20, "bold"), anchor="w", relief="solid", borderwidth=1)
titleHeader.grid(row=2, column=0, columnspan=3, padx=15, pady=5, ipadx=370, ipady=150)
#this will allow the user to input their written response
answerInput = Text(content, width = 60, borderwidth=5, font=("HelvLight", 18))
answerInput.grid(row=3, column=0, ipady = 10, sticky="w", padx=(20,0), pady=20)
answerScrollBar= Scrollbar(content, command=answerInput.yview, orient="vertical")
answerScrollBar.grid(row=3, column=1, sticky="w")
submitButton = Button(content, borderwidth=1, font=("Ariel", 22), text="Submit", bg="#12a8e3", fg="black", activebackground="#12a8e3", relief="solid")
submitButton.grid(row=3, column=2, ipady=50, ipadx=70, sticky="nw", pady=20)
header.grid(row=0, sticky='NSEW')
content.grid(row=1, sticky='NSEW')
Configuring a scrollbar requires a two-way connection: the scrollbar needs to call the yview or xview method of the widget, and the widget needs to call the set method of the scrollbar.
Usually, this is done in three steps like in the following example:
answerInput = Text(...)
answerScrollBar= Scrollbar(..., command=answerInput.yview)
answerInput.configure(yscrollcommand=answerScrollBar.set)
You are forgetting the final step.
Unrelated to an actual functioning scrollbar, you're going to want to be able to see the scrollbar. You need to use sticky="ns" for the scrollbar so that it stretches in the Y direction. Otherwise it will only be a couple dozen pixels tall.
answerScrollBar.grid(row=3, column=1, sticky="ns")
Have you tried the solution here?
Let's say that the text widget is called text. Your code could be (excluding the setup of the window):
import tkinter
import tkinter.ttk as ttk
scrollb = ttk.Scrollbar(self, command=text.yview)
scrollb.grid(row=0, column=1, sticky='nsew')
text['yscrollcommand'] = scrollb.set
I have picked out what I think will be ueful for you from Honest Abe's answer. Hope it helped. Remember to set up your window before using the code...
Sorry if it's an easy fix - I'm new to tkinter (and graphical applications in general), and on my way up the learning curve.
I have a simple window in grid layout, with a canvas and a few labels to the right of it. They're positioned and sized correctly - but when I resize the window to the right, they DO expand over, but only about half way (i.e., for every 2 pixels to the right I expand the window, they widgets only expand by 1). I have their respective columns weighted, as well as the parent frame's column weighted. I'm not sure how to remedy this, and haven't found anything similar through Googling. Below I've posted my code, and screenshots of the widgets when the application is launched vs. when I resize.
CODE
from tkinter import *
root = Tk()
root.title("title")
mainframe = Frame(root)
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
canvas = Canvas(mainframe, width=800, height=800)
canvas.grid(row=1, column=1, rowspan=3)
info_label = Label(mainframe, text='Info Label', bg='white', relief='solid', borderwidth=1)
info_label.grid(row=1, column=2, columnspan=2)
chatbox = Label(mainframe, text='Welcome to the application.', bg='white', relief='solid', borderwidth=1)
chatbox.grid(row=2, column=2, columnspan=2, sticky=(N,S,E,W))
chat_entry = Entry(mainframe)
chat_entry.grid(row=3, column=2)
chat_send = Button(mainframe, text='Send')
chat_send.grid(row=3, column=3)
mainframe.rowconfigure(1, weight=1)
mainframe.rowconfigure(2, weight=1)
mainframe.columnconfigure(2, weight=1)
root.columnconfigure(1, weight=1)
root.mainloop()
SCREENSHOTS
The only positioning command that resizes according to the window size is pack().
As known, you have the following functions:
pack()
grid()
place()
By the way, I recommend using the place function and use this:
window.resizable(width=False, height=False)
This function prevent from the client the ability to resize the tkinter window.
I am new to using grid_rowconfigure() and grid_columnconfigure() but from my understanding, the code below should make a centered textbox that has space either side:
self.grid_rowconfigure((0, 1, 2), weight=1)
self.grid_columnconfigure((0, 1, 2), weight=1)
Box = tk.Text(self, height=2, pady=4)
Box.grid(row=1, column=1)
However, the Text widget is the default width. How can I make it so it fills the column width (based on weight)?
I thought about placing a frame in the grid then packing the textbox within the frame to fill it but it looks the same as this.
UPDATE:
I used sticky="nsew" and that seems to work for the vertical height but not the horizontal height.
Fix: added a value for width in Box
Working Code:
self.grid_rowconfigure((0, 1, 2), weight=1)
self.grid_columnconfigure((0, 1, 2), weight=1)
Box = tk.Text(self, height=2, width=2, pady=4)
Box.grid(row=1, column=1, sticky="nsew")
You need to use the sticky attribute to cause a widget to fill the space given to it.
Box.grid(row=1, column=1, sticky=“nsew”)
I am currently trying to make a game in Tkinter which uses multiple different windows.
However, as I am trying to create the layout of a secondary window, I can't seem to get my Return to Menu button underneath the list box, and aligned to the left. I have tried it using .pack() and .grid() methods, but they don't make sense to me.
I've tried using .pack():
header = Frame(wn).pack()
title = Label(header, text='Single-Player',font=('Arial bold',20),bg=bgcolor).pack(anchor='center')
footer = Frame(wn).pack(side=BOTTOM)
return_to_menu = Button(footer, text='Return to Main Menu',font=('Arial',16),bg=bgcolor,command=lambda: menu()).pack(side=BOTTOM,padx=20,pady=250)
# body frame (left side)
bodyL = Frame(wn).pack(side=LEFT)
#output box
output = Listbox(bodyL, width=50, font=("Arial", 20)).pack(side=LEFT,padx=15)`
And I've tried using .grid():
header = Frame(wn).grid(sticky=N)
title = Label(header, text='Single-Player',font=('Arial bold',20),bg=bgcolor).grid(sticky=N+E+W,row=0,column=0)
footer = Frame(wn).grid(sticky=S)
return_to_menu = Button(footer, text='Return to Main Menu',font=('Arial',16),bg=bgcolor,command=lambda: menu()).grid(sticky=S,padx=20,row=0,column=0)
# body frame (left side)
bodyL = Frame(wn).grid(sticky=W)
#output box
output = Listbox(bodyL, width=50, font=("Arial", 20)).grid(sticky=W,padx=15, )`
However using .grid() doesn't align my title to the center of the screen anymore.
Is there a way to center it more efficiently - I didn't like using padx=450 to get it centered.
What happens with the button and the list box, is the button appears to the left of the list box, instead of on the bottom. I have attempted several other methods, such as incrementing row numbers, but my script doesn't appear to do what I anticipated.
Here is an example of how you can set up the weight of specific columns and row to get widgets to stick to a specific location on the screen.
With the use of grid() we need to use columnconfigure() and rowconfigure() to make this work.
These 2 methods are used to define at what ratio the column or row will expand in relation to the columns or rows around it as the container grows or shrinks.
See below example and let me know if you have any questions:
import tkinter as tk
root = tk.Tk()
for i in range(3):
root.columnconfigure(i, weight=1)
root.rowconfigure(1, weight=1)
tk.Label(root, text='Top left').grid(row=0, column=0, sticky='w')
tk.Label(root, text='Top center').grid(row=0, column=1)
tk.Label(root, text='Top right').grid(row=0, column=2, sticky='e')
tk.Label(root, text='center').grid(row=1, column=1)
tk.Label(root, text='Bottom left').grid(row=2, column=0, sticky='w')
tk.Label(root, text='Bottom center').grid(row=2, column=1)
tk.Label(root, text='Bottom right').grid(row=2, column=2, sticky='e')
root.mainloop()
Example:
Here is another example but this time I have a title label outside of a frame so that we can make it easier to manage the title being centered and then working with all the other content of the frame is separate from the title label.
import tkinter as tk
root = tk.Tk()
root.columnconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
frame = tk.Frame(root)
frame.grid(row=1, column=0, sticky='nsew')
for i in range(3):
frame.columnconfigure(i, weight=1)
frame.rowconfigure(1, weight=1)
tk.Label(root, text='Title centered').grid(row=0, column=0)
tk.Label(frame, text='Top left').grid(row=0, column=0, sticky='w')
tk.Label(frame, text='Top center').grid(row=0, column=1)
tk.Label(frame, text='Top right').grid(row=0, column=2, sticky='e')
tk.Label(frame, text='Center').grid(row=1, column=1)
tk.Label(frame, text='Bottom left').grid(row=2, column=0, sticky='w')
tk.Label(frame, text='Bottom center').grid(row=2, column=1)
tk.Label(frame, text='Bottom right').grid(row=2, column=2, sticky='e')
tk.Label(root, text='Footer centered').grid(row=2, column=0)
root.mainloop()
Example:
To address your problem in the comments you cannot use grid() or any other geometry manager for that matter on the same line you create your container. This will always cause the variable for that frame to return None as the geometry managers return None when called.
See this image as to what happens when you use grid() on the same line you create your container.
Now if you delete the grid() part on the row that your container is created and then write it on the next line as the commented out section of the above images shows it will work as expected. See below image of proper use of grid() for containers.
To address your 2nd question in the comments you can add this line to provide a button at the bottom left.
tk.Button(root, text='Bottom left button').grid(row=3, column=0, sticky='w')
Example:
Is there a way using Tkinter to have buttons so that they are always placed a certain number of pixels from the edge of the window, even when the window is resized? I've tried using anchors but that didn't seem to move the placement in the window that much.
You can anchor buttons or any other widget to the sides of a window by starting with a Frame, and configuring its rows and columns to have a weight of 1 in order for it to fill the parent window.
import Tkinter as tk
import ttk
root = tk.Tk()
frame = ttk.Frame(root)
frame.pack(fill=tk.BOTH, expand=True)
frame.columnconfigure(index=0, weight=1)
frame.columnconfigure(index=2, weight=1)
frame.rowconfigure(index=0, weight=1)
frame.rowconfigure(index=2, weight=1)
Then, for each button you want to use sticky to anchor it to the respective side, and use padx or pady to add some padding (in pixels) between the button and the window.
top_padding = 5
top = ttk.Button(frame, text="Top")
top.grid(row=0, column=1, sticky=tk.N, pady=(top_padding, 0))
left_padding = 5
left = ttk.Button(frame, text="Left")
left.grid(row=1, column=0, sticky=tk.W, padx=(left_padding, 0))
right_padding = 5
right = ttk.Button(frame, text="Right")
right.grid(row=1, column=2, sticky=tk.E, padx=(0, right_padding))
bottom_padding = 5
bottom = ttk.Button(frame, text="Bottom")
bottom.grid(row=2, column=1, sticky=tk.S, pady=(0, bottom_padding))
root.mainloop()
have you tried using the padx function?
it works like this:
button=Button(place,text="something something", padx=10)
it provides with extra horizontal padding between widgets, aditionally, you could use frames with padx and an anchor so the text is fixated to a position