Python - Tkinter Event Generation - python

I am doing a GUI using for my code and finding it hard to develop what i want.
First ...
on the window an image and label appear and disappear after couple of seconds. after that a frame should arrive, followed by a menu option, when the menu option is selected it should disappear from frame and another image should appear.
self.gui = Tk()
def configure_window(self):
self.gui.geometry('700x500')
self.gui.resizable(height=False, width=False)
self.gui.update()
self.welcome_label()
self.welcome_image()
def welcome__image(self):
image = Image.open(image path)
photo = ImageTk.PhotoImage(image)
welcome_image = Label(master=self.gui, image=photo, justify='center',relief='raised')
welcome_image.image = photo
welcome_image.pack(padx=100, pady=100)
welcome_image.place(bordermode='outside', x=200,y=100)
welcome_image.after(ms=1000, func=welcome_image.place_forget)
def welcome_label(self):
welcome_label = Label(master=self.gui, text=welcome_label_text,font=welcome_label_font, justify='center',
state='active', fg='blue', anchor='center', pady=10, relief='raised' )
welcome_label.place(x=100, y=350)
welcome_label.after(ms=1000, func=welcome_label.place_forget)
def first_frame(self):
self.first_frame = LabelFrame( master = self.gui,text='Select First File',font= 'arial 10 bold underline', bg=self.background_colour,
height=200,width=690, bd=1, padx=5, pady=5)
self.first_frame.pack()
self.first_frame.place(x=0, y=0)
def select_button1(self):
self.file_open_button1 = Button(master=self.first_frame,text='...',state='disabled',command=self.cmd_file_select_button1)
when i run the code, welcome_image and welcome_frame places and forgets places after 1000 ms, but, first_frame also loads with parent widget. i want frame to arrive after the welcome_label disappears.
and the same sequence continues for LabelFrame
i have widgets in LabelFrame in which i have OptionMenu and button, i want optionMenu to disappear when user selects an option and another button should appear, same sequence in the button, button returns some sting and a label should appear in the place of button etc.
how to generate the sequence e.g. if an widget has place_forget() a sequence will be generated and another widget should be bind on that sequence. please help.
apology, if i am unable to make you understand my problem.

Related

Tkinter: How to resize a scroll bar if the canvas changes size?

I am working on a project where I need to display information when a button is clicked, and hide information when that button is clicked again. The information can be several rows and extend beyond the window, so I am trying to add a scroll bar to get around this issue. The problem is that when the information is displayed, the scroll bar does not show. Scrolling is still possible but the actual bar is not there. Resizing the window fixes this issue for some reason. Also when the button is clicked again to hide the information, the size of the canvas and the scrollbar remain the same, so you can scroll far beyond the button into empty space. My theory is that the scroll region is not updating when the widgets in the canvas change size - but I'm not sure how to go about fixing that.
I realize this explanation may be a bit confusing, so I have provided a simplified example below. This example has a single button that when clicked reveals several lines of "other info". The scrollbar and/or canvas does not resize properly upon interacting with this button.
My strategy right now was to have a method called add_scrollbar that removes the current scrollbar and creates a new one every time the widgets change in hopes that the new one would be the right size; however this still is not working.
from tkinter import *
from tkinter import ttk
def add_scrollbar(outer_frame, canvas):
if len(outer_frame.winfo_children()) == 2:
# canvas is at index 0 of the outer frame, if a scrollbar has been added it will be at index 1
outer_frame.winfo_children()[1].destroy()
# my strategy here was to destroy the existing scroll bar
# and create a new one each time the widget changes size
scrollbar = ttk.Scrollbar(outer_frame, orient=VERTICAL, command=canvas.yview)
scrollbar.pack(side=RIGHT, fill=Y)
canvas.configure(yscrollcommand=scrollbar.set)
canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
return
def create_example():
root = Tk()
root.geometry("1200x1200")
my_outer_frame = Frame(root)
my_outer_frame.pack(fill=BOTH, expand=1)
my_canvas = Canvas(my_outer_frame)
my_canvas.pack(side=LEFT, fill=BOTH, expand=1)
inner_frame = Frame(my_canvas)
my_canvas.create_window((0, 0), window=inner_frame)
# ^^^ Sets up the ability to have a scroll_bar
changing_frame = Frame(inner_frame, borderwidth=4) # this is the frame that will be changing its contents
changing_frame.pack(side=LEFT, anchor="n")
display_frame(changing_frame, my_outer_frame, my_canvas)
# this method re-displays the changing frame depending on the specified size ('big' or 'small'
root.mainloop()
return
def display_frame(frame, outer_frame, canvas, size='small'):
for widget in frame.winfo_children():
widget.destroy()
if size == 'small':
Button(frame, height=5, width=5, text="Show",
command=lambda this_frame=frame: display_frame(this_frame, outer_frame, canvas, size='big')).grid(row=0,
column=0)
elif size == 'big':
Button(frame, height=5, width=5, text="Hide",
command=lambda this_frame=frame: display_frame(this_frame, outer_frame, canvas, size='small')).grid(
row=0, column=0)
for n in range(1, 100):
Label(frame, text="Other Stuff!").grid(row=n, column=0)
frame.pack(side=LEFT)
add_scrollbar(outer_frame, canvas) # this method is supposed to destroy the existing scrollbar and make a new one
return
if __name__ == '__main__':
create_example()

How To Multiply / Divide Entry Box With A Number, tkinter

Hey im pretty new to python and im taking a class in high school. For an assignment im working on we have to make a tkinter gui that includes the widgets, label, buttons, entry box, radio or check buttons, frames, and a display box. I am making a kilometers to miles converter that can do the opposite if chosen, there will be radio buttons that the user can choose to choose which one they would like to calculate, but i am having a lot of trouble on the calculation part because i cant get the entry box number to multiple or divide by 1.609 or any number.
Heres the code i have now, I apologize for the mess and how bad it probably
import tkinter as tk
import tkinter.messagebox
# Customize main window
root = tk.Tk()
root.title('GUI Assignment')
# Create the frames, right, left, and bottom, and pack them
bframe = tk.LabelFrame(root, highlightthickness=0, borderwidth=0, padx=100, pady=50)
bframe.pack(side='bottom')
rframe = tk.LabelFrame(root, highlightthickness=0, borderwidth=0, padx=100, pady=50)
rframe.pack(side='right')
lframe = tk.LabelFrame(root, highlightthickness=0, borderwidth=0, padx=100, pady=50)
lframe.pack(side='left')
# Make the label and the entry box for the right frame
dlabel = tk.Label(rframe, text = 'Enter the distance', )
dentry = tk.Entry(rframe, width=75)
# Pack the label and entry
dlabel.pack(side='left')
dentry.pack(side="right")
dist = 3.0
temp =(dentry.get())
# Create the convert command
def convert():
if radio_var.get()==1:
tkinter.messagebox.showinfo('Distance',temp / dist )
# Make the convert and quit buttons
b = tk.Button(bframe, text="Convert", command=convert)
quit = tk.Button(bframe, text='Quit', command=root.destroy)
# Pack the buttons
b.pack(side='left')
quit.pack(side='right')
# Make the radio variable
radio_var = tk.IntVar()
radio_var.set(1)
# Make the radio buttons for the left frame
rb = tk.Radiobutton(lframe, text='Km to Miles', variable=radio_var, value=1)
rb2 = tk.Radiobutton(lframe, text='Miles to Km', variable=radio_var, value=2)
# Pack The Radio Buttons
rb.pack()
rb2.pack()
root.mainloop()
The issue you're having here is that you're trying to divide temp, a string, by dist, a float. You need to convert temp to a float before converting it using float(temp). Also, since you set temp once during your script, it will only ever refer to the value that was in the input box as soon as the variable was assigned. In order to fix this, you have to call dentry.get() inside of your convert() function rather than outside of it.

Add label to Tkinter button

I'm trying to add a label to a Tkinter button. A Tkinter button has a 'text' attribute which is great. However I need another similar text field on the button, i.e 2 text fields per button. So I would like to add a label as a child to the button. The problem with this is that it creates unpredictable behaviour. Actuating the button or even just hovering the mouse over the label causes the label to vanish.
button_1 = tk.Button(canvas, text='Take',command='take',width='12')
button_1.pack()
label_1 = tk.Label(button_1, text='Stream 1',font=('calibre',8))
label_1.pack()
label_1.place(x=10, y=10)
I can avoid this unwanted behaviour by adding the label to the same parent as the button.
label_1 = tk.Label(canvas, text='Stream 1',font=('calibre',8))
But by doing this I loose the convenience of positioning the label with the button's geometry, e.g inset by 10 pixels from left and 10 pixels from top of button. I plan to make a convenience method for adding hundreds of such buttons, and do not wish to be attempting to calculate each label in the parents coordinates. And besides, as a sub-child of the button, it becomes part of the button hierarchy, i.e. will move with the button, will be hidden with the button etc.
You can display multiple lines of text on a Button by embedding newlines in the text.
Like this:
import tkinter as tk
root = tk.Tk()
root.geometry('100x100')
canvas = tk.Canvas(root)
canvas.pack()
button_1 = tk.Button(canvas, text='Take\nStream 1',command='take',width='12')
button_1.pack()
#label_1 = tk.Label(button_1, text='Stream 1',font=('calibre',8))
#label_1.pack()
#label_1.place(x=10, y=10)
root.mainloop()
Result:
You can use the anchor and justify options to change the positioning of the text on the Label:
button_1 = tk.Button(canvas, text='Take\nStream 1', command='take', width='12',
anchor='w', justify='left')
button_1.pack()
Result 2:

How to display widgets on a frame that is mounted on canvas in Tkinter?

I created a main root with two frames.
-One frame is for program toolbar.
-Other frame is for canvas where data will be displayed and a scrollbar widget.
-Inside of the canvas is a third smaller frame which will be used for scrolling trough data.
However, when I try to define new widgets and place them on that third smaller frame, nothing happens. I'm defining new widgets inside of a function call of a button command. I have also tried declaring everything as global variables but without luck.
Hint: I tried placing the code from the function to the top level of the code and it works. Also, if I try to mount these widgets on the toolbar frame it also works. It seems that the only thing I can't do is to mount these new widgets on the small frame that is inside the canvas.
I used a simple for loop to create labels just for testing.
Could anyone tell what I am doing wrong?
from tkinter import *
from tkinter import ttk
#Creating main window
root = Tk()
root.resizable(width=False, height=False)
#Defining Background
toolbar = Frame(root, width=613, height=114)
toolbar.grid(row=0, column=0)
background_frame = Frame(root, width=615, height=560)
background_frame.grid(row=1, column=0)
background = Canvas(background_frame, width=615, height=560)
background.pack(side=LEFT, fill=BOTH, expand=1)
scroll_bar = ttk.Scrollbar(background_frame, orient=VERTICAL, command=background.yview)
scroll_bar.pack(side=RIGHT, fill=Y)
background.configure(yscrollcommand=scroll_bar.set)
background.bind('<Configure>', lambda e:background.configure(scrollregion = background.bbox('all')))
second_frame = Frame(background)
background.create_window(150,100, window=second_frame, anchor='nw')
def confirm1():
for x in range(100):
Label(second_frame, text = x ).grid(row=x, column=1)
show_labels = Button(toolbar, text= "Show labels", fg="black", command=confirm1)
show_labels.grid(row=0, column=2)
root.mainloop()
Picture of the app so far
I surely can't reproduce the issue with your current code, but looking at the previous edit it is pretty clear what your problem is.
(taken from your previous edit)
def confirm1():
global background_image1
background.delete('all') # <--- this line of code
for x in range(100):
Label(second_frame, text = x ).grid(row=x, column=1)
Here you delete all your items from your canvas:
background.delete('all')
hence no item appears.
You should instead delete only those items that you want to remove by passing the id or tags to delete method. You can delete multiple items together at once by giving the same tags.
Another option would be to recreate the frame item again on canvas using create_window (Do note: your frame is not deleted/destroyed, it's only removed from canvas)

When an entry box is present, a button does not show up

I have been doing some work in python and have came across Tkinter which is very useful for my project. I was in the process of making a screen where there is a button and a text entry box however when the text entry box is present, no button shows up. However when I remove the entry box, I can see the button.
Here is the part of the script I've been working on:
Hi, I have been doing some work in python and have came across Tkinter which is very useful for my project. I was in the process of making a screen where there is a button and a text entry box however when the text entry box is present, no button shows up. However when I remove the entry box, I can see the button.
from tkinter import *
def submit1():
print("working");
def password1():
passwordbox= Tk()
passwordbox.title("Password Verification")
passwordbox.configure(background="white")
passwordbox.geometry("1000x1000")
box1 = Entry(passwordbox, width=200, bg="gray")
box1.grid(row=2000, column=10, sticky=W)
submit = Button(passwordbox, text="Submit", width=20, height=5,
bg="black", fg="white", command=submit1)
submit.grid(row=1000, column=15, sticky=W);
password1()
The text box should show to entry box and the button however it only shows the button
If the entry box code was # out, the button will work
Anyone got any ideas?
You need to add a line passwordbox.mainloop() at the end of password1 definition. Also you need to specify row and column of the grid properly.
Set Entry box to row 0 and column 0
Set Submit button to row 1 and column 0
from tkinter import *
def submit1():
print("working");
def password1():
passwordbox= Tk()
passwordbox.title("Password Verification")
passwordbox.configure(background="white")
passwordbox.geometry("1000x1000")
box1 = Entry(passwordbox, width=200, bg="gray")
box1.grid(row=0, column=0, sticky=W)
submit = Button(passwordbox, text="Submit", width=20, height=5,
bg="black", fg="white", command=submit1)
submit.grid(row=1, column=0, sticky=W);
passwordbox.mainloop()
password1()

Categories

Resources