Tkinter: Window not showing image - python

I am new to GUI programming and recently started working with tKinter.
My problem is that the program won't show my image, I'm suspecing that it is my code that is wrong, however, I would like somone to exactly explain to me how i can make it work...
Here's my code:
from tkinter import * # Import the tkinter module (For the Graphical User Interface)
from PIL import ImageTk, Image
width = 1920
height = 1080
RootGeo = str(width) + "x" + str(height) # Make a def for RootGeo so the Root geometry isn't hardcoded
def MakeWindow():
# -----Root_Attributes-----
Root = Tk()
Root.geometry(RootGeo)
Root.state("zoomed")
# -----Root_Attributes, Root_Containers----- ### NOT WORKING ###
__DISPlAY__ = Image.open("Display.png")
__DISPLAY_RENDER__ = ImageTk.PhotoImage(__DISPlAY__)
Display_icon = Label(Root, image=__DISPLAY_RENDER__)
Display_icon.image = __DISPLAY_RENDER__
Display_icon.place(x=0, y=0)
# -----Root_Containers----- ### NOT WORKING ###
Root.mainloop()
MakeWindow()
Any and all help would be very appreciated.

try to change the image and check out if its still not showing up.
if its still not showing up, try to change this line:
__DISPlAY__ = Image.open("Display.png")
to
__DISPlAY__ = Image.open("Display.png").resize((600,800))
see if it would show up now then change the width and height as you like.

Pychamarm does not want to show the images, so to solve this problem i had to run the script from cmd every time...

Related

A countdown timer that runs in the background and interacts with other functions

I've been looking around for this but all the solutions feel extremely complex and even then I haven't been able to get it to work how I want it. I'm making a program that randomly opens an image from a folder, waits 10 seconds, then opens another random image from the same folder, and keeps going.
Simple enough, I was able to do it in a While True loop and making the "wait 10 seconds" part with time.sleep(10). But, I'd like to have a button that simply resets it whenever I feel like it. I'm doing this in tkinter and I have a button that starts it, but when I added a button to reset it, I haven't been able to click it and when I try to, the program crashes. That's because it's in the time.sleep(10) and the whole program stops for 10 seconds. For anyone curious about the code, here it is.
from tkinter import *
import random
import os
from PIL import Image
import time
root = Tk()
def AnmuViewer():
while True:
random_pic = (random.choice(os.listdir("D:/de_clutter/memez/anmu")))
openPic = Image.open('D:/de_clutter/memez/anmu/' + random_pic)
openPic.show()
time.sleep(10)
continue
def Restart():
AnmuViewer()
start_btn = Button(root, text = "Start", command = AnmuViewer)
start_btn.pack()
next_btn = Button(root, text = 'Restart', command = Restart)
next_btn.pack()
root.mainloop()
I know I don't need a "Restart" button as being able to click the "Start" button again would've done the same thing. Either way, that "Start" button itself is also unclickable.
I've looked into threading so I'm thinking of making a function that counts down from 10, and when it reaches 10, the AnmuViewer() starts over again, that way I can click "Start" again whenever and reset the whole code from scratch. But I just haven't been able to get that to work either. Any suggestions?
You can combine start and reset in the same button, but you can also add a reset button that calls the same function (commented code).
That is upon start, the system is reset to its initial state, here with the callback value set to None.
Most times, it is better to use tkinter.mainloop than a custom while loop. Using time.sleep in GUIs is usually a recipe for disaster as it blocks all interactivity during its execution.
I replaced the images with a text label for simplicity, you will have to change that.
import tkinter as tk
import random
def anmu_viewer():
global cb
random_pic = random.choice(images)
lbl.config(text=random_pic)
cb = root.after(10000, anmu_viewer) # keep a reference of the callback
def reset():
global cb
if cb is not None:
root.after_cancel(cb) # cancel the callback
cb = None # reset the reference to the callback to None
anmu_viewer()
images = ['im1', 'im2', 'im3', 'im4', 'im5', 'im6']
root = tk.Tk()
cb = None
lbl = tk.Label(root, text='')
lbl.pack()
start_btn = tk.Button(root, text="Start", command=reset)
start_btn.pack()
# reset_btn = tk.Button(root, text="Reset", command=reset)
# reset_btn.pack()
root.mainloop()
Using while with tkinter will cause some issues with mainloop() and will freeze the issue. You should be using after(ms,func) which does not freeze the GUI. A very simple code can do this, take a look here:
from tkinter import *
from tkinter import filedialog
from PIL import ImageTk, Image
from glob import glob #for the path of the image
import random
root = Tk()
def anmuViewer():
global cb
choice = random.choice(all_img) #random choice of image from the list of img
cur = ImageTk.PhotoImage(file=choice) #make an image object
img_label.config(image=cur) #changing the image on the label
img_label.img = cur #keeping a reference to the image
cb = root.after(10000,anmuViewer) #repeating the function every 10 second
def restart(): #reset func from Roblochons code
global cb
if cb is not None:
root.after_cancel(cb)
cb = None
anmuViewer()
path = filedialog.askdirectory(title='Choose the directory with images') #ask the directory with the image.
png = glob(path+'/*.png') #pick all the png image
jpg = glob(path+'/*.jpg') #pick all the jpg image
all_img = png + jpg #concatenate both the list
img_label = Label(root) #image label, later to be configured
img_label.pack()
start_btn = Button(root, text = "Start", command=anmuViewer)
start_btn.pack(padx=10,pady=10)
next_btn = Button(root, text = 'Restart', command=restart)
next_btn.pack(padx=10,pady=10)
root.mainloop()
I've explained the code with comments so its easier to understand on the go. I've not assumed what path of image you have, so I'm choosing the paths dynamically as you can see. The code looks long, because I simplified most lines of code to understand better.
Anyway you will need to resize the image so that it fits the screen for everyone, because pixels and screen resolution varies from device. Take a look here

Extra Tkinter GUI popup

I've written a bunch of code that produces a GUI. Now whenever I run the code it produces the main GUI window and one additional small window with nothing in it. When I close the smaller window the large main window disappears.
Now I've been reading other posts with similar problems, but I haven't been able to identify where the error is in my code.
Please help :)
Follow up question: How would I add a background image rather than the grey boring color?
Here is what it looks like.
#%% GUI Interface
import Tkinter as tk
from tkFont import Font
from PIL import ImageTk, Image
from Tkinter import END
#This creates the main window of an application
window = tk.Toplevel()
window.title("Sat Track")
window.geometry("1200x800")
window.configure(background='#f0f0f0')
#Imports the pictures.
pic1 = "Globeview.png"
pic2 = "MercatorView.png"
pic3 = "currentweathercroppedsmall.png"
pic4 = "GECurrentcroppedsmall.png"
#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img1 = ImageTk.PhotoImage(Image.open(pic1))
img2 = ImageTk.PhotoImage(Image.open(pic2))
img3 = ImageTk.PhotoImage(Image.open(pic3))
img4 = ImageTk.PhotoImage(Image.open(pic4))
header = tk.Label(window, text="Satellite Control Center", font=Font(size=40))
header.pack()
toprow = tk.Frame(window)
infobox = tk.Text(toprow, width=50, height=7, font=("Calibri",12))
infobox.pack(side = "left")
infobox.insert(END,"Current information for:"+spacer+name +'\n'+
"Time:" +space+times+ '\n'+
"Longitude:"+space +x_long+ '\n'+
"Latitude:" +space+x_lat+ '\n'+
"Altitude:" +space+alt+space+ "[km]"+'\n'+
"Velocity:" +space+vel+space+ "[km/s]" + '\n'+
"Spatial Resolution: "+space +spat+space+ "[Pixels pr. m]"
)
toprow.pack()
midrow = tk.Frame(window)
globeview = tk.Label(midrow, image = img1)
globeview.pack(side = "left") # the side argument sets this to pack in a row rather than a column
mercatorview = tk.Label(midrow, image = img2)
mercatorview.pack(side = "left")
midrow.pack() # pack the toprow frame into the window
bottomrow = tk.Frame(window)
currentweather= tk.Label(bottomrow, image = img3)
currentweather.pack(side = "left")
gearth = tk.Label(bottomrow, image = img4)
gearth.pack(side = "left")
bottomrow.pack()
#Start the GUI
window.mainloop()
Every tkinter application needs exactly one instance of Tk class. In your code you don't create one but mainloop seem to create one automatically it's still created (See Bryan's comment below), even though you can't(easily) refer to it later.
If you will use additional Toplevel widgets to that of your curent one go:
root = tk.Tk()
root.withdraw() # You can go root.iconify(), root.deiconify() later if you
# want to make this window visible again at some point.
# MAIN CODE HERE
root.mainloop()
if not simply replace:
window = tk.Toplevel()
with:
window = tk.Tk()
Note: Also note that if you're working using IDLE keep in mind that it creates its own Tk object which may hide the fact that your application will need one when used standalone.
Remove Toplevel from window = tk.Toplevel(). I don't have a python2 dist available -- I'm on python3 but when I removed TopLevel from my code, it only brought up one window. So, the python3 way is....
import tkinter as tk
#This creates the main window of an application
window = tk.Tk()
#Start the GUI
window.mainloop()
I think the only difference would be that python2's tkinter is actually Tkinter (as you have already done).

Make tkinter label refresh at set time intervals without input

I've been trying for the past couple of hours to find a way to refresh a label with information without having to input anything myself.
The program I am trying to write is taking the CPU temp from the Raspberry Pi and displaying it in a window. I need to make that temp input to update every 5 seconds or so, but all attempts to do so have failed.
I tried while loops and found that they do not work inside tkinter, and I can't think how to refresh something constantly without input without one.
I am quite new to Python so I'm sure there is a way and I just haven't come across it yet. Similar questions on here don't quite lead to an answer that applies for me.
Here is my bit of code right now:
import subprocess
from tkinter import *
root = Tk()
root.title('CPU Temp')
cpuLab = Label(root, text = 'CPU Temp:',
font =('Nimbus Mono L',14,),
bg = 'black', fg = 'green').grid(row = 0, column = 0)
cpuTemp = subprocess.check_output(['/opt/vc/bin/vcgencmd', 'measure_temp'])
cpuVar = StringVar()
cpuDisplay = Label(root, textvariable = cpuVar,
font =('Nimbus Mono L',14),
bg = 'black', fg = 'green').grid(row = 0, column = 1)
cpuVar.set(cpuTemp[5:11])
root.mainloop()
This works perfectly for showing the temperature, it just has to be rerun in order to refresh.
Tkinter root windows have a method called after which can be used to schedule a function to be called after a given period of time. So call that function itself like (you will have to create a class first):
def update_label(self):
self.label.configure(cpuTemp)
self.root.after(1000, self.update_label)
This will then reload your label every second.
This may help you: Creating a Timer with tkinter
TKINTER
Refresh, Update, Rerender
This code works for any type of Tkinter widget update
#!/usr/bin/env python3
import sys
import time
from tkinter import *
# Global variables
running = True
# Button action updater
def callback():
if button_1["state"] == "disabled":
button_1["state"] = "normal"
else:
button_1["state"] = "disabled"
root.after(4000, callback)
# Window setup
root = Tk()
root.title("Buttons")
root.geometry("400x300")
# Buttons setup
button_1 = Button(root, text="Learn Python", command=callback)
button_1.pack()
# Software loop
root.mainloop()
Python version used to created this software is: >=3.x

Button displaying white canvas instead of image [duplicate]

This question already has answers here:
Tkinter Label does not show Image
(3 answers)
Closed 7 years ago.
I'm trying to create an image, but it's not working and I'm not sure what I'm doing wrong. All I get when I click the button that should display the image is the white canvas, without the image. How do I get it to display?
def show_original(self):
from os.path import exists
from PIL import Image, ImageTk
if not os.path.exists(self.wdg_orig_file_name_.get()):
tkMessageBox.showinfo('Load','File does not exist:' + self.wdg_orig_file_name_.get())
return
self.orig_image_=Image.open(str_orig_file_name)
canvas = self.gui_.ca(500,500,bg='white')
im_TK = ImageTk.PhotoImage(self.orig_image_)
canvas.create_image(250,250,image=im_TK)
canvas.pack()
pass
self.wdg_orig_file_name_.get() in the main loop is:
self.wdg_orig_file_name_ = self.gui_.en(text='boat.png')
The global str_orig_file_name is assigned in pick_file():
def pick_file(self):
'''Opens a file dialog and sets its result to the filename entry'''
global str_orig_file_name
str_orig_file_name = tkFileDialog.askopenfilename()
if str_orig_file_name:
self.wdg_orig_file_name_.delete(0, END)
self.wdg_orig_file_name_.insert(0, str_orig_file_name)
#We got a new image to process. Forget the previous results.
self.orig_image_ = None
self.preview_image_ = None
Have you tried easygui?
#!/usr/bin/python
from easygui import *
image = "img.jpg"
msg = "Do you like this picture?"
choices = ["Yes","No","No opinion"]
reply=buttonbox(msg,image=image,choices=choices)
Very easy.
http://www.ferg.org/easygui/tutorial.html
I'm sorry. I though the OP was looking for a way to display an image and now I see the image is supposed to be on the button. Well I tried this and it works just fine with .gif and .png. However .jpg gives an error: "_tkinter.TclError: couldn't recognize data in image file "img.jpg"".
#!/usr/bin/python
from Tkinter import *
root=Tk()
b=Button(root,justify = LEFT)
photo=PhotoImage(file="img.png")
b.config(image=photo,width="100",height="100")
b.pack(side=LEFT)
root.mainloop()

Adding and removing image Tkinter / root

Below is my code. The code is from within a different program, so a button would be clicked
on another program and initiate this code.I have been struggling with this a while, in short i am trying to a) take an image, save it to a directory, b) display the image on canvas or root a long with a button named "refresh". When refresh is clicked then remove is called deleting the 'file' first taken, takes another picture and refreshes the canvas with the second picture taken and so on and on. I am not seeming to get it to work in this sequence and have used multiple examples etc etc. Can anyone assist please, is my design incorrect perhaps? I have ample other code but the code below details only one function calling global properties etc etc. I would appreciate an answer but also want to learn from the answer to understand what is being done wrong.
import os
import sys
import time
from VideoCapture import Device
impot Image
from PIL import ImageTk, Image
from Tkinter import *
import Tkinter
root = Tk()
root.wm_title("Camera Capture")
root.resizable(0,0)
root.geometry("600x400")
path = ('C:\Users\Public')
os.chdir(path)
def take_picture():
global root
global path
os.chdir(path)
cam = Device()
cam.saveSnapshot('pic.gif')
webcam_pic = Tkinter.PhotoImage(file='./pic.gif')
item = Label(root, anchor = W, image = webcam_pic)
item.pack()
button_take_picture = Button(root, text = "Take picture", command = take_picture(), bg
= 'blue')
button_take_picture.place(relx = .9, rely = .5, anchor = "center")
mainloop()
actually the command should be without this '()'
command =take_picture
button_take_picture = Button(root, text = "Take picture", command = take_picture, bg=blue')

Categories

Resources