Tkinter scrollbar removes textbox and doesnt sticky to the right - python

My textbox spans over 5 rows and 4 columns and I want it to have a scrollbar, so I added one but it removes the textbox and doesn't stick.
My textbox looks like this:
and its code like this
# Textbox
self.textbox = Text(self)
self.textbox.grid(row=10, column=1, rowspan=5, columnspan=4, padx=10, pady=10)
self.vsb = Scrollbar(self.textbox, orient='vertical', command=self.textbox.yview)
self.vsb.grid(row=10, column=4, rowspan=5, sticky='ns')
self.textbox.configure(yscrollcommand=self.vsb.set)
after running it my textbox just vanishes
I have no clue what caused this, I usually have no problems with scrollbars.

Maybe you'll have better luck with the ScrolledText widget. See here for docs
from tkinter.scrolledtext import ScrolledText
self.textbox = ScrolledText(self)

Related

Tkinter: Placing widgets on top of other Widgets

I'm trying to place an Entry widget on top of a frame but i'm having some trouble with it
(I'm using customtk but i suppose there's no big difference)
import customtkinter
app = customtkinter.CTk()
app.geometry(500x380)
random_frame = customtkinter.CTkFrame(master=app, width=480, height=50)
Box1 = customtkinter.CTkEntry(master=app, width=30, height=30)
random_frame.grid(row=3, column=0, padx=10, pady=10)
Box1.grid(row=3, column=1, padx=10, pady=10)
I am expecting the Box1 widget to be on top of the random_frame widget, however in the gui i can't see the Box1. I'm unsure if it's under the frame, but that's what i think is happening.
I tried using the lift() method but it doesn't seem to do anything

Add a scrollbar for text object inside frame

I have a frame which has a text object inside it. How do I add a vertical scrollbar that controls the text object. The scrollbar should be on the right side..
inputFrame = Frame(bg='#d9d9d9')
inputFrame.pack()
inputEntryImg = PhotoImage(file=resource_path("inputEntry.png"))
inputEntryBg = mainWindowCanvas.create_image(400.0, 168.5, image=inputEntryImg)
inputEntry = Text(inputFrame, bd=0, bg="#d9d9d9", highlightthickness=0, font='calibri',
pady=10)
inputEntry.pack(padx=(0, 10), pady=10)
inputFrame.place(x=41.0, y=83, width=718.0, height=169)
Thankyou.
Try this
scrollbar = Scrollbar(inputFrame, orient=VERTICAL, command=inputEntry.yview)
scrollbar.pack(side=RIGHT, fill=Y)
inputEntry.config(yscrollcommand=scrollbar.set)
How do I add a vertical scrollbar that controls the text object. The
scrollbar should be on the right side..
Try this. I did not add PhotoImage. You can add it by yourself.
Code:
import tkinter as tk
root = tk.Tk()
inputFrame = tk.Frame(bg='#d9d9d9')
inputFrame.pack()
#inputEntryImg = tk.PhotoImage(file=resource_path("inputEntry.png"))
#inputEntryBg = mainWindowCanvas.create_image(400.0, 168.5, image=inputEntryImg)
inputEntry=tk.Text(inputFrame, height=10, width=50)
scrollBar= tk.Scrollbar(inputFrame, command=inputEntry.yview, orient="vertical")
scrollBar.grid(row=0, column=1, sticky="ns")
inputEntry.grid(row=0,column=0)
inputEntry.configure(yscrollcommand=scrollBar.set)
root.mainloop()
Screenshot for scrollbar with text:

How do I fill empty space using grid system in tkinter?

I have 5 buttons with 3 of them in the first row and 2 in the second row. How do I fill the white space that is left? I tried the following:
Date_play.grid(row=3,column=1,columnspan=2,sticky="w")
File_play.grid(row=3,column=2,columnspan=2,sticky="e")
Thanks in advance.
There are multiple ways to do this. One of the easier ones is to play around with the Grid Layout.
Try this:
import tkinter as tk
root = tk.Tk()
# create a grid of 2x6
root.rowconfigure(0, weight=1)
root.rowconfigure(1, weight=1)
for i in range(6):
root.columnconfigure(i, weight=1)
# by playing around with columnspan, you can get the layout that you need
button1 = tk.Button(root, text='1')
button1.grid(row=0, column=0, columnspan=2, sticky=tk.NSEW)
button2 = tk.Button(root, text='2')
button2.grid(row=0, column=2, columnspan=2, sticky=tk.NSEW)
button3 = tk.Button(root, text='3')
button3.grid(row=0, column=4, columnspan=2, sticky=tk.NSEW)
button4 = tk.Button(root, text='4')
button4.grid(row=1, column=0, columnspan=3, sticky=tk.NSEW)
button5 = tk.Button(root, text='5')
button5.grid(row=1, column=3, columnspan=3, sticky=tk.NSEW)
root.mainloop()
You can try and add space to the text in each button.
If the text is something like:
Date Module
Just expand it like this:
Date Module
It will make the button be bigger.
Also, you can use the width attribute of each button:
date_module_button.configure(width=...)
In both of the options, you need to play with it, add more/less space, add more/less width, until you are happy with the size of the button.
try this:
Date_play.grid(row=3,column=0,columnspan=2,sticky="w")
File_play.grid(row=3,column=2,columnspan=1,sticky="e")
grid system does not allow to fill half the grid.
best to do is make a new frame without a highlighted boarder, place them just below the row 2 in that frame add your two button.
bottonframe = Frame(root)
bottoframe.grid(row = 3, columnspan=3, width = <as per your window>)
Date_play = Button(buttonframe,<your button config>)
File_play = Button(buttonframe,<your button config>)
Date_play.grid(row=1,column=1,sticky="w")
File_play.grid(row=1,column=2,sticky="e")
and then little bit adjustment.

How can i attach my scroll bar to my text box on tkinter?

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...

How do I align something to the bottom left in Tkinter using either .grid() or .pack()?

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:

Categories