Python 使用WxByton显示WXbitmap时出现问题
我在写一个程序时遇到了一些问题,希望能得到一些帮助或意见。在某些背景下,我使用Python2.7和wxPython来实现流媒体网络摄像头客户端。客户机在自己的线程中从服务器获取图像,并将其放入队列中。然后,GUI线程从队列中获取这些图像,并将它们转换为Python 使用WxByton显示WXbitmap时出现问题,python,wxpython,Python,Wxpython,我在写一个程序时遇到了一些问题,希望能得到一些帮助或意见。在某些背景下,我使用Python2.7和wxPython来实现流媒体网络摄像头客户端。客户机在自己的线程中从服务器获取图像,并将其放入队列中。然后,GUI线程从队列中获取这些图像,并将它们转换为wxBitmap对象。这种情况每0.5秒发生一次,效果非常好。我可以将wxBitmap对象保存为一个文件,这样我就知道一切都正常工作了 我遇到的问题实际上是,要在GUI上显示wxBitmapobject。我似乎能让GUI做的唯一一件事就是在web
wxBitmap
对象。这种情况每0.5秒发生一次,效果非常好。我可以将wxBitmap
对象保存为一个文件,这样我就知道一切都正常工作了
我遇到的问题实际上是,要在GUI上显示wxBitmap
object。我似乎能让GUI做的唯一一件事就是在web cam图像应该显示的位置显示一个灰色矩形
这是我的onPaint()
,当我想刷新屏幕时调用它:
def onPaint(self,e):
## this is the function that actually draws and redraws the window
## to be displayed. I think it is something similar to blit()
## in other graphical display frameworks
print "in onPaint"
## create the device context object (graphics painter)
dc = wx.PaintDC(self)
dc.BeginDrawing()
## draw the bitmap to the screen
dc.DrawBitmap(self.imageBit,0,0,True)
dc.EndDrawing()
## test code.
## the following works and updates, which means that
## everything is being converted properly and updated.
## not sure why the dc won't paint it to the window.
self.imageBit.SaveFile("bit.bmp", wx.BITMAP_TYPE_BMP)
简单地说,我不知道为什么它不起作用。根据我的研究,我发现因为我在windows机器上,我需要BeginDrawing()
和EndDrawing()
函数,所以我添加了它们。还是不行。没有引发任何错误或异常
可能有助于解决此问题的其他问题:
- 我正在更新
对象。可能wxFrame
需要在另一种类型的容器中运行才能工作wxPaintDC
- ?李>
\uuuu init\uuu
函数导致了问题。我的设置正确吗
class viewWindow(wx.Frame):
imgSizer = (480,360)
def __init__(self, *args, **kw):
## this is called when an instance of this class is created
super(viewWindow,self).__init__(*args,**kw)
## here is where the actual stuff inside the frame is set up.
self.pnl = wx.Panel(self)
## create a button that opens up a Connection Window
#test = wx.Button(self.pnl, label='Connection Settings')
## test.Bind(wx.EVT_BUTTON, self.openConnectionWindow)
## create the wxImage for the web cam pic
self.image = wx.EmptyImage(self.imgSizer[0],self.imgSizer[1])
## create the wxBitmap so that the wxImage can be displayed
self.imageBit = wx.BitmapFromImage(self.image)
## create a timer that will update the window based of frame rate
self.timex = wx.Timer(self, wx.ID_OK)
self.timex.Start(500)
self.Bind(wx.EVT_TIMER, self.redraw, self.timex)
## need to do the following in order to display images in wxPython:
self.Bind(wx.EVT_PAINT, self.onPaint)
self.SetSize(self.imgSizer)
self.SetTitle('View Window')
self.Show()
无论如何,先谢谢你的帮助
编辑:我通过删除行self.pnl=wx.Panel(self)
意外地解决了这个问题
很明显,它渲染正确,但位图在面板下面。大概我不太确定。我对wxPython这个东西还不熟悉。这似乎也是wxPython演示所做的:dc.DrawBitmap。而且它在Windows上工作!至少,他们在AlphaDrawing演示中就是这么做的。在DrawImage演示中,他们使用dc.Blit()。你可以试试
然而,我想知道你是否不能像我用我的手机那样做。我不使用DCs绘图,而是使用我更新的wx.StaticBitmap。此代码有效。它每次都会显示图像。不过,它确实倾向于“闪烁”。所以可能有一种更好的方法,我不知道
class viewWindow(wx.Frame):
imgSizer = (480,360)
def __init__(self, parent, title="View Window"):
super(viewWindow,self).__init__(parent)
## create the menu and its sub trees
menubar = wx.MenuBar()
filemenu = wx.Menu()
menubar.Append(filemenu, 'File')
self.fitem = filemenu.Append(wx.ID_ANY, 'Open Connection Window')
self.Bind(wx.EVT_MENU, self.openConnectionWindow, self.fitem)
self.SetMenuBar(menubar)
## here is where the actual stuff inside the frame is set up.
self.pnl = wx.Panel(self)
self.vbox = wx.BoxSizer(wx.VERTICAL)
## create the wxImage for the web cam pic
self.image = wx.EmptyImage(self.imgSizer[0],self.imgSizer[1])
## create the wxBitmap so that the wxImage can be displayed
self.imageBit = wx.BitmapFromImage(self.image)
self.staticBit = wx.StaticBitmap(self.pnl,wx.ID_ANY, self.imageBit)
## add the staticBit to the sizer so it is rendered properly on resizes and such
## note: not actually needed to get the image to display, but reccommended for ease
## of layout
self.vbox.Add(self.staticBit)
## register the sizer with the panel so the panel knows to use it.
self.pnl.SetSizer(self.vbox)
## create a timer that will update the window based on frame rate
self.timex = wx.Timer(self, wx.ID_OK)
self.timex.Start(1000/framerate)
self.Bind(wx.EVT_TIMER, self.redraw, self.timex)
## set the size of the frame itself when it is first opened
self.SetSize(self.imgSizer)
self.Show()
def openConnectionWindow(self, e):
## this will open a new connection window
connect = connectionWindow(None)
def redraw(self,e):
## this function updates the frame with the latest web cam image that has been
## retrieved by the client thread from the server.
## get the newest image in the queue
if not imgQ.empty():
picz = imgQ.get()
## convert the image from a string to something usable (wxImage)
self.image.SetData(picz)
## from wxImage to wxBitmap
self.imageBit = wx.BitmapFromImage(self.image)
self.staticBit = wx.StaticBitmap(self.pnl,wx.ID_ANY, self.imageBit)
## refresh the frame
self.Refresh()
几个小时后,我研究了一个不同的问题,我发现:
这其中包含了运行良好的示例代码。面板下方出现的图像是可能的。除非您明确地设置使用
wx.Sizer的位置,否则对象默认为(0,0)。这就是为什么即使我只有一个项目,我也会使用一个sizer。在我问这个问题之前,我实际上已经看过你的照片查看器代码了。我看了看,没法让它工作。在我对wxPython如何将东西呈现到屏幕上的理解中可能存在一些缺陷,我认为这与wx.App、wx.Frame和wx.Panel如何协同工作有关。我注意到您的照片查看器代码是wx.Panel中的wx.Sizer和wx.Widgets,wx.Panel位于wx.Frame中,wx.Frame位于wx.App中,而我的代码只是一个wx.Frame和一个dc对象。我将尝试重新构造我的代码,使其与您的代码相似,然后返回给您。好的。最好能看到一个小的可运行示例。这将非常有帮助。这是我的新代码。它基于您博客中的示例,图像查看器。我很高兴它能工作,但我不高兴它每次刷新时都闪烁。哦,好吧。解决一个bug,然后创建另一个bug。代码如下:编辑:字符太多,不能作为注释保留。遗憾的是,我不能在工作时看pastebins。不过,您可能可以使用冻结和解冻方法来减少闪烁。