I am trying to display all images from image folder using for loop and that all displayed correctly. But i want to add another image at runtime so I use threading here threading.Timer(2.0, self.basicgui).start()
whenever I add new image to folder i can see the name of image in image list but it can't be updated. i want to refresh panel to show updated image how can i fix this.
import wx
import threading
from PIL import Image
import wx.lib.scrolledpanel
import os
class windowclass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowclass, self).__init__(*args, **kwargs)
global panel1
panel1 = wx.Panel(self,size=(1000,28), pos=(0,0), style=wx.SIMPLE_BORDER)
panel1.SetBackgroundColour('#FDDF99')
global panel2
panel2 = wx.lib.scrolledpanel.ScrolledPanel(panel1,-1, size=(350,710), pos=(1010,0), style=wx.SIMPLE_BORDER)
panel2.SetupScrolling()
panel2.SetBackgroundColour('#FFFFFF')
self.basicgui()
def basicgui(self):
padding = 0
bSizer = wx.BoxSizer( wx.VERTICAL )
self.jpgs = GetJpgList("./image")
allimage = len(self.jpgs)
print(allimage)
for i in range(0,allimage):
#print("i=",i)
bitmap = wx.Bitmap(self.jpgs[i])
image = wx.ImageFromBitmap(bitmap)
image = image.Scale(300, 200, wx.IMAGE_QUALITY_HIGH)
bitmap = wx.BitmapFromImage(image)
control = wx.StaticBitmap(panel2, -1, bitmap)
#print(control)
control.SetPosition((10, padding+10))
padding += 210
bSizer.Add( control, 0, wx.ALL, 5 )
panel2.SetSizer( bSizer )
panel2.Layout()
threading.Timer(2.0, self.basicgui).start()
self.Show()
return
def GetJpgList(dir):
jpgs = [f for f in os.listdir(dir) if f[-4:] == ".jpg"]
# print "JPGS are:", jpgs
return [os.path.join(dir, f) for f in jpgs]
def main():
app = wx.App()
windowclass(None)
app.MainLoop()
main()
Here is your code, amended to be a bit more efficient.
Currently, you generate the images every time, which with a small number may be fine but if there are a lot of images this will eat your cpu.
Here, I've built a dictionary of the images, so only additions and deletions need to be transformed. It's also useful to discover if any work needs to be done at all, so I've assumed that a simple count can tell me that nothing has changed and therefore no work needs to be done.
import wx
import wx.lib.scrolledpanel
import glob
class windowclass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowclass, self).__init__(*args, **kwargs)
self.panel1 = wx.Panel(self,size=(1000,28), style=wx.SIMPLE_BORDER)
self.panel1.SetBackgroundColour('#FDDF99')
self.panel2 = wx.lib.scrolledpanel.ScrolledPanel(self.panel1,-1, size=(350,550))
self.panel2.SetupScrolling()
self.panel2.SetBackgroundColour('#FFFFFF')
self.panel2.SetMinSize((350,550))
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.basicgui, self.timer)
self.dict = {}
self.bSizer = wx.BoxSizer( wx.VERTICAL )
self.panel2.SetSizer(self.bSizer)
self.mainsizer = wx.BoxSizer( wx.HORIZONTAL )
self.mainsizer.Add(self.panel1,1,wx.EXPAND)
self.SetSizer(self.mainsizer)
self.timer.Start(2000)
def basicgui(self,event):
self.GetJpgList("./images")
allimage = len(self.dict)
items = self.bSizer.GetChildren()
#if the image count is the same as before nothing has changed - bail
if len(items) == allimage:
return
#remove existing images from the sizer
for i in items:
i.GetWindow().Destroy()
# add images to the sizer
for item, bitmap in self.dict.items():
control = wx.StaticBitmap(self.panel2, -1, bitmap)
self.bSizer.Add( control, 0, wx.CENTER|wx.ALL, 5 )
#reset scrolling
self.panel2.SetupScrolling(scrollToTop=False)
self.Layout()
self.Show()
def GetJpgList(self, dir):
#use glob rather than os.listdir
jpgs = glob.glob(dir+"/*.jpg")
#Build a dictionary of the images
#this way we only have to create them once
for i in jpgs:
#if image already in dict bail
if i in self.dict:
continue
print("adding", i)
bitmap = wx.Bitmap(i)
image = bitmap.ConvertToImage()
image = image.Scale(300, 200, wx.IMAGE_QUALITY_HIGH)
bitmap = wx.Bitmap(image)
self.dict[i] = bitmap
#make a list of any deleted images
del_list = []
for i in self.dict:
if i not in jpgs:
del_list.append(i)
#remove deleted images from the dictionary
for i in del_list:
self.dict.pop(i)
print("deleting",i)
return
def main():
app = wx.App()
windowclass(None)
app.MainLoop()
main()