My title impacts the button on my tkinker gui - python

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.

Related

Tkinter Text scroll lag issue

I have this super simple implementation of a textBox:
root = Tk()
root.geometry('1650x900')
center_windows(root)
root.resizable(0, 0)
scrollbar = Scrollbar(root)
old_xml_text = Text(root, wrap=WORD, yscrollcommand=scrollbar.set, height=40, width=60)
old_xml_text.grid(row=0, column=0,pady=(100,0),padx=(50,50),sticky='we')
scrollbar.config(command=old_xml_text.yview)
The problem is that if I paste there a long text (2k lines) it became extremely laggy during scrolling.
How can I solve this?
If there is no solution using Tkinter, is there any other way to achieve this using other package (in Python)? I don't want any kind of lag when I past or scroll the text. Am I forced to use C/C++ ?
Any suggestion appreciated.
The problem lies in the computation time it takes the Text widget to insert all line breaks and thereby to compute the total number of lines and the current position. While scrolling, this computation is too slow and you get lags and the scrollbar is rendered useless.
If you want to speed it up and remove the lags, you have to insert line breaks manually, so that no line extends the 60 character width of your text window. If you insert line breaks and don't pass it to the wrapper, it won't lag. See the following example for reference:
from tkinter import *
root = Tk()
root.geometry('800x600')
#center_windows(root)
root.resizable(0, 0)
scrollbar = Scrollbar(root)
old_xml_text = Text(root, wrap=WORD, yscrollcommand=scrollbar.set, width=60,height=10)
old_xml_text.grid(row=0, column=0,pady=(100,0),padx=(0,0),sticky=N+S+E)
scrollbar.config(command=old_xml_text.yview)
scrollbar.grid(row=0,column=1,pady=(100,0),sticky=N+S+W)
scrollbar2 = Scrollbar(root)
old_xml_text2 = Text(root, wrap=WORD, yscrollcommand=scrollbar2.set, width=60,height=10)
old_xml_text2.grid(row=2, column=0,pady=(100,0),padx=(0,0),sticky=N+S+E)
scrollbar2.config(command=old_xml_text2.yview)
scrollbar2.grid(row=2,column=1,pady=(100,0),sticky=N+S+W)
old_xml_text.insert(END,"Hello World, this is a test of reaction times\n"*1000)
old_xml_text2.insert(END,"Hello World, this is a test of reaction times"*1000)
You can see that the Text widget with line breaks is perfectly well scrollable while the one that uses the Text widget wrapper is not.

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.

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)

Python tkinter: button disappearing after label update

I've been using Python for quite some time now and I made a few applications with GUI's. When I was writing my new application I came across some behaviour of tkinter that I think is just strange.
Consider the following code:
from tkinter import *
root = Tk()
root.geometry('200x200')
label = Label(root, bg='green', text='0', font=('arial', 40, 'bold'))
label.place(x=0, y=0, width=200, height=200)
def add():
label['text'] = int(label['text']) + 1
if label['text'] == 10:
button.place_forget()
button = Button(root, command=add, text='+1', font=('arial', 20, 'bold'))
button.place(x=50, y=50, width=100, height=100)
root.mainloop()
As you would expect, when you run this code you will get a small window with a green background and a button. After you pressed the button 10 times, it disappears, and a '10' is show in the window.
The problem I encountered occures when I use a different parent widget for the button widget. For example, when I change this line
button = Button(root, command=add, text='+1', font=('arial', 20, 'bold'))
to
button = Button(label, command=add, text='+1', font=('arial', 20, 'bold'))
replacing 'root' with 'label', my gui just glitches out. Every time I press the button it disappeares. Sometimes it reappears after a few seconds but sometimes it only reappears when I try to click on it.
After some more testing I found out the button disappears every time the parent label updates.
I was wondering; Why is this happening? And is there a way to fix the problem without using 'root' as the parent for button (this would make my application a lot more complicated, or would at least force me to rebuild a lot of the gui stuff)
I tried to find information about this problem, but I couldn't find any.
I don't think there's a good reason for why you are seeing this behavior. I don't see it on OSX, but the, on OSX buttons behave a bit differently than other platforms. It should be perfectly fine to use a label as a parent to another window without seeing this flickering.
One possible workaround might be to call lift on the button widget whenever you reconfigure the label. Perhaps the stacking order is changing on you, causing the label to be above the button.
Finally, are you aware you can use place with relative coordinates, and that widgets can be relative to other widgets even if there is no parent/child relationship? You seem concerned that you'll have to change a lot of code if you can't create the two widgets in a parent/child relationship.
For example, you can create your widget and call place like this:
button = Button(root, command=add, text='+1', font=('arial', 20, 'bold'))
button.place(in_=label, relx=0, rely=0, relwidth=1, relheight=100)
You'll need to make sure the stacking order is correct. The easiest way is to simply make sure the button is created sometime after creating the label.

Categories

Resources