Adding images to toplevel window - python

I'm trying to add an image in a Top Level window in python, however I can't seem to get it working.
I've tried using canvases and following some other steps on stack overflow. One thing I haven't tried is using class, init and self, but I don't really understand that, and hoping I can acheive my thing without the use of self. and stuff like that :D.
def pika():
def close():
win.destroy()
win = Toplevel()
win.geometry("150x150")
win.title("I CHOOSE U")
yellowb = Label(win, bg = 'yellow', fg = 'yellow', padx = 100, pady = 100)
yellowb.pack()
poke = PhotoImage(file = "pika.gif")
pika = Label(image = poke) # REEEEEEEEEEEEEEEEEE IT NO WORKEY
pika.grid(row = 0, column=1, padx = 10, pady = 10)
button = Button(win, text = "Close", command = close)
button.place(x=49, y=130)
Heres the main windows code
win = Tk()
win.geometry("290x200")
win.title('Error')
text1 = Label(win, bg= "Cyan", fg = 'Teal', padx = 50, pady = 75, text = '#hash error',
font = ('Times', '40', 'bold'))
text1.place(x=win.winfo_width() / 2, y=win.winfo_width() / 2)
button1 = Button(win, text = 'green', command = green)
button1.place(x=40, y=160)
button2 = Button(win, text = 'blue', command = blue)
button2.place(x=90, y=160)
button3 = Button(win, text = "red", command = red)
button3.place(x=130, y=160)
button4 = Button(win, text = 'yellow', command = yellow)
button4.place(x=170, y=160)
button5 = Button(win, text = "orange", command = orange)
button5.place(x=229, y=160)
eggs = PhotoImage(file = "pika.gif")
eggpic = Button(win, image = eggs, bg = 'Cyan', fg = 'Cyan', command = pika)
eggpic.place(x=100, y=20)
def close():
win.destroy()
closebut = Button(win, text='close', command = close)
closebut.place(x=0, y=0)
When I click a button and it opens a new windows the bg of the windows is yellow and everything as intended, however the image doesn't appear on the windows, and a white box the size of the image appears in the main tk window.
https://imgur.com/a/XU5m3Se

You can have two problems:
First: Every widget needs parent. If you don't use it then tkinter assigs widget to main window.
And you have this problem in Label(image = poke) because you forgot win in
pika = Label(win, image=poke)
This is why you see rectangle in main window instead of toplevel window.
Second: There is bug in PhotoImage. Garbage Collector removes it from memory when it is created in function and assigned to local variable. And then you can see empty image.
You have to assign PhotoImage to global variable or assign to other widget in function.
Popular solution with assigning to other widget:
poke = PhotoImage(file = "pika.gif")
pika = Label(win, image=poke)
pika.photo = poke # <-- assign PhotoImage to other widget too
More: PhotoImage

Related

How can I run python script inside a frame in tkinter?

I have a function that asks the user to answer a couple of question which prints out a result I have written my code inside a function called Script and I made it so when I press a button the function runs but in my terminal while I want it to run inside the frame I created
Here is my code:
from tkinter import *
def Script():
#My script/code is written here
root = tk.Tk()
root.configure(background = "#110a60")
canvas = tk.Canvas(root, height = 750, width = 800, bg = "#110a60")
canvas.pack()
root.resizable(False, False)
frame = tk.Frame(root, bg = "black")
frame.place(relheight = 0.8, relwidth = 0.8, relx = 0.1, rely = 0.1)
start_button = Button(root, text = 'Start Program', padx = 10, pady = 5, fg = "#FFFF00", bg = "#012456", command = Script)
start_button.place(x = 350, y = 680)
exit_button = Button(root, text = 'Exit', padx = 20, pady = 5, fg = "#FFFF00", bg = "#012456", command = exit)
exit_button.place(x = 368, y = 714.5 )
root.mainloop()
So how can I make it when I press the Start program button the text and input outputting to the terminal/console be printed inside the frame I made(inside the red borders)
And Thanks in advance
Simple answer: You can't. print() is for the console.
More elaborate answer:
You'll probably need a Label() widget for your questions and a Entry() widget for user input. Also your script() function should not print but return a string which you can then display in a Text() widget.
Edit (added some code to your code to get you going):
from tkinter import Tk, Canvas, Frame, Button, Label, Entry, StringVar, Text
def my_script():
questions=["What is your name?",
"What is your age?"]
answers = []
answer_box.config(background='grey')
answer_box.focus()
for question in questions:
question_label.config(text=question)
answer_box.wait_variable(answer_given)
answers.append(answer_box.get())
answer_box.delete(0, 'end')
answer_box.focus()
for answer in answers:
print_area.insert('end', answer+"\n")
root = Tk()
root.configure(background = "#110a60")
canvas = Canvas(root, height = 750, width = 800, bg = "#110a60")
canvas.pack()
root.resizable(False, False)
frame = Frame(root, bg = "black")
frame.place(relheight = 0.8, relwidth = 0.8, relx = 0.1, rely = 0.1)
start_button = Button(root, text = 'Start Program', padx = 10, pady = 5, fg = "#FFFF00", bg = "#012456", command = my_script)
start_button.place(x = 350, y = 680)
exit_button = Button(root, text = 'Exit', padx = 20, pady = 5, fg = "#FFFF00", bg = "#012456", command = exit)
exit_button.place(x = 368, y = 714.5 )
question_label = Label(frame, text="", bg='black', fg='white')
question_label.place(relx=0.5, y=80, anchor='center')
answer_given = StringVar()
answer_box = Entry(frame, bg='black', borderwidth=0)
answer_box.place(relx=0.5, y=110, anchor='center')
answer_box.bind('<Return>', lambda x: answer_given.set("foobar"))
print_area = Text(frame, bg='black', fg='white')
print_area.place(relx=0.5, y=180, height=300, width=500, anchor='n')
root.mainloop()

I want to change the background color of the button when I click in tkinter GUI

I have a python GUI code to open and close. I need to modify the code like when I press the open button the button colour turns into green and when I press close button the open button colour changes to its default colour.
from serial import*
from time import*
from tkinter import*
window = Tk()
def open_command():
print("Opening")
def close_command():
print("Closing")
b = Button(window, text = "Open", font = ("Times New Roman", 12), fg = "green", bg = "white", height = 1, width = 5, command = open_command).pack()
b = Button(window, text = "Close", font = ("Times New Roman", 12), fg = "red", bg = "white", height = 1, width = 5, command = close_command).pack()
mainloop()
when clicking open button colour of open button needs to change from its default colour to green. If we click close button close button colour needs to change red and open button colour changes to its default colour.
You can simply use .config(bg=...) to change the background color of the button to whatever color you want as below:
import tkinter as tk
window = tk.Tk()
def open_command():
open_btn.config(bg='green')
close_btn.config(bg='white')
def close_command():
open_btn.config(bg='white')
close_btn.config(bg='red')
font=('Times New Roman', 12)
open_btn = tk.Button(window, text='Open', font=font, fg='green', bg='white', width=5, command=open_command)
open_btn.pack()
close_btn = tk.Button(window, text='Close', font=font, fg='red', bg='white', width=5, command=close_command)
close_btn.pack()
window.mainloop()

Python, Tkinter how to give optionmenu its own windows when pressed

I have a drop down menu girded on my calculator and i have it set so that there is 3 menu items. What i want to happen is that when one of the menu items is selected it opens a toplevel window describing that item menu and each one is a different menu because they contain different things how can i code this to happen. Im stuck with setting it so that it opens different window for when a different one is slected.
def change_dropdown(*args):
top = Toplevel()
top.title("READ")
toplabel = Label(top,text= "Lmao", font = ("Helvetica", 13))
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = ("Helvetica", 10, "bold"), fg = "ghostwhite", bg = "black", width = "30", height = "2", command=top.destroy)
button.grid()
top.focus()
def popmenu():
global tkvar
tkvar = StringVar(master)
choices = {"About","Colour themes", "Contact",}
popupMenu = OptionMenu(master, tkvar, *choices)
popupMenu.grid(row = 0, column = 0, columnspan = 5, sticky=W+E+S+N)
tkvar.set("About")
tkvar.trace("w", change_dropdown)
As far as I can understand, you want something like this...
def change_dropdown(*args):
if tkvar.get() == "About":
# open About window
elif tkvar.get() == "Contact":
# open Contact window
...., etc
Complete example
Each Toplevel window is a window like the root window and you put widgets on it just like on master.
I changed the code a bit to make it more readable from my point of view; I lifted the main window (master) code from the function. I put font specs in the beginning to make the Labels and Buttons code shorter. I changed the Dict choices to a Tuple which feels more natural. I gave the OptionMenu a width to keep it from changing size with chosen selection.
from tkinter import *
master = Tk()
master.geometry('300x150+1000+50')
info = Label(master, text='Press "p" for popup menu')
info.pack()
# Fonts
H13 = ("Helvetica", 13)
H10B = ("Helvetica", 10, "bold")
def change_dropdown(*args):
top = Toplevel()
if tkvar.get() == "About": # About window
top.title("About")
toplabel = Label(top,text= "The About window", font = H13)
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = H10B,
fg = "ghostwhite", bg = "black", width = "30",
height = "2", command=top.destroy)
button.grid()
top.focus()
elif tkvar.get() == "Contact": # Contact window
top.title("Contact")
toplabel = Label(top,text= "Contact form", font = H13)
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = H10B,
fg = "ghostwhite", bg = "black", width = "30",
height = "2", command=top.destroy)
button.grid()
top.focus()
elif tkvar.get() == "Colour themes": # Color themes window
top.title("Colour themes")
toplabel = Label(top,text= "Choose color theme", font = H13)
toplabel.grid()
button = Button(top, text="Dismiss", relief=FLAT, font = H10B,
fg = "ghostwhite", bg = "black", width = "30",
height = "2", command=top.destroy)
button.grid()
top.focus()
tkvar = StringVar(master)
def popmenu(event):
top = Toplevel()
choices = ("About","Colour themes", "Contact") # Tuple or List instead of dict
popupMenu = OptionMenu(top, tkvar, *choices)
popupMenu.config(width=15) # Otherwise width varies with option
popupMenu.grid(row = 0, column = 0, columnspan = 5, sticky=W+E+S+N)
tkvar.set("Pick one")
tkvar.trace("w", change_dropdown)
master.bind('p', popmenu)
master.mainloop()
This is a very simple interface, but if you plan on making it more complex I strongly suggest you read up on Object Oriented Python. Keeping track of globals gets difficult pretty quick.

Tkinter - How to display image when clicking a button?

First time here so forgive me as this is my FIRST attempt at making a silly GUI game (if you want to call it that). I'm trying to get the user to click a button and the image of their selection pops up. I can't seem to figure out how to get the image to pop up though.
Image does show if I run it separately.
My code:
from Tkinter import *
root = Tk()
class PokemonClass(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.WelcomeLabel = Label(root, text="Welcome! Pick your Pokemon!",
bg="Black", fg="White")
self.WelcomeLabel.pack(fill=X)
self.CharButton = Button(root, text="Charmander", bg="RED", fg="White",
command=self.CharClick)
self.CharButton.pack(side=LEFT, fill=X)
self.SquirtButton = Button(root, text="Squirtle", bg="Blue", fg="White")
self.SquirtButton.pack(side=LEFT, fill=X)
self.BulbButton = Button(root, text="Bulbasaur", bg="Dark Green",
fg="White")
self.BulbButton.pack(side=LEFT, fill=X)
def CharClick(self):
print "You like Charmander!"
global CharSwitch
CharSwitch = 'Yes'
CharSwitch = 'No'
if CharSwitch == 'Yes':
CharPhoto = PhotoImage(file="Charmander.gif")
ChLabel = Label(root, image=CharPhoto)
ChLabel.pack()
k = PokemonClass(root)
root.mainloop()
This works, but the actual image no longer shows, if I keep the PhotoImage OUT of the class it will print but I want to have it print IF they click the specific button:
from Tkinter import *
root = Tk()
class PokemonClass(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.WelcomeLabel = Label(root, text = "Welcome! Pick your Pokemon!", bg = "Black", fg = "White")
self.WelcomeLabel.pack(fill = X)
self.CharButton = Button(root, text = "Charmander", bg = "RED", fg = "White", command = CharClick)
self.CharButton.pack(side = LEFT, fill = X)
self.SquirtButton = Button(root, text = "Squirtle", bg = "Blue", fg = "White")
self.SquirtButton.pack(side = LEFT, fill = X)
self.BulbButton = Button(root, text = "Bulbasaur", bg = "Dark Green", fg = "White")
self.BulbButton.pack(side = LEFT, fill = X)
def CharClick():
print "You like Charmander!"
CharPhoto = PhotoImage(file = "Charmander.gif")
ChLabel = Label(root, image = CharPhoto)
ChLabel.pack()
k = PokemonClass(root)
root.mainloop()
You need to maintain a reference to your PhotoImage object. Unfortunately there is an inconsistency in tkinter in that attaching a Button to a parent widget increments the reference count, but adding an image to a widget does not increment the reference count. As a consequence at the moment the CharPhoto variable goes out of scope at the end of the function CharClick, the number of reference to the PhotoImage falls to zero and the object is made available for garbage collection.
If you keep a reference to the image somewhere, it will appear. When you kept it globally it remained in scope for the entire script and hence appeared.
You can keep a reference to it in the PokemonClass object or in the Label widget.
Below is the later of those options
from Tkinter import *
root = Tk()
class PokemonClass(object):
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.WelcomeLabel = Label(root, text="Welcome! Pick your Pokemon!",
bg="Black", fg="White")
self.WelcomeLabel.pack(fill=X)
self.CharButton = Button(root, text="Charmander", bg="RED", fg="White",
command=self.CharClick)
self.CharButton.pack(side=LEFT, fill=X)
self.SquirtButton = Button(root, text="Squirtle", bg="Blue", fg="White")
self.SquirtButton.pack(side=LEFT, fill=X)
self.BulbButton = Button(root, text="Bulbasaur", bg="Dark Green",
fg="White")
self.BulbButton.pack(side=LEFT, fill=X)
def CharClick(self):
print "You like Charmander!"
global CharSwitch
CharSwitch = 'Yes'
CharPhoto = PhotoImage(file="Charmander.gif")
ChLabel = Label(root, image=CharPhoto)
ChLabel.img = CharPhoto
ChLabel.pack()
CharSwitch = 'No'
k = PokemonClass(root)
root.mainloop()
The solution which helped me is just simply declaring all the image variables on the next line after 'root = Tk()'. Doing so won't spoil your code or anything.

Using Entry box with Tkinter in Grid manager?

I'm trying to make a basic GUI using Tkinter and have an entry box next to my label using a Grid manager, but the window is not showing when I run my program if I use .grid() with my Entry object.
It does work when I use .pack(), which is strange because I heard not to use .pack() when I have other things using .grid() in the same widget. But I do want to use .grid() because I want to be able to organize it how I want to.
Code is below, I'm having trouble with Entry object showName. The commented out .pack() statement is the one that does work, the .grid() statement is the one that does not work.
Does anybody know what's wrong with this?
from Tkinter import *
class RenamerGUI():
def __init__(self, master):
frame = Frame(master)
frame.pack() #Make frame visible
self.exit = Button(frame, text = "Exit", fg = "red", command = frame.quit)
self.csv2tsv = Button(frame, text = "csv2tsv", fg = "green", bg = "black", command=self.csv2tsv)
self.epguidestsvFormatter = Button(frame, text = "epguidestsvFormatter", fg = "green", bg = "black", command = self.epguidestsvFormatter)
self.epNamesList = Button(frame, text = "epNamesList", fg = "green", bg = "black", command = self.epNamesList)
self.SeasonSplitter = Button(frame, text = "SeasonSplitter", fg = "green", bg = "black", command = self.SeasonSplitter)
self.Renamer = Button(frame, text = "Renamer", fg = "green", bg = "black", command = self.Renamer)
self.showLabel = Label(frame, text = "Show: ")
self.showName = Entry(master)
self.get = Button(frame, text = "Get", command = self.textgetter)
self.exit.grid(row=3, column=4)
self.csv2tsv.grid(row=1, column = 0)
self.epguidestsvFormatter.grid(row=1, column=1)
self.epNamesList.grid(row=1, column=2)
self.SeasonSplitter.grid(row=1, column=3)
self.Renamer.grid(row=1, column=4)
self.showLabel.grid(row=2)
self.showName.grid(row=2, column=1)
#self.showName.pack(side=BOTTOM)
The entry has the wrong parent:
self.showName = Entry(master)
should be
self.showName = Entry(frame)

Categories

Resources