I want to show two images successively like a slideshow in my stacked tkinter frame. I heard, that I can do that with the after-method, but how do I use this method? Sorry if my english is bad. Thanks.
# -*- coding: cp1252 -*-
import sys
import Tkinter as tk
from Tkinter import *
from functools import partial
import random
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title("test")
self.state('zoomed')
container= tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames={}
for F in (fenster, mode1):
frame= F(container, self)
self.frames[F]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(fenster)
def show_frame(self, c):
frame=self.frames[c]
frame.tkraise()
class fenster(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label=tk.Label(self, text="Das ist die Startseite")
label.pack()
button=tk.Button(self, text="Start",
command=lambda: controller.show_frame(mode1))
button.pack()
class mode1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label1=tk.Label(self, text=" ")
label1.pack()
def ok(label1):
def do_a():
image1 = PhotoImage(file = 'test.gif')
photo1=Label(image=image1)
photo1.image=image1
photo1.pack()
image2 = PhotoImage(file = 'tet.gif')
photo2=Label(image=image2)
photo2.image=image2
photo2.pack()
def do_b():
print("ngfijnwgfekö")
WORDS={"test1":do_a,
"test2":do_b}
choice=random.choice(list(WORDS))
label1['text']=choice
WORDS[choice]()
button1=tk.Button(self, text='Knopf', command=partial(ok, label1))
button1.pack()
if __name__== "__main__":
app=SampleApp()
app.mainloop()
Not sure where you want to add the slide show to your code, so here's a minimal working example of a simple Tkinter GUI, using after to cycle though all the images found in the current directory.
from Tkinter import Tk, PhotoImage, Label
from glob import glob
from itertools import cycle
# this method calls itself again after 1000 milliseconds
def show_next():
image.configure(file=next(images))
root.after(1000, show_next)
# cycle though gif images found in working directory
images = cycle(glob("*.gif"))
# build minimal test GUI
root = Tk()
image = PhotoImage()
Label(root, image=image).pack()
# start slide show and GUI main loop
show_next()
root.mainloop()
Related
Segmentation fault: 11 - not sure what it means, why it has happened. I thought it was an issue with Python on my machine by all other files run fine. I have, of course, tried restarting and re-installing Python but didn't help.
I'm just trying to implement frame switching via a menu bar with tkinter.
Any help greatly appreciated.
# import tkinter modules
from tkinter import *
from tkinter import ttk
import tkinter.font as tkFont
from PIL import ImageTk, Image
from tkcalendar import *
# import modules for restart functionality
import os
import sys
import time
# define self
class tkinterApp(Tk):
def __init__(self,*args, **kwargs):
Tk.__init__(self, *args, **kwargs)
# creating a container
container = Frame(self)
container.pack(side = "top", fill = "both", expand = True)
container.grid_rowconfigure(0, weight = 1)
container.grid_columnconfigure(0, weight = 1)
# initialising frames to an empty array
self.frames = {}
menu_bar = Menu(container)
menu_bar.add_cascade(label="Main Menu", menu=menu_bar)
menu_bar.add_command(label="Welcome page", command=lambda: self.show_frame(welcome_frame))
menu_bar.add_command(label="Book a vehicle", command=lambda: self.show_frame(booking_frame))
menu_bar.add_command(label="Register as new user", command=lambda: self.show_frame(register_frame))
Tk.config(self, menu=menu_bar)
for F in (welcome_frame, register_frame, booking_frame):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row = 0, column = 0, sticky = "nsew")
self.show_frame(welcome_frame)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class welcome_frame(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
# welcome_frame = Frame(self, width=1000, height=800)
# welcome_frame.grid()
welcome = Label(welcome_frame, text="Hello, please use the menu above to navigate the interface")
welcome.grid(row=0, column=4, padx=10, pady=10)
class register_frame(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
welcome = Label(self, text="New user - enter your details below to use the Collyer's car park.")
welcome.grid(row=0, column=4, padx=10, pady=10)
class booking_frame(Frame):
def __init__(self, parent, controller):
Frame.__init__(self, parent)
app = tkinterApp()
app.geometry("1000x800")
app.mainloop()
You are trying to make a cascade menu where the cascaded menu is the same menu:
menu_bar.add_cascade(label="Main Menu", menu=menu_bar)
The menu option needs to point to a new menu menu.
main_menu = Menu(menu_bar)
menu_bar.add_cascade(label="Main Menu", menu=main_menu)
I'm guessing you also want to put the menu commands on that menu, too
main_menu.add_command(label="Book a vehicle", command=lambda: self.show_frame(booking_frame))
main_menu.add_command(label="Register as new user", command=lambda: self.show_frame(register_frame))
Unrelated to the question, this code is also wrong:
welcome = Label(welcome_frame, text="Hello, please use the menu above to navigate the interface")
You are trying to use a class as the parent/master of the Label widget. You can't do that. The first parameter needs to be a widget. In this case, it should be self.
You also need to make sure that show_frame is indented the same as the __init__ method of the tkinterApp class.
able frame in tkinter, the frame consist of multiple mini long canvases(which contain some text and a button)which can be scrolled up and down with a scrollbar. I also used tkinter themes to make my gui look nice. But for some reason as soon as i added in the gui, the frame would lag abit when scrolled up and down, like the canvases are crashing into eachother, is their away to fix this?
Here is how it looks without scrolling
Here's how it looks sometimes, when its scrolled
Here's the code
from tkinter import *
from ttkthemes.themed_tk import ThemedTk
from tkinter import *
from tkinter.ttk import *
import tkinter as tk
from tkinter import ttk
class tkinterprogram(ThemedTk):
def __init__(self, *args, **kwargs):
ThemedTk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage,Task):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
frame.winfo_toplevel().geometry("1024x720")
class StartPage(tk.Frame):
def __init__(self, parent, controller):
ttk.Frame.__init__(self, parent)
l = Canvas(self, bg='#4A4949')
l.pack(fill='both', expand='True')
global canvascon
canvascon = Canvas(l, height=400,width=1500,bg='#4A4949',highlightthickness=0)
global frame2
frame2 = Frame(canvascon)
global myscrollbar
myscrollbar = Scrollbar(l, orient="vertical",command=canvascon.yview)
canvascon.create_window((0, 0), window=frame2,width=15000,anchor='nw')
canvascon.place(x=25,y=150,relheight=0.558,relwidth=0.87)
myscrollbar.pack(side=RIGHT, fill=Y,pady=25)
Button(l,text='go',command=lambda: meth()).pack()
def meth():
for count in range(25):
c = Canvas(frame2, height=50, bg="#1E2133",highlightthickness=5,highlightbackground='#4A4949')
lab = tk.Label(frame2, text='running',bg='#1E2133',fg='#EFEFEF')
lab_window = c.create_window(10,15, window=lab,anchor=tk.NW)
stop = tk.Button(frame2, text='STOP')
stop_window = c.create_window(200, 15, window=stop, anchor=tk.NW)
c.pack(fill=X,expand=True)
frame2.update() # update frame2 height so it's no longer 0 ( height is 0 when it has just been created )
canvascon.configure(yscrollcommand=myscrollbar.set, scrollregion="0 0 0 %s" % frame2.winfo_height())
class Task(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
app = tkinterprogram()
app.get_themes()
app.set_theme('scidgrey')
app.mainloop()
Thanks for any help in advance.
I am new to Python and not very experienced with classes, however working on the creation of a tkinter GUI for data processing right now.
As many time consuming processes are happening in the background not visible for the user, I would like to insert a progress-bar that shows the current progress between 0 and 100 as Progress and the processing step Action in the main window
Right now, I have problems to access the bar parameters (value and label/name) outside of the class when the code is doing the data processing in a different function.
Below is a working example of the GUI in Python 3.7
import time
import tkinter as tk
from tkinter import ttk
def ProcessingScript():
### UpdateProgressbar(50, 'Halfway there') ###
time.sleep(2)
print('Processing takes place here')
### UpdateProgressbar(75, 'Finishing up') ###
time.sleep(2)
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self, width=500, height=500)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.geometry("500x500")
self.frames = {}
frame = ProcessingPage(container, self)
self.frames[ProcessingPage] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(ProcessingPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class ProcessingPage(tk.Frame):
def __init__(self, parent, controller, ):
tk.Frame.__init__(self, parent)
self.controller = controller
def PlotData():
UpdateProgressbar(10, 'Generating...')
# Execute Main Plotting Function here
ProcessingScript()
UpdateProgressbar(100, 'Finished Plot')
def UpdateProgressbar(Progress, Action):
progressLabel = tk.Label(self, text=Action).place(x=20, y=440)
progressBar['value'] = Progress
progressBar = ttk.Progressbar(self, orient="horizontal", length=200,mode="determinate")
progressBar.place(x=20, y=470)
progressBar['value'] = 0
progressLabel = tk.Label(self, text='Idle...').place(x=20, y=440)
PlotButton = tk.Button(self, text='Plot Data',command= PlotData)
PlotButton.place(x=20, y=320)
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
In this example, the ProcessingScript function would be in a different file and as an ideal outcome I would like to be able to call the UpdateProgressbar function from anywhere in my other scripts to update the bar.
Note: I am aware that a function inside the __init__ function is not best practice, however I was not able to get it running in any other way as I found no way to connect the results of the UpdateProgressbar function with the progressBar created.
Any help to achieve this and exclude UpdateProgressbar from __init__ is much appreciated.
EDIT:
Below is a working version based on the input from the comments. It might now be very pretty but is currently doing what I expect it do to. Please let me know if you see some possibilities for improvement.
app.update() has to be called after each change in the progress bar to show the error and old labels are deleted with self.progressLabel.destroy().
timeit.sleep() is simply a way of showing the changes and will not be part of the final code.
import time
import tkinter as tk
from tkinter import ttk
def ProcessingScript(self, callback):
ProcessingPage.UpdateProgressbar(self, 50, 'Halfway there')
time.sleep(2)
print('Processing takes place here')
ProcessingPage.UpdateProgressbar(self, 75, 'Finishing up')
time.sleep(2)
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self, width=500, height=500)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.geometry("500x500")
self.frames = {}
frame = ProcessingPage(container, self)
self.frames[ProcessingPage] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(ProcessingPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class ProcessingPage(tk.Frame):
def __init__(self, parent, controller, ):
tk.Frame.__init__(self, parent)
self.controller = controller
progressBar = ttk.Progressbar(self, orient="horizontal", length=200,mode="determinate")
progressBar.place(x=20, y=470)
progressBar['value'] = 0
self.progressLabel = tk.Label(self, text='Idle...')
self.progressLabel.place(x=20, y=440)
PlotButton = tk.Button(self, text='Plot Data',command= self.PlotData)
PlotButton.place(x=20, y=320)
def PlotData(self):
self.UpdateProgressbar(10, 'Generating...')
app.update()
time.sleep(2)
# Execute Main Plotting Function here
ProcessingScript(self, self.UpdateProgressbar)
self.UpdateProgressbar(100, 'Finished Plot')
app.update()
def UpdateProgressbar(self, Progress, Action):
self.progressLabel.destroy()
self.progressLabel = tk.Label(self, text=Action)
self.progressLabel.place(x=20, y=440)
progressBar = ttk.Progressbar(self, orient="horizontal", length=200,mode="determinate")
progressBar.place(x=20, y=470)
progressBar['value'] = Progress
app.update()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
I can't show up the Image in tkinter PIL class.
Image is packed or placed successfully but it is not showing up.
windowxp wall paper and a man's face are not shown.
I made message box when click his face.
So if I click the location, message box is showing up. But picture is not showing up. Just location :(
I use windows 64bit and Python 3.6
I am Korean. I'm not goot at English.... Please understand me.
Please help me
This is right display: screenshot
from tkinter import *
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk
##함수
class Mainwindow(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title("김상곤이 좋아하는 꿈꾸는 학과 과목 문제 맞추기♡")
self.geometry("1600x900")
self.resizable(width=FALSE, height=FALSE)
wall = tk.PhotoImage(file="gif/bg.gif")
labelwall = tk.Label(self, image = wall)
labelwall.place(x=0, y=0)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
def func_make():
messagebox.showinfo("제작자", "김재온, 정성윤, 안예진, 이소유, 우연서")
def func_exit():
window.quit()
window.destroy()
mainMenu=Menu(self)
fileMenu=Menu(mainMenu)
self.config(menu=mainMenu)
mainMenu.add_cascade(label="파일", menu=fileMenu)
fileMenu.add_command(label="제작자", command=func_make)
fileMenu.add_separator()
fileMenu.add_command(label="종료", command=func_exit)
self.frames={}
for F in (MainPage, QuizPage):
page_name=F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name]=frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("MainPage")
def show_frame(self, page_name):
frame = self.frames[page_name]
frame.tkraise()
def 국어():
page == 1
subject=['국어', '과학', '역사', '사회', '기술']
#색이나 위치 숫자 설정
mint="#99FFFF"
subjectsize=30
subjectbutton=60
##위젯
class MainPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller=controller
def clickksk(event):
messagebox.showinfo("김상곤", "아주 좋아요^^")
labeltitle=tk.Label(self, text=
"""김상곤이 좋아하는 꿈꾸는
학과 과목 문제 맞추기♡""", font=("궁서체", 35), bg="#8DFD73")
ksk=tk.PhotoImage(file="gif/ksk.gif")
labelksk=tk.Label(self, image=ksk)
labelksk.place(x=400-subjectbutton, y=200)
labelksk.bind("<Button>", clickksk)
labelhow=tk.Label(self, text="게임방법! ", font=("맑은 고딕", 30), bg="#FFE400")
labelexplain=tk.Label(self, text=
"""원하는 과목을 택해 클릭한후,
OX퀴즈를 풀면 됩니다^^
난이도=중3""", font=("고딕체", 25), bg="#FFE400")
btKorean=tk.Button(self, text="국어", font=("양재블럭체", subjectsize), bg=mint,
command=lambda: controller.show_frame("QuizPage"))
btScience=tk.Button(self, text="과학", font=("양재블럭체", subjectsize), bg=mint)
btHistory=tk.Button(self, text="역사", font=("양재블럭체", subjectsize), bg=mint)
btSocial=tk.Button(self, text="사회", font=("양재블럭체", subjectsize), bg=mint)
bttech=tk.Button(self, text="기술", font=("양재블럭체", subjectsize), bg=mint)
##pack하는 장소(코드 순차대로)
labeltitle.place(relx= 0.25, rely=0.02, relwidth=0.5)
labelhow.place(x=610-subjectbutton, y=200, relwidth=0.3)
labelexplain.place(x=610-subjectbutton, y=260, relwidth=0.3)
btKorean.place(x=400-subjectbutton, y=600)
btScience.place(x=600-subjectbutton, y=600)
btHistory.place(x=800-subjectbutton, y=600)
btSocial.place(x=1000-subjectbutton, y=600)
bttech.place(x=1200-subjectbutton, y=600)
btKorean.bind("<Button-1>")
btScience.bind("<Button-1>")
btHistory.bind("<Button-1>")
btSocial.bind("<Button-1>")
bttech.bind("<Button-1>")
class QuizPage(tk.Frame):
def __init__(self, parent, controller):
OB=PhotoImage(file="gif/OB.gif")
XR=PhotoImage(file="gif/XR.gif")
tk.Frame.__init__(self, parent)
self.controller = controller
buttonOB=Button(self, image=OB)
buttonXR=Button(self, image=XR)
buttonOB.place()
buttonXR.place()
if __name__ == "__main__":
app = Mainwindow()
app.mainloop()
I think your main problem is you are using two subclassed frames and using grid to manage them but the main application window is not expanding the grid area. You need to add the following to MainWindow.__init__:
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
so that the (0,0) cell is expanded to fill all the available space. Then your currently selected frame will expand into that region as it has sticky='NSWE' set in the grid method call.
Where you define container you are both packing and gridding. You have to only use one. However, this looks like dead code. Maybe you intended to put the subclassed frames into this container at one time.
Also, you cannot just call buttonXR.place(), you need to give it a position. For instance: buttonXR.place(x=1, y=1).
This question already has answers here:
Why is "import *" bad?
(12 answers)
Closed 5 years ago.
I'm trying to open a file with PIL and tkinter. Im using this code:
import tkinter as tk
from PIL import Image,ImageTk
from tkinter import *
intWidth=20
intHeight=5
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.grid(row=0,column=0)#pack(side="top", fill="both", expand=True)
self.frames = {}
for F in (StartPage, Departure, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.config(bg='#FBC311')
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
for row in range(9):
self.grid_rowconfigure(row, weight=1)
Button(self,text="Button %d"%(row), bg = '#005ca0', fg = 'white', font = "Verdana 10", width = intWidth, height = intHeight).grid(row = row,column = 0,sticky = E+W)
for c in range(9):
self.grid_columnconfigure(c, weight=1)
Button(self,text="Button %d"%(c), bg = '#005ca0', fg = 'white', font = "Verdana 10", width = intWidth, height = intHeight).grid(row = 5,column = c,sticky = E+W)
label = tk.Label(self, text="Welkom bij NS", font='Verdana 50', fg='#005ca0', bg='#FBC311')
label.grid(row=1,column=3,columnspan=3)
path = "nslogo.png"
img = ImageTk.PhotoImage(Image.open(path))
panel = Label(self , image=img, bg = '#FBC311', width = 340)
panel.photo = img
panel.grid(column=4, row=2)
button1 = tk.Button(self, text="Actuele reistijden", command=lambda: controller.show_frame("Departure"),bg='#005ca0', fg='white',width=20,height=5)
button1.grid(row=6, column=3,sticky='nsew')
button2 = tk.Button(self, text="Go to Page Two", command=lambda: controller.show_frame("PageTwo"),bg='#005ca0', fg='white',width=20,height=5)
button2.grid(row=6,column=5,sticky='nsew')
class Departure(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
for row in range(7):
self.grid_rowconfigure(row, weight=1)
for c in range(7):
self.grid_columnconfigure(c, weight=1)
label = tk.Label(self, text="Actuele vertrektijden", font='Verdana 50', fg='#005ca0', bg='#FBC311')
label.grid(row=0,column=2,columnspan=5)
button = tk.Button(self, text="Start",command=lambda: controller.show_frame("StartPage"),bg='#005ca0', fg='white',width=20,height=5)
button.grid(row=2,column=4)
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
for row in range(7):
self.grid_rowconfigure(row, weight=1)
for c in range(7):
self.grid_columnconfigure(c, weight=1)
label = tk.Label(self, text="Storingen", font='Verdana 50', fg='#005ca0', bg='#FBC311')
label.grid(row=0,column=2,columnspan=5)
button = tk.Button(self, text="Start", command=lambda: controller.show_frame("StartPage"), bg='#005ca0', fg='white',width=20,height=5)
button.grid(row=2,column=4)
app = SampleApp()
app.mainloop()
But im getting an error:
File "C:/Users/kevin/Desktop/HU/Programming/TICT-ViPROG-15/mini_project/test.py", line 59, in init
img = ImageTk.PhotoImage(Image.open(path))
AttributeError: type object 'Image' has no attribute 'open'
I have no idea why this is happening and was hoping someone coul help me with this issue.
Thanks in advance.
You have a namespace conflict. Instead of doing...
from PIL import Image,ImageTk
Try doing:
from PIL import ImageTk
from PIL import Image as PilImage
and then, in the line you're getting the error, you'll do:
img = ImageTk.PhotoImage(PilImage.open(path))
I hope that helps. Regards.
The problem is caused by the way that you import the tkinter module:
from PIL import Image,ImageTk
from tkinter import *
The second import will replace any existing names of variables, classes etc. with those contained in the tkinter module. It just so happens that there is an Image class defined in tkinter (that doesn't have an open() method), so it will replace the one that was already imported from PIL.
>> from tkinter import *
>>> Image
<class 'tkinter.Image'>
This is a demonstration of why it is preferable not to use import *, although it is common to do so with Tkinter.
One way to fix this is to swap the order of your imports so that PIL.Image replaces tkinter.Image, but that now prevents you from using tkinter.Image if you had wanted to use both in the same namespace.
So, you can import using as to define your own name for items imported from the module:
from PIL import ImageTk, Image as PILImage
and use PILImage instead of Image when you require a PIL.Image.