import wx
import sys, glob
class DemoFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1,"wx.ListCtrl in wx.LC_ICON mode",size=(600,400))
il_max=0
il = wx.ImageList(200,200)
for name in glob.glob("img/*.bmp"):
bmp = wx.Bitmap(name, wx.BITMAP_TYPE_BMP)
il_max = il.Add(bmp)
self.list = wx.ListCtrl(self, -1, style=wx.LC_ICON | wx.LC_AUTOARRANGE)
self.list.AssignImageList(il, wx.IMAGE_LIST_NORMAL)
for x in range(25):
img = x % (il_max+1)
self.list.InsertImageStringItem(x, "This is item %02d" % x, img)
app = wx.PySimpleApp()
frame = DemoFrame()
frame.Show()
app.MainLoop()
This code only work with bmp not with jpeg or png
What suitable change is required to get it work with any image format?
change
bmp = wx.Bitmap(name, wx.BITMAP_TYPE_BMP)
to
bmp = wx.Bitmap(name, wx.BITMAP_TYPE_ANY)
There's also
BITMAP_TYPE_CUR
BITMAP_TYPE_ICON
BITMAP_TYPE_IFF
BITMAP_TYPE_GIF
BITMAP_TYPE_JPEG
BITMAP_TYPE_PNG
BITMAP_TYPE_TIF
....among others
Related
Below code was taken from an existing post by Kieleth which I use as a subset of my larger codebase. I'm trying to leverage it to capture a list of frames taken once every thousand+ real time frames and later play in a time-lapse fashion. I've captured the frames but can't seem to view them when calling a simple function. I've seen in other posts that for loops are not recommended for this type of event but haven't figured out how to properly display. Any advise on this one would be appreciated?
from tkinter import ttk
import time
import cv2
from PIL import Image,ImageTk
#import threading
root = Tk()
def video_button1():# this flips between start and stop when video button pressed.
if root.video_btn1.cget('text') == "Stop Video":
root.video_btn1.configure(text = "Start Video")
root.cap.release()
elif root.video_btn1.cget('text') == "Start Video":
root.video_btn1.configure(text = "Stop Video")
root.cap = cv2.VideoCapture(0)
show_frame()
def show_frame():
# if video_btn1.cget('text') == "Stop Video":
global time_lapse_counter
ret, frame = root.cap.read()
if ret:
frame = cv2.flip(frame, 1) #flip image
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img) #converts img into tkinter readable format
root.video_label.imgtk = imgtk
if time_lapse_counter >= 20: # for Every 20 frames, capture one into time_lapse_list
time_lapse_list.append(imgtk)
time_lapse_counter = 0
root.video_label.configure(image=imgtk)
if len(time_lapse_list) == 5: # keep only 4 frames in the list *** debug purposes.
time_lapse_list.pop(0)
time_lapse_counter += 1
video_loop = root.after(40, show_frame)
else:
root.video_btn1.configure(text = "Start Video")
def time_lapse_play():
root.cap.release() #stop capturing video.
for image in time_lapse_list:
print (image, " ", len(time_lapse_list)," ",time_lapse_list) #
#*** I see the print of the pyimagexxx but nothing appears on the video***#
imgtk = image
root.video_label.imgtk = imgtk
root.video_label.configure(image=imgtk)
cv2.waitKey(500)
# video_loop = root.after(500, time_lapse_play)
def setup_widgets(): #simple label and 2 button widget setup
#Setup Top Right Window with pictures
f_width, f_height = 810, 475
root.rightframe= Frame(root, border=0, width=f_width, height = f_height)
root.rightframe.grid(row=0, column=0, padx=10, pady=0)
# Show video in Right Frame
root.cap = cv2.VideoCapture(0)
root.cap.set(cv2.CAP_PROP_FRAME_WIDTH, f_width)
root.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, f_height)
root.video_label = Label(root.rightframe)
root.video_label.grid(row=0, column = 0)
root.video_btn1 = Button(root.rightframe, fg='maroon', bg="yellow", text = "Stop Video", font=("Arial",10),height=0, width = 10, command=video_button1)
root.video_btn1.grid(row=0, column = 1)
root.video_btn2 = Button(root.rightframe, fg='maroon', bg="yellow", text="Time Lapse", font=("Arial",10),height=0, width = 10, command=time_lapse_play)
root.video_btn2.grid(row=1, column = 1)
# Main Code
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
screen_resolution = str(screen_width)+'x'+str(screen_height)
root.geometry(screen_resolution)
time_lapse_counter = 0
time_lapse_list=[]
setup_widgets()
show_frame()
root.mainloop()```
I've finally figure this one out. Seems that the for loop effectively doesn't work when using callback. I've modified the code to remove the for loop. I'm sure it could use some improvements but it works. I'm not sure how to reset the image count within the list as pop/append grows the list image number over time and I wonder about an overflow error. i.e after a few minutes, the list will contain [pyimage100 - pyimage200], after a few hours, [pyimage1000000 - pyimage1000100].
from tkinter import *
import cv2
from PIL import Image,ImageTk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg)
import matplotlib.pyplot as plt
root = Tk()
def video_button1():# this flips between start and stop when video button pressed.
if root.video_btn1.cget('text') == "Stop Video":
root.video_btn1.configure(text = "Start Video")
root.cap.release()
elif root.video_btn1.cget('text') == "Start Video":
root.video_btn1.configure(text = "Stop Video")
root.cap = cv2.VideoCapture(0)
root.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 400)
root.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 400)
show_frame()
def show_frame():
# if video_btn1.cget('text') == "Stop Video":
global time_lapse_counter
ret, frame = root.cap.read()
if ret:
frame = cv2.flip(frame, 1) #flip image
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img) #converts img into tkinter readable format
root.video_label.imgtk = imgtk
root.video_label.configure(image=imgtk)
if time_lapse_counter >= 20: # for Every 20 frames, capture one into time_lapse_list
time_lapse_list.append(imgtk)
time_lapse_counter = 0
if len(time_lapse_list) == 100: # keep 99 frames in the list
time_lapse_list.pop(0)
time_lapse_counter += 1
video_loop = root.after(40, show_frame)
else:
root.video_btn1.configure(text = "Start Video")
def time_lapse_play():
root.cap.release() #stop capturing video.
global frame_counter
if frame_counter <= len(time_lapse_list)-1:
imgtk = time_lapse_list[frame_counter] # get image from list
root.video_label.configure(image=imgtk) # update label with image from list
frame_counter += 1
video_loop = root.after(250, time_lapse_play) #wait 250ms until next frame
else:
frame_counter = 0 #reset frame_counter
def setup_widgets(): #simple label and 2 button widget setup
#Setup Top Right Window with pictures
f_width, f_height = 1200, 500
root.rightframe= Frame(root, border=0, width=f_width, height = f_height)
root.rightframe.grid(row=0, column=0, padx=10, pady=0)
# Show video in Right Frame
root.cap = cv2.VideoCapture(0)
root.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 400)
root.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 400)
root.video_label = Label(root.rightframe)
root.video_label.grid(row=0, column = 0)
root.video_btn1 = Button(root.rightframe, fg='maroon', bg="yellow", text =
"Stop Video", font=("Arial",10),height=0, width = 10, command=video_button1)
root.video_btn1.grid(row=0, column = 1)
root.video_btn2 = Button(root.rightframe, fg='maroon', bg="yellow", text="Time Lapse", font=("Arial",10),height=0, width = 10, command=time_lapse_play)
root.video_btn2.grid(row=1, column = 1)
fig = plt.figure(1)
canvas = FigureCanvasTkAgg(fig, root.rightframe)
canvas.get_tk_widget().place(x=700,y=0)
canvas.get_tk_widget().config(border=2, bg="yellow", width=400, height=400)
# Main Code
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
screen_resolution = str(screen_width)+'x'+str(screen_height)
root.geometry(screen_resolution)
time_lapse_counter = 0
frame_counter = 0
time_lapse_list=[]
setup_widgets()
show_frame()
root.mainloop()
`
from Tkinter import *
import Tkinter as tk
import ttk
import tkFileDialog
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
class Look():
def __init__(self, master):
self.master = master
self.master.title("Demo")
self.master.configure(background = "grey91") #the color will be changed later
self.master.minsize(500, 300) # width + height
self.master.resizable(False, False)
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
ttk.Button(self.top_frame, text = "Load file", command = self.load_file,
style = "TButton").pack()
ttk.Button(self.top_frame, text = "Reset", command = self.clear_file,
style = "TButton").pack()
ttk.Button(self.top_frame, text = "Plot", command = self.plot_file,
style = "TButton").pack()
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.fig = plt.figure(figsize=(12, 5), dpi=100) ##create a figure; modify the size here
self.fig.add_subplot()
plt.title("blah")
self.canvas = FigureCanvasTkAgg(self.fig, master = self.bottom_frame)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def load_file(self):
self.file = tkFileDialog.askopenfilename(defaultextension = ".txt", filetypes = [("Text Documents", "*.txt")])
def clear_file(self):
self.fig.clf()
self.fig.add_subplot()
plt.xticks()
plt.yticks()
self.canvas.draw()
def plot_file(self):
self.r, self.g = np.loadtxt(self.file).transpose()
self.fig.clf()
plt.plot(self.r, self.g)
self.canvas.show()
def main():
root = Tk()
GUI = Look(root)
root.mainloop()
if __name__ == "__main__": main()
The code above creates a program has three buttons. The Load file buttom loads a txt file, Reset button is supposed to clear the plot and delete the file just loaded into the memory. Plot button is to plot the figure onto canvas below.
I have a question about how to write function associated with Reset function, i.e. clear_file function. Currently what it does is just clear the plot from canvas. But it seems the file that has been loaded to plot is stored in memory, since click again Plot, it will display the plot. My goal is to use Reset button to bring it to a fresh start--nothing stored in memory. I know loading a new file will overwrite the previous file. But when there are multiple buttons for loading different files, the situations could become complicated. Therefore I hope Reset can do the job.
If you want to try this little program, you may create a simple txt with two column data to be loaded into the program.
Thanks.
I would make 2 changes. Move the code that sets up your plot into its own method and reset the frame each time the method is called. This can be done with destroying the frame and remaking it. The 2nd change I would change the command on your reset to reference this new method.
Taking your code this is what I would change to be able to reset the plot.
import tkinter as tk
import tkinter.ttk as ttk
from tkinter import filedialog
import numpy as np
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
class Look():
def __init__(self, master):
self.master = master
self.master.title("Demo")
self.master.configure(background = "grey91") #the color will be changed later
self.master.minsize(500, 300) # width + height
self.master.resizable(False, False)
self.top_frame = ttk.Frame(self.master, padding = (10, 10))
self.top_frame.pack()
ttk.Button(self.top_frame, text = "Load file", command = self.load_file,style = "TButton").pack()
ttk.Button(self.top_frame, text = "Reset", command = self.new_plot,style = "TButton").pack()
ttk.Button(self.top_frame, text = "Plot", command = self.plot_file,style = "TButton").pack()
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.new_plot()
# this function will reset your plot with a fresh one.
def new_plot(self):
self.bottom_frame.destroy()
self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
self.bottom_frame.pack()
self.fig = plt.figure(figsize=(12, 5), dpi=100) ##create a figure; modify the size here
self.fig.add_subplot()
plt.title("blah")
self.canvas = FigureCanvasTkAgg(self.fig, master = self.bottom_frame)
self.canvas.show()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
self.toolbar.update()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
def load_file(self):
self.file = filedialog.askopenfilename(defaultextension = ".txt", filetypes = [("Text Documents", "*.txt")])
def clear_file(self):
self.fig.clf()
self.fig.add_subplot()
plt.xticks()
plt.yticks()
self.canvas.draw()
def plot_file(self):
self.r, self.g = np.loadtxt(self.file).transpose()
self.fig.clf()
plt.plot(self.r, self.g)
self.canvas.show()
if __name__ == "__main__":
root = tk.Tk()
GUI = Look(root)
root.mainloop()
Here is my script
# Python 2.7.14 version
from Tkinter import *
import Tkinter
import tkMessageBox
from urllib2 import urlopen
import PIL
from PIL import ImageTk
import ImageTk
FILENAME = 'Fleur_de_lys.jpg'
root = Tk()
background = Canvas(root, width=250, height=250)##AttributeError: class Tk has no attribute 'Canvas'
canvas.pack()
tk_img = ImageTk.PhotoImage( file = FILENAME)
canvas.create_image(125, 125, image=tk_img)
quit_button = tk.Button(root, text = "Quit", command = root.quit, anchor = 'w',
width = 10, activebackground = "#33B5E5")
quit_button_window = canvas.create_window(10, 10, anchor='nw', window=quit_button)
root.mainloop()
No matter what attempt I do I keep getting AttributeError: class Tk has no attribute 'Canvas' where is my error if I just create button I have no issue what so ever all work but when I attempt to have a background image everything does not work
The problem appears to be that you're creating a canvas, and storing it in a variable named background, yet the very next line you are trying to call something called 'canvas', which you've never created.
Change this:
background = Canvas(root, width=250, height=250)
canvas.pack()
...
canvas.create_image(125, 125, image=tk_img)
to this:
background = Canvas(root, width=250, height=250)
background.pack()
...
background.create_image(125, 125, image=tk_img)
I fixed the issue jpg image was not being accepted I made it with a gif. Also found how to correct the buttons location and posn.
Here is the example without all the program
canvas = Canvas(root, width = 500, height = 500, bg='black')
canvas.pack(expand=YES, fill=BOTH)
my_image = PhotoImage(file='C:\\MOTD\\fleur_de_lys.gif')
canvas.create_image(0, 0, anchor = NW, image=my_image)
b1 = Button(root, text="From the Commander", command=callback,anchor = 'w',
width = 18, activebackground = "#33B5E5")
button_window1 = canvas.create_window(10, 10, anchor='nw', window=b1)
I have two images, "desert" image over "winter" image:
import pyglet
desert_img = pyglet.image.load('assets/desert.jpg')
desert = pyglet.sprite.Sprite(desert_img, x=50, y=50)
winter_img = pyglet.image.load('assets/winter.jpg')
winter = pyglet.sprite.Sprite(winter_img, x=0, y=0)
window = pyglet.window.Window()
#window.event
def on_draw():
winter.draw()
desert.draw()
pyglet.app.run()
Result is:
I would like draw a square of "transparency" on desert image (winter image should be visible in this square). Is it possible ? How to do that ?
I found many question who permit to make transparency with image itself (png, alpha ... but no like i want).
Based on Torxed suggestion, replace image content with transparent bytes where we want to make it transparent:
import io
from PIL import Image
import pyglet
from PIL.PngImagePlugin import PngImageFile
def replace_content_with_transparency(img: PngImageFile, x, y, width, height):
pixels = img.load()
for i in range(x, width):
for j in range(y, height):
pixels[i, j] = (0, 0, 0, 0)
desert_png = Image.open('assets/desert.png')
replace_content_with_transparency(desert_png, 32, 32, 123, 123)
fake_file = io.BytesIO()
desert_png.save(fake_file, format='PNG')
desert_img = pyglet.image.load('img.png', file=fake_file)
desert = pyglet.sprite.Sprite(desert_img, x=50, y=50)
winter_img = pyglet.image.load('assets/winter.jpg')
winter = pyglet.sprite.Sprite(winter_img, x=0, y=0)
window = pyglet.window.Window()
#window.event
def on_draw():
winter.draw()
desert.draw()
pyglet.app.run()
I am trying to create a new class of Canvas that will be able to display and resize images. However The image does not display. I searched for similar questions and all the answers said to keep a reference of the PhotoImage in the class.( This answer for example). I tried doing that in a number of ways and none worked. In this example I tried saving a reference in a dictionary. I also tried self.tkimage = ImageTk.PhotoImage(image=img) which didn't work. And also tried using globals. I assume it has something to do with the garbage collector, but don't know how to solve.
Please assist.
import Tkinter as tk
from PIL import ImageTk, Image
import numpy as np
# a subclass of Canvas
class MyCanvas(tk.Canvas):
def __init__(self,parent,**kwargs):
tk.Canvas.__init__(self,parent,**kwargs)
self.tkimg = {}
self.images = []
self.image_on_canvas = []
def my_create_image(self, *args, **kw):
img = kw['image']
self.images.append(img)
self.tkimg[img] = ImageTk.PhotoImage(image=img)
kw['image'] = self.tkimg[img]
item = self.create_image(*args, **kw)
self.image_on_canvas.append(item)
def main():
root = tk.Tk()
myframe = tk.Frame(root)
myframe.pack(fill=tk.BOTH, expand=tk.YES)
mycanvas1 = MyCanvas(myframe, width=850, height=400, bg="red", highlightthickness=0)
mycanvas2 = MyCanvas(myframe, width=850, height=400, bg="green", highlightthickness=0)
mycanvas1.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.YES)
mycanvas2.pack(side=tk.RIGHT, fill=tk.BOTH, expand=tk.YES)
# add some widgets to the canvas
mycanvas2.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
mycanvas2.create_rectangle(50, 25, 150, 75, fill="blue")
arr1 = np.random.random([256,256])*255
img1 = Image.fromarray(arr1)
mycanvas1.my_create_image(0, 0, image=img1, anchor=tk.NW)
root.mainloop()
if __name__ == "__main__":
main()