0

我创建了一个交互式图像序列查看器。只有在没有闪烁的情况下,查看器才能几乎完美地工作。我读了一些关于双缓冲的文章,发现它有点混乱。我需要直接解释/代码我应该怎么做才能消除程序中的闪烁。在大多数示例中,都有调整大小的解释。另一方面,我不需要那个,我的窗口是固定大小的。那么我应该采取什么方法来解决闪烁问题呢?

代码:

import wx

class main_frame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, 'Main window', size=(1300, 750))
        self.panel = wx.Panel(self, -1)
        self.Centre()
#------------------------------------------------------------------------------
        self.Frames = []
        l=1
        while l < 365:
            self.Frames.append(wx.Image('images/{0}.png'.format(l), wx.BITMAP_TYPE_ANY))
            print l
            l+=1
        self.slider = wx.Slider(self.panel, wx.ID_ANY, size = (500,-1))
        self.slider.SetMax(356)
        l = self.slider.GetValue()

        self.image = wx.StaticBitmap(self.panel,-1,wx.BitmapFromImage(self.Frames[l]))

#------------------------------------------------------------------------------ 
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.sizer_v = wx.BoxSizer(wx.VERTICAL)
        self.sizer_v.Add(self.image, 0, wx.CENTRE | wx.ALL, 5)
        self.sizer_v.Add(self.slider, 0, wx.CENTRE | wx.ALL, 5)
        self.sizer.Add(self.sizer_v, 1, wx.EXPAND | wx.ALL | wx.CENTER, 5)
        self.panel.SetSizer(self.sizer)

        self.Bind(wx.EVT_SLIDER, self.OnSlider, self.slider)

    def OnSlider(self,e):
        l = self.slider.GetValue()
        self.image.SetBitmap(wx.BitmapFromImage(self.Frames[l]))

if __name__ == '__main__':
    app = wx.App()
    frame = main_frame().Show()
    app.MainLoop()
4

2 回答 2

2

wx.StaticBitmap 当它是static时效果最好,就像在不变时一样。我认为我不会使用 wx.StaticBitmap,而是使用为EVT_PAINT事件绑定处理程序的面板。当您想要更改图像时,您只需执行类似self.panel.currentBitmap = self.Frames[i]后跟self.panel.Refresh(). (或者更好的是将该功能移动到面板类中以便更好地封装。)然后在EVT_PAINT处理程序中,您只需获取wx.PaintDC并执行DrawBitmap当前位图的 a 。此外,我会在列表中保留位图而不是图像,以在移动滑块时节省转换时间。

于 2013-05-14T00:32:49.860 回答
1

我将发布一个最小的代码示例,以回答 wx python 中图像序列不闪烁显示的一般问题,因为我最近自己也在寻找答案。更新位图时消除闪烁的关键是使用 BufferedPaintDC(或 BufferedDC),并将新位图绘制到此。绘制到 BufferedPaintDC 时,您首先将位图绘制到内存,完成后,缓冲位图仅绘制到屏幕一次。

import time
import wx
import threading

def changeBitmapWorker(parent):
    img1 = 'img1.png'
    img2 = 'img2.png'
    i = 0
    while True:
        if i % 2 == 0:
            parent.bitmap = wx.Bitmap(img1)
        else:
            parent.bitmap = wx.Bitmap(img2)
        parent.Refresh()
        time.sleep(1)
        i += 1

class Window(wx.App):
    def __init__(self):
        wx.App.__init__(self)
        self.init_ui()
        self.mainWindow.Show()

    def init_ui(self):
        self.mainWindow = wx.Frame(None)
        self.mainWindow.SetSize((800, 510))
        self.vbox1 = wx.BoxSizer(wx.VERTICAL)
        panel = MyPanel(self.mainWindow)
        panel.SetSizer(self.vbox1)

class MyPanel(wx.Panel):

    def __init__(self,parent=None):
        wx.Panel.__init__(self,parent,id=-1)
        self.parent = parent
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.bitmap = None
        t = threading.Thread(target=changeBitmapWorker, args=(self,))
        t.setDaemon(True)
        t.start()

    def OnPaint(self, evt):
        if self.bitmap != None:
            dc = wx.BufferedPaintDC(self)
            dc.Clear()
            dc.DrawBitmap(self.bitmap, 0,0)
        else:
            pass

    if __name__ == '__main__':
        app = Window()
        app.MainLoop()
于 2015-05-02T00:28:50.103 回答