I am currently using WXPython to do a GUI which displays images. I am currently changing the images about 1 to 2 times per second:
image = image.Scale(scaledHeight, scaledWidth)
image1 = image.ConvertToBitmap()
# Center the image
self.panel.bmp1 = wx.StaticBitmap(self.panel, -1, image1, ((width / 2) - (image.GetWidth() / 2), (height / 2) - (image.GetHeight() / 2)), (image.GetWidth(),image.GetHeight()))
Only problem is periodically the image does not display. I tried out an inefficient solution and copied the image into image1, image2, etc and displayed all of them hoping for the chances for all of them to not display to be lower. Unfortunately, the image will still periodically not display. Is there some sort of buffer I need to use?
Thanks in advance!
It would be convenient if you could provide your code snippet and some more details regarding what you are trying to achieve.
How ever I have created a small example which shows how to change/update images on a panel. The code below basically creates a random number in myThread() class. The number is then sent to the gui() class using publisher-subscriber strategy. The changeImage() of the gui() class checks if the value is less than or equal to 5, then it will display green image on the panel named as self.myPanel, else if the value is greater than 5 then a blue image is displayed.
The images can be downloaded from here: green.bmp blue.bmp
Code: Please note that the image files should be in the same directory in which this script is located.
import wx
import time
from wx.lib.pubsub import setupkwargs
from wx.lib.pubsub import pub
from threading import Thread
import random
class gui(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, None, id, title, size=(100,100))
self.myPanel = wx.Panel(self, -1)
image_file1 = 'green.bmp'
image_file2 = 'blue.bmp'
self.image1 = wx.Image(image_file1, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.image2 = wx.Image(image_file2, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap = wx.StaticBitmap(self.myPanel, -1)
pub.subscribe(self.changeImage, 'Update')
def changeImage(self, value):
#To destroy any previous image on self.myPanel
if self.bitmap:
self.bitmap.Destroy()
#If the value received from myThread() class is <= 5 then display the green image on myPanel
if value <=5:
self.bitmap = wx.StaticBitmap(self.myPanel, -1, self.image1, (0, 0))
#If the value received from myThread() class is > 5 then display the green image on myPanel
else:
self.bitmap = wx.StaticBitmap(self.myPanel, -1, self.image2, (10, 10))
class myThread(Thread):
def __init__(self):
Thread.__init__(self)
self.daemon = True
self.start()
def run(self):
while True:
number = random.randrange(1,10)
wx.CallAfter(pub.sendMessage, 'Update', value=number)
time.sleep(1)
if __name__=='__main__':
app = wx.App()
frame = gui(parent=None, id=-1, title="Test")
frame.Show()
myThread()
app.MainLoop()
Related
I want something similar like this image and this is same layout which I supposed to want.
And with additional note,I want to generate a graph based on the video file timings.For Eg. 10 sec this graph should be generated and after 20 sec another graph should be generated.
Is this possible
I wanted to show that it's even possible to update the plot for each frame at video rate using wx pyhotn.
This example will calculate the average pixel intensity along x-axis and update the plot for every frame. Since you want to update every 10 sec, you will need some modification. This Clip (Jenny Mayhem) is taken from https://www.youtube.com/watch?v=cOcgOnBe5Ag
import cv2
import numpy as np
import matplotlib
matplotlib.use('WXAgg') # not sure if this is needed
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx
class VideoPanel(wx.Panel):
def __init__(self, parent, size):
wx.Panel.__init__(self, parent, -1, size=size)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.parent = parent
self.SetDoubleBuffered(True)
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
dc.Clear()
if self.parent.bmp:
dc.DrawBitmap(self.parent.bmp,0,0)
class MyFrame(wx.Frame):
def __init__(self, fp):
wx.Frame.__init__(self, None)
self.bmp = None
self.cap = cv2.VideoCapture(fp)
ret, frame = self.cap.read()
h,w,c = frame.shape
print w,h,c
videopPanel = VideoPanel(self, (w,h))
self.videotimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnUpdateVidoe, self.videotimer)
self.videotimer.Start(1000/30.0)
self.graph = Figure() # matplotlib figure
plottPanel = FigureCanvas(self, -1, self.graph)
self.ax = self.graph.add_subplot(111)
y = frame.mean(axis=0).mean(axis=1)
self.line, = self.ax.plot(y)
self.ax.set_xlim([0,w])
self.ax.set_ylim([0,255])
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(videopPanel)
sizer.Add(plottPanel)
self.SetSizer(sizer)
self.Fit()
self.Show(True)
def OnUpdateVidoe(self, event):
ret, frame = self.cap.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img_buf = wx.ImageFromBuffer(frame.shape[1], frame.shape[0], frame)
self.bmp = wx.BitmapFromImage(img_buf)
# modify this part to update every 10 sec etc...
# right now, it's realtime update (every frame)
y = frame.mean(axis=0).mean(axis=1)
self.line.set_ydata(y)
self.graph.canvas.draw()
self.Refresh()
if __name__ == '__main__':
fp = "Jenny Mayhem and The Fuzz Orchestrator - Gypsy Gentleman (Live at the Lodge on Queen).mp4"
app = wx.App(0)
myframe = MyFrame(fp)
app.MainLoop()
I have the following simple code (click the pink box and you can move it around with your mouse while holding down the left mouse button).
import wx
class AppPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
p = MovablePanel(self, -1)
self.i = 0
self.Bind(wx.EVT_PAINT, self.OnPaint, self)
def OnPaint(self, event):
dc = wx.PaintDC(self)
self.i = self.i+10
c = self.i % 255
c = (0, 0, c)
dc.SetPen(wx.Pen(c))
dc.SetBrush(wx.Brush(c))
dc.DrawRectangle(0, 0, 10000,10000)
class MovablePanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetMinSize((500,500))
self.SetSize((500,500))
self.SetBackgroundColour("PINK")
self.LEFT_DOWN = False
self.Bind(wx.EVT_MOTION, self.OnMove, self)
self.Bind(wx.EVT_LEFT_DOWN,
self.OnClickDown,
self)
self.Bind(wx.EVT_LEFT_UP,
self.OnClickUp,
self)
def OnClickUp(self, event):
self.LEFT_DOWN = False
self.Refresh()
def OnClickDown(self, event):
self.LEFT_DOWN = True
self.Refresh()
def OnMove(self, event):
if self.LEFT_DOWN:
p = self.GetTopLevelParent().ScreenToClient(wx.GetMousePosition())
self.SetPosition(p)
if __name__ == "__main__":
app = wx.App(False)
f = wx.Frame(None, -1, size = (700, 700))
p = AppPanel(f, -1)
f.Show()
f.Maximize()
app.MainLoop()
and it is suppose to look like the following (simply resize the frame)
However after moving the pink box around you will see it really looks like this
I have tried the following
dc.Clear()
dc.DestroyClippingRegion()
wx.FULL_REPAINT_ON_RESIZE
wx.EVT_ERASE_BACKGROUND
I'm pretty sure it has to do with it being a panel, and therefore the PaintEvent only marking it partially damaged. This part is colored differently making the 'ghosting' or 'smearing' obvious. Perhaps I'm using the wrong words because I was unable to find a solution (and I this seems to be a non complex issue simply having to do with the 'damaged' region).
Ok I found the problem, but I'll try to post more details later.
Basically the goal of this code is to move a panel around and then update the parent panel. SetPosition calls Move which going through the wxWidget code calls DoMoveWindow, all of this leads to a change in position and a repaint call (not sure what calls the repaint yet). Great. However the repaint only marks a certain 'area' as it tries to be efficient. That is why some of the issue can be solved by having the panel go over the 'ghosted' area. What you have to do is after the SetPosition, call GetParent().Refresh(), which will send a 'full' paint without any excluded area.
Another thing to note is there are TWO terms for this 'damaged' or 'clipped' area. One is 'damage' however there is another, 'dirty'. Damage is used in the wx PaintDC information
Using wx.PaintDC within EVT_PAINT handlers is important because it
automatically sets the clipping area to the damaged area of the
window. Attempts to draw outside this area do not appear.
Trusting the documentation you will be mostly lost. However in one of the wxPython DoubleBuffer how to's the lingo changes (but it is the same thing as 'damage')
Now the OnPaint() method. It's called whenever ther is a pain event
sent by the system: i.e. whenever part of the window gets dirty.
Knowing this if you Google wx Window dirty you will get the following
Mark the specified rectangle (or the whole window) as "dirty" so it
will be repainted. Causes an EVT_PAINT event to be generated and sent
to the window.
Take the following three print cycles where an EVT_PAINT was fired after a SetPosition call (this is WITHOUT the GetParent().Refresh() call)
# first EVT_PAINT
Drawing
Panel Size (1440, 851)
Clipping Rect (0, 0, 1440, 851)
Client Update Rect (x=0, y=6, w=500, h=501) # the only place getting update is
# directly below the panel
# (that is (500, 500) )
# second
Drawing
Panel Size (1440, 851)
Clipping Rect (0, 0, 1440, 851)
Client Update Rect (x=0, y=6, w=910, h=845) # however this time the update area is
# bigger, this is also right before
# the move
# i believe what it is doing is
# drawing from (0,6) to (910, 851)
# why? because the panel is moving to
# (410, 390) and the bottom right
# corner of the panel (after moved)
# is (410+500, 390+461) = (910, 851)
# or about where the edge of the panel
# will be
# third
Drawing
Panel Size (1440, 851)
Clipping Rect (0, 0, 1440, 851)
Client Update Rect (x=410, y=390, w=500, h=461)
Here is the update code to play around with, hopefully this will help others.
import wx
instructions = """
How to use.
1) Hover your mouse over the pink panel.
2) Click down (left click)
3) While holding down drag mouse around
4) Release mouse button to stop.
"""
class AppPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.settings_sizer = wx.BoxSizer(wx.HORIZONTAL)
p = MovablePanel(self, -1)
self.c = wx.CheckBox(self, -1, label = "Ghosting On?")
self.p = p
self.i = 0
self.settings_sizer.Add(self.c)
self.sizer.Add(self.settings_sizer)
self.sizer.Add(self.p)
self.SetSizer(self.sizer)
self.Layout()
self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.c)
self.Bind(wx.EVT_PAINT, self.OnPaint, self)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnErase, self)
def OnCheck(self, event):
print "CHECK\n\n\n\n\n"
v = self.c.GetValue()
self.p.r = v
print v
def OnErase(self, event):
pass
def OnPaint(self, event):
print "Drawing"
dc = wx.PaintDC(self)
print "Panel Rect, ", self.p.GetPosition(),
print self.p.GetSize()
print "Clipping Rect", dc.GetClippingBox()
print "Client Update Rect", self.GetUpdateClientRect()
print "----------------------------"
self.i = self.i+10
c = self.i % 255
c = (0, 0, c)
dc.SetPen(wx.Pen(c))
dc.SetBrush(wx.Brush(c))
dc.DrawRectangle(0, 0, 10000,10000)
self.SetBackgroundColour(c)
dc.SetPen(wx.Pen("WHITE"))
dc.SetBrush(wx.Brush("WHITE"))
dc.DrawRectangle(0, 0, self.GetSize()[0], self.c.GetSize()[1])
class MovablePanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetMinSize((300,300))
self.SetSize((300,300))
txt = wx.StaticText(self, -1, label = "CLICK AND DRAG ME!")
inst = wx.StaticText(self, -1, label = instructions)
font = wx.Font(18, wx.SWISS, wx.NORMAL, wx.BOLD)
txt.SetFont(font)
inst.SetFont(font)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(txt, flag = wx.ALIGN_CENTRE_VERTICAL | wx.ALIGN_CENTRE_HORIZONTAL)
sizer.Add(inst, flag = wx.ALIGN_CENTRE_VERTICAL | wx.ALIGN_CENTRE_HORIZONTAL)
self.SetSizer(sizer)
self.SetBackgroundColour("PINK")
self.LEFT_DOWN = False
self.r = False
self.Bind(wx.EVT_MOTION, self.OnMove, self)
self.Bind(wx.EVT_LEFT_DOWN,
self.OnClickDown,
self)
self.Bind(wx.EVT_LEFT_UP,
self.OnClickUp,
self)
def OnClickUp(self, event):
self.LEFT_DOWN = False
self.Refresh()
def OnClickDown(self, event):
self.LEFT_DOWN = True
self.Refresh()
def OnMove(self, event):
if self.LEFT_DOWN:
p = self.GetTopLevelParent().ScreenToClient(wx.GetMousePosition())
self.SetPosition(p)
if not self.r:
self.GetParent().Refresh()
if __name__ == "__main__":
app = wx.App(False)
f = wx.Frame(None, -1, size = (700, 700))
p = AppPanel(f, -1)
f.Show()
app.MainLoop()
I am working with python v2.7 and wxPython v3.0 on Windows 7 OS. In my application I have a panel named as myPanel. I have a image as a background on myPanel the image names is green.bmp The myPanel contains a button named as myButton. This myButton also contains an image as a background named as blue.bmp The thread simply changes the image on myButton.
For the demo purpose I am using the same image again and again on myButton. In my real world problem I have different images.
Problem: After executing my application, when I see the memory consumption in the task manager I observed that the memory consumption keeps increasing. What is wrong with my code below that causes unnecessary memory consumption? How can I avoid this?
Code: The images used in the code can be downloaded from here Green.bmp and Blue.bmp. The code snippet is provided below:
import wx
from wx.lib.pubsub import setupkwargs
from wx.lib.pubsub import pub
from threading import Thread
import threading
import time
class gui(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, None, id, title, size=(500,400))
myPanel = wx.Panel(self, -1, size=(300,200))
image_file1 = 'green.bmp'
image1 = wx.Image(image_file1, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap2 = wx.StaticBitmap(myPanel, -1, image1, (0, 0))
pub.subscribe(self.addImage, 'Update')
def addImage(self):
myButton = wx.Button(self.bitmap2, -1, size =(30,30), pos=(20,20))
image_file2 = 'blue.bmp'
image2 = wx.Image(image_file2, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap1 = wx.StaticBitmap(myButton, -1, image2, (0, 0))
class myThread(Thread):
def __init__(self):
Thread.__init__(self)
self.start()
def run(self):
while True:
time.sleep(2)
wx.CallAfter(pub.sendMessage, 'Update')
if __name__=='__main__':
app = wx.App()
frame = gui(parent=None, id=-1, title="Test")
frame.Show()
myThread()
app.MainLoop()
Thanks for your time.
Your problem is in addImage. Each time this line executes:
myButton = wx.Button(self.bitmap2, -1, size =(30,30), pos=(20,20))
You are adding another child window to self.bitmap2. The window perfectly overlaps the previous one added, so it is not apparent that you have multiple children. To see what is happening, add this line to the bottom of addImage:
print len(self.bitmap2.GetChildren())
To fix this problem you should destroy all the children before you add the new button. Add this to the top of addImage
self.bitmap2.DestroyChildren()
However, this approach destroys ALL windows you have added to bitmap2, so tread lightly. If you want to only destroy the button, you should keep a reference to it. I've modified your program to use this approach:
import wx
from wx.lib.pubsub import setupkwargs
from wx.lib.pubsub import pub
from threading import Thread
import threading
import time
class gui(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, None, id, title, size=(500,400))
myPanel = wx.Panel(self, -1, size=(300,200))
image1 = wx.Image('green.bmp', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap2 = wx.StaticBitmap(myPanel, -1, image1, (0, 0))
pub.subscribe(self.addImage, 'Update')
self.myButton = None
def addImage(self):
# Don't keep adding children to bitmap2
if self.myButton:
self.myButton.Destroy()
self.myButton = wx.Button(self.bitmap2, -1, size =(30,30), pos=(20,20))
image2 = wx.Image('blue.bmp', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap1 = wx.StaticBitmap(self.myButton, -1, image2, (0, 0))
class myThread(Thread):
def __init__(self):
Thread.__init__(self)
self.start()
def run(self):
while True:
time.sleep(2)
wx.CallAfter(pub.sendMessage, 'Update')
if __name__=='__main__':
app = wx.App()
frame = gui(parent=None, id=-1, title="Test")
frame.Show()
myThread()
app.MainLoop()
I am trying to display live images from my 1394 camera.
Currently my code is able to obtain images in a loop from the camera and I was looking for any quick GUI that will update dynamically (as a separate thread). I can do this in PyQt maybe using QThreads but is there any recommendation or faster way of doing this??
Here's my code
#Loop capturing frames from camera
for frame in range(1,500):
print 'frame:',frame
TIME.sleep(1) #capture frame every second
image_binary = pycam.cam.RetrieveBuffer()
#convert to PIL Image
pilimg = PIL.Image.frombuffer("L",(cimg.GetCols(),cimg.GetRows()),image_binary,'raw', "RGBA", 0, 1)
# At this point I want to send my image data to a GUI window and display it
Thank you.
Here's wxPython code that will do it...
import wx
from PIL import Image
SIZE = (640, 480)
def get_image():
# Put your code here to return a PIL image from the camera.
return Image.new('L', SIZE)
def pil_to_wx(image):
width, height = image.size
buffer = image.convert('RGB').tostring()
bitmap = wx.BitmapFromBuffer(width, height, buffer)
return bitmap
class Panel(wx.Panel):
def __init__(self, parent):
super(Panel, self).__init__(parent, -1)
self.SetSize(SIZE)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.Bind(wx.EVT_PAINT, self.on_paint)
self.update()
def update(self):
self.Refresh()
self.Update()
wx.CallLater(15, self.update)
def create_bitmap(self):
image = get_image()
bitmap = pil_to_wx(image)
return bitmap
def on_paint(self, event):
bitmap = self.create_bitmap()
dc = wx.AutoBufferedPaintDC(self)
dc.DrawBitmap(bitmap, 0, 0)
class Frame(wx.Frame):
def __init__(self):
style = wx.DEFAULT_FRAME_STYLE & ~wx.RESIZE_BORDER & ~wx.MAXIMIZE_BOX
super(Frame, self).__init__(None, -1, 'Camera Viewer', style=style)
panel = Panel(self)
self.Fit()
def main():
app = wx.PySimpleApp()
frame = Frame()
frame.Center()
frame.Show()
app.MainLoop()
if __name__ == '__main__':
main()
I thought I'd try PyQt4 imageviewer.py example and it worked for me.
Thanks for all your help guys.
Here's my modified code:
from PyQt4 import QtCore, QtGui
class CameraViewer(QtGui.QMainWindow):
def __init__(self):
super(CameraViewer, self).__init__()
self.imageLabel = QtGui.QLabel()
self.imageLabel.setBackgroundRole(QtGui.QPalette.Base)
self.imageLabel.setScaledContents(True)
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidget(self.imageLabel)
self.setCentralWidget(self.scrollArea)
self.setWindowTitle("Image Viewer")
self.resize(640, 480)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.open)
timer.start(33) #30 Hz
def open(self):
#get data and display
pilimg = getMyPILImageDatFromCamera()
image = PILQT.ImageQt.ImageQt(pilimg)
if image.isNull():
QtGui.QMessageBox.information(self, "Image Viewer","Cannot load %s." % fileName)
return
self.imageLabel.setPixmap(QtGui.QPixmap.fromImage(image))
self.imageLabel.adjustSize()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
CameraViewer = CameraViewer()
CameraViewer.show()
sys.exit(app.exec_())
I recommend using Tkinter since it's already part of python. I've never used PIL but a quick google shows it's easy to use PIL images in Tk widgets (via the pil.ImageTk.PhotoImage() method).
If you already have a Tkinter widget set up to display images (a Label widget works fine) all you need to do is arrange for the image to be updated every second or so. You can do this by using the after command of tkinter.
Here's an example; I don't have PIL so it uses a static image but it illustrates how to use the event loop to fetch images every second:
import Tkinter
class App(Tkinter.Tk):
def __init__(self):
Tkinter.Tk.__init__(self)
self.label = Tkinter.Label(text="your image here", compound="top")
self.label.pack(side="top", padx=8, pady=8)
self.iteration=0
self.UpdateImage(1000)
def UpdateImage(self, delay, event=None):
# this is merely so the display changes even though the image doesn't
self.iteration += 1
self.image = self.get_image()
self.label.configure(image=self.image, text="Iteration %s" % self.iteration)
# reschedule to run again in 1 second
self.after(delay, self.UpdateImage, 1000)
def get_image(self):
# this is where you get your image and convert it to
# a Tk PhotoImage. For demonstration purposes I'll
# just return a static image
data = '''
R0lGODlhIAAgALMAAAAAAAAAgHCAkC6LV76+vvXeswD/ANzc3DLNMubm+v/6zS9PT6Ai8P8A////
/////yH5BAEAAAkALAAAAAAgACAAAAS00MlJq7046803AF3ofAYYfh8GIEvpoUZcmtOKAO5rLMva
0rYVKqX5IEq3XDAZo1GGiOhw5rtJc09cVGo7orYwYtYo3d4+DBxJWuSCAQ30+vNTGcxnOIARj3eT
YhJDQ3woDGl7foNiKBV7aYeEkHEignKFkk4ciYaImJqbkZ+PjZUjaJOElKanqJyRrJyZgSKkokOs
NYa2q7mcirC5I5FofsK6hcHHgsSgx4a9yzXK0rrV19gRADs=
'''
image = Tkinter.PhotoImage(data=data)
return image
if __name__ == "__main__":
app=App()
app.mainloop()
Since the good answers are pretty large, I feel like I should post a library I built specifically for this:
from cvpubsubs.webcam_pub import VideoHandlerThread
import numpy as np
image_np = numpy.array(pilImage)
def update_function(frame, cam_id):
frame[...] = image_np[...]
VideoHandlerThread(video_source=image_np, callbacks=update_function).display()
Actually, that's if image_binary is a new numpy array every time. If it's assigned to the same location, then just this should work:
from cvpubsubs.webcam_pub import VideoHandlerThread
VideoHandlerThread(video_source=image_np).display()
I know OpenCV barely counts as a GUI, but this is quick code wise.
Try to take a look at gstreamer. This is the first result google gave me searching for "gstreamer 1394" and this one is the first for "gstreamer pyqt".
I'm trying to make a special splash screen that is displayed while the application is loading,
it outputs messages of the various components loading and features a progress bar.
The first job I am tackling is mapping a .png image to the frame that will host the splash screen.
import wx
class edSplash(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, size=(410, 410), style=wx.NO_BORDER)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.Center()
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
return
def OnEraseBackground(self, evt):
dc = evt.GetDC()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
tempBrush = wx.Brush((0,0,0,0),wx.TRANSPARENT)
print tempBrush
dc.SetBackground(tempBrush)
dc.SetBackgroundMode(wx.TRANSPARENT)
#dc.Clear()
img = wx.Image("splash.png", wx.BITMAP_TYPE_PNG, -1)
bmp = wx.BitmapFromImage(img)
dc.DrawBitmap(bmp, 0, 0, True)
def PushMessage(self, mesage):
print mesage
class edApp(wx.App):
def OnInit(self):
splash = edSplash(None, 'Ed')
self.SetTopWindow(splash)
splash.Show(True)
return True
if __name__ == '__main__':
edApp(redirect=False).MainLoop()
The problem is that dc.Clear() clears to an opaque rectangle, although i have set it's brush and mode to transparent (I think :D). Commenting out dc.Clear() gives me the desired variable transparency based on the .png's alpha channel but the window gathers image noise from the neighboring windows.
How could I get both the .png's transparency and have the background clearing to an transparent brush to keep from gathering image noise?
Maybe you should try putting the background image onto a panel rather than the frame. Here's one way to do it:
http://www.blog.pythonlibrary.org/2010/03/18/wxpython-putting-a-background-image-on-a-panel/