How to make Scrollbar work in Tkinter frame? - python

I'm making a project where I have to display logs in a frame with the help of Tkinter. Here is my code for that particular frame.
# frame3 for logs
frame3 = Frame(
win,
bg='black',
width=310,
height=140,
padx=0,
pady=0)
frame3.pack(fill=X, expand=True, padx=(0, 10), pady=0)
frame3.pack_propagate(0) # stops frame from shrinking
scroll = Scrollbar(frame3)
scroll.pack(side = RIGHT, fill = Y)
The logs are generated and are printed in that frame. Here is the code for generating and printing logs
logs = Label(frame3, text = (time.ctime()), font=("Consolas", 9), bg="#000000", fg="#ffffff")
logs.pack(pady=(0, 0))
The scrollbar is showing but it is somehow not working. The scroll is sliding if I click and slide it with the mouse. I guess there are 3 types of scrollbars in Tkinter (Correct me if I'm wrong).
window scrollbar.
Frame scrollbar.
Label Scrollbar (not sure about that).
I think the problem is that I made is a scrollbar for a frame. But, I need it for Label. Or is there any way by which I can print logs directly onto the frame? Don't know what the actual problem is. Also, is there a way by which I can make it auto scrollable when the logs are generated?
Any help would be greatly appreciated. Thanks in advance.

Here is an example using tkinter.scrolledtext:
from tkinter import *
from tkinter import scrolledtext
root = Tk()
txt = scrolledtext.ScrolledText(root)
txt['font'] = ('consolas', '12')
txt.pack(expand=True, fill='both')
txt.configure(state=DISABLED)
def log(data):
txt.configure(state=NORMAL)
txt.insert(END, data+'\n')
txt.configure(state=DISABLED)
log('abc')
log('abcde')
root.mainloop()
Hope that's helpful!

.see("end") method helps autoscroll.

Related

My title impacts the button on my tkinker gui

Here is my code
from tkinter import *
root = Tk()
root.geometry('500x500')
btn = Button(root, text = 'Play', height=5,width=30, command = root.destroy)
btn.place(x=140, y=200)
w = Label(root, text ='Lost', font=("Courier", 50), height=4)
w.pack()
root.mainloop()#
The button is meant to say play on it
This is a side effect of several things. What's happening here is that the text in your label is being centered vertically in a box with room for 4 lines. That text has opaque background, so the bottom of text box is sitting over the top of your button and hiding the text. If you remove height=4, you'll see that it works just fine.
The other problem here is mixing the placement tools. You are mixing place and pack, and that is going to cause trouble. You may need to think about the layout issues some more.

Frame-size does not show up anymore after using grid_forget() - Python tkinter

I was testing a method to hide and show frames by pressing a button (the buttons will be a menu bar later). So I created this code:
import tkinter as tk
from tkinter import *
win = Tk()
win.geometry("275x350")
win.title("MyProgram")
win.configure(background="white")
frame1 = Frame(win, width=200, height=200)
frame1.grid_propagate(False)
frame2 = Frame(win, width=200, height=200)
frame2.grid_propagate(False)
Label(frame1, text="Hello world", font="20").grid()
Label(frame2, text="Zweiter frame", font="20").grid()
def runGrid(run, destroy):
run.grid(row=1, column=2)
destroy.grid_forget()
def run2nd(run, destroy):
run.grid(row=1, column=2)
destroy.grid_forget()
Button(win, text="Run", command=lambda:runGrid(frame1, frame2)).grid(row=0, column=0)
Button(win, text="Run 2nd", command=lambda:run2nd(frame2, frame1)).grid(row=0, column=1)
win.mainloop()
So here is the problem...
After pressing the first button, the first frame comes up in his wanted size. After pressing the 2nd button, the 2nd frame comes up in his wanted size. But when you press the first button again (after pressing both buttons once before) then the frame is just showing up like grid_propagate was removed from the code (the frame is just as big as the label in it). Can someone explain me the fault in my code which is causing the problem?
Thanks a lot ;)
I found an other way to get what I want:
By simply using grid_remove() instead of using grid_forget() it is working.
But I still hope someone can answer my question because it really should work with grid_forget() as well I think.

How to implement a Scrollbar on a list of Entry with tkinter?

I am currently trying to make a scrollable list of entries using tkinter in Python 3. While looking for some documentation, I found this: Adding a scrollbar to a group of widgets in Tkinter. It is really great and works really fine with Labels, but it doesn't seem to work with Entries. You'll find right here my code which creates a 2x25 list of entries through which I would like to be able to scroll:
import tkinter as tk
class MainPage(tk.Frame):
def __init__(self, racine):
super().__init__(master=racine)
self.grid()
self.entriesCanvas = tk.Canvas(self, borderwidth=0, background="white")
self.entriesFrame = tk.Frame(self.entriesCanvas, background="white")
self.scrollbar = tk.Scrollbar(self, command=self.entriesCanvas.yview)
self.entriesCanvas.configure(yscrollcommand=self.scrollbar.set)
self.entriesCanvas.grid(column=0, row=2, columnspan=2)
self.scrollbar.grid(column=3, row=2, sticky='ns')
# self.entriesFrame.grid()
self.entriesCanvas.create_window((0, 0), window=self.entriesFrame,
anchor='nw', tags='self.entriesFrame')
# self.entriesFrame.grid()
self.entriesCanvas.bind('<Configure>', self.onFrameConfigure)
self.entries = []
for i in range(50):
self.entries.append(tk.Entry(self.entriesFrame, font=('arial', 30)))
self.entries[i].grid(column=i % 2, row=i//2)
def onFrameConfigure(self, event):
self.entriesCanvas.configure(scrollregion=self.entriesCanvas.bbox("all"))
if __name__ == "__main__":
root = tk.Tk()
mainPage = MainPage(root)
root.mainloop()
Notice I commented two lines out. If you "activate" the first line, there will be a scrollbar and one can scroll through the entries, but it is strangely zoomed. On the other hand, if you "activate" the second line, the GUI will be as I would like it to be, but without the possibility to scroll, and it seems to show all entries (even if there are 1000 entries, therefore making a window which is 20 times the size of your screen).
Do you know where my mistake is?
Okay, so I found a way to have my program doing what I want. I just changed the method
def onFrameConfigure(self, event):
self.entriesCanvas.configure(scrollregion=self.entriesCanvas.bbox("all"))
by
def onFrameConfigure(self, event):
self.entriesCanvas.configure(scrollregion=self.entriesCanvas.bbox("all"), width=self.entriesFrame.winfo_width())
(I basically only added a parameter to ask the canvas to be the width of the frame.)
I don't know if it is perfect (as I still use .grid() istead of .pack()), but it works.
Thank you for giving me the source Tkinter: How to get frame in canvas window to expand to the size of the canvas?, it really helped me find where my mistake was.
I truely apologise for my English, I know I make a lot of mistakes.

Make a Tkinter element on top of the others in Python

I'm searching for a way to put one element of Tkinter on top of the others in Python.
In the example below, what I tried to do is to put the yellow label on top of the white one - so when we change the size of the window the first label that will disappear is the white one, and only when its no longer visible the yellow one will start to shrink.
How can I realize this idea? Thanks in advance! (;
The code:
import tkinter as tk
root = tk.Tk()
root.config(background='black')
regularlabel = tk.Label(root, width=20, height=10, text='label')
regularlabel.pack()
bottomlabel = tk.Label(root, text='bottom label', bg='yellow')
bottomlabel.pack(side='bottom', fill='both')
root.mainloop()
Tkinter will shrink widgets in the reverse order of which they were added. Pack the bottom window first to solve your problem.
Since the layout of widgets tends to be changed more than the actual widgets during development, I find the code easier to understand and easier to maintain when layout is separate from widget creation. In the following example I've grouped the two layout statements together.
import tkinter as tk
root = tk.Tk()
root.config(background='black')
regularlabel = tk.Label(root, width=20, height=10, text='label')
bottomlabel = tk.Label(root, text='bottom label', bg='yellow')
bottomlabel.pack(side='bottom', fill='both')
regularlabel.pack()
root.mainloop()

tkinter - Attach scrollbar to widget for Text Adventure

I'm relatively new to Python and coding in general, so I'm a bit rubbish with most of the terminology.
I've researched this myself but I'm still relatively unsure (kept messing up), so hope someone can help me.
I'm looking to attach the scrollbar within my code to the right side of the text widget, rather than having it floating around the bottom corner.
My project is a text adventure (learning Python along to a book), and I have been building a very basic GUI to house the game. Essentially the text box here is placeholder, and it'll be replaced with the game code down the line, with graphics making up the rest of the window surrounding the center text/command prompt. I'm assuming doing this would be doable relatively easily?
I'm happy to work out just how to sort the scrollbar currently, as it's helping me learn!
Thanks guys!
from tkinter import *
root = Tk()
root.title("GAME TITLE")
mainframe = Frame(root, width=720, height=540)
mainframe.pack()
gametext = Text(root, width=75, height=15)
gametext.place(relx=0.5, rely=0.7, anchor=CENTER)
scrollbar = Scrollbar(root, command=gametext.yview)
gametext.config(yscrollcommand=scrollbar.set)
scrollbar.pack(side=RIGHT, fill=Y)
gametext.tag_configure('fonttype1', font = ('Arial', '12', 'bold'))
quote = """GAMEPLAY TEXT HERE"""
gametext.insert(END, quote, 'fonttype1')
root.mainloop()
Sample Screenshot of code running
If all you're using is a text widget and scrollbar, use pack for both. place is best used very, very rarely.
scrollbar.pack(side=RIGHT, fill=Y)
gametext.pack(side=LEFT, fill=BOTH, expand=True)

Categories

Resources