3

マウスを使用して描画できるScrolledWindowを作成しようとしていますが、それも機能していますが、スクロールバーが「ホーム」の位置にないときにユーザーがウィンドウに描画していると、厄介なちらつきが発生します。 ..

再現するには、添付のプログラムを実行し、少し下(または右)にスクロールして、マウスの左ボタンを押したままにして少し「落書き」します。時々ちらつきが見られるはずです。

import wx

class MainFrame(wx.Frame):
    """ Just a frame with a DrawPane """

    def __init__(self, *args, **kw):
        wx.Frame.__init__(self, *args, **kw)
        s = wx.BoxSizer(wx.VERTICAL)
        s.Add(DrawPane(self), 1, wx.EXPAND)
        self.SetSizer(s)

########################################################################
class DrawPane(wx.PyScrolledWindow):
    """ A PyScrolledWindow with a 1000x1000 drawable area """

    VSIZE = (1000, 1000)

    def __init__(self, *args, **kw):
        wx.PyScrolledWindow.__init__(self, *args, **kw)
        self.SetScrollbars(10, 10, 100, 100)
        self.prepare_buffer()

        self.Bind(wx.EVT_PAINT, self.on_paint)
        self.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
        self.Bind(wx.EVT_MOTION, self.on_motion)

    def prepare_buffer(self):
        self.buffer = wx.EmptyBitmap(*DrawPane.VSIZE)
        dc = wx.BufferedDC(None, self.buffer)
        dc.Clear()
        dc.DrawLine(0, 0, 999, 999) # Draw something to better show the flicker problem

    def on_paint(self, evt):
        dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)

    def on_mouse_down(self, evt):
        self.mouse_pos = self.CalcUnscrolledPosition(evt.GetPosition()).Get()

    def on_motion(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            dc = wx.BufferedDC(wx.ClientDC(self), self.buffer)
            newpos = self.CalcUnscrolledPosition(evt.GetPosition()).Get()
            coords = self.mouse_pos + newpos
            dc.DrawLine(*coords)
            self.mouse_pos = newpos
            self.Refresh()

if __name__ == "__main__":
    app = wx.PySimpleApp()
    wx.InitAllImageHandlers()
    MainFrame(None).Show()
    app.MainLoop()

SetBackgroundStyle(wx.BG_STYLE_CUSTOM)、またはバインディングEVT_ERASE_BACKGROUND、またはRefreshRectの代わりにを使用してみRefreshましたが、ちらつきはまだあります。次に何を試すかについて何か考えはありますか?

私の環境:Xubuntu 9.04、wxPython 2.8.9.1(ただし、Ubuntu 10.04でもテスト済み)

お時間をいただき、ありがとうございました!

4

2 に答える 2

5

ロビン・ダン自身から:

まず、Refresh()デフォルトでは、ペイント イベントを送信する前に背景が消去されます (ただし、BG スタイルを設定するか、消去イベントをキャッチすることで対処できます) on_motion。スクロールオフセットによってClientDCをオフセットするのではなく、線分を描画しているバッファ内の位置だけです。そのため、バッファーがクライアント DC にフラッシュされると、仮想 (0,0) ではなく、物理 (0,0) で描画されます。言い換えれば、あなたが見ているちらつきは、すべてのマウスドラッグイベントの後に間違った位置にバッファを描画し、その後すぐに on_paintによってトリガーされた Refresh().

PrepareDC次のように、クライアント DC を使用する前に呼び出すことで、これを修正できるはずです。

    cdc = wx.CLientDC(self)
    self.PrepareDC(cdc)
    dc = wx.BufferedDC(cdc, self.buffer)

Refreshただし、とにかくやっているので、 RefreshRectここでクライアント DC を使用する必要はまったくありません。代わりに、画面へのバッファーのフラッシュを on_paint で行うだけです。

    dc = wx.BufferedDC(None, self.buffer)
于 2010-07-01T07:17:01.277 に答える
2

Jorilの推奨事項を使用し、Refresh()を削除すると、ちらつきがなくなります(フレームを拡大しても)。

import wx


class MainFrame(wx.Frame):
    """ Just a frame with a DrawPane """

    def __init__(self, *args, **kw):
        wx.Frame.__init__(self, *args, **kw)
        s = wx.BoxSizer(wx.VERTICAL)
        s.Add(DrawPane(self), 1, wx.EXPAND)
        self.SetSizer(s)

########################################################################
class DrawPane(wx.PyScrolledWindow):
    """ A PyScrolledWindow with a 1000x1000 drawable area """

    VSIZE = (1000, 1000)

    def __init__(self, *args, **kw):
        wx.PyScrolledWindow.__init__(self, *args, **kw)
        self.SetScrollbars(10, 10, 100, 100)
        self.prepare_buffer()
        cdc = wx.ClientDC(self)
        self.PrepareDC(cdc)
        dc = wx.BufferedDC(cdc, self.buffer)

        self.Bind(wx.EVT_PAINT, self.on_paint)
        self.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
        self.Bind(wx.EVT_MOTION, self.on_motion)

    def prepare_buffer(self):
        self.buffer = wx.EmptyBitmap(*DrawPane.VSIZE)
        cdc = wx.ClientDC(self)
        self.PrepareDC(cdc)
        dc = wx.BufferedDC(cdc, self.buffer)
        dc.Clear()
        dc.DrawLine(0, 0, 999, 999) # Draw something to better show the flicker problem


    def on_paint(self, evt):
        dc = wx.BufferedPaintDC(self, self.buffer, wx.BUFFER_VIRTUAL_AREA)

    def on_mouse_down(self, evt):
        self.mouse_pos = self.CalcUnscrolledPosition(evt.GetPosition()).Get()

    def on_motion(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            newpos = self.CalcUnscrolledPosition(evt.GetPosition()).Get()
            coords = self.mouse_pos + newpos
            cdc = wx.ClientDC(self)
            self.PrepareDC(cdc)
            dc = wx.BufferedDC(cdc, self.buffer)
            dc.DrawLine(*coords)
            self.mouse_pos = newpos

if __name__ == "__main__":
    app = wx.PySimpleApp()
    wx.InitAllImageHandlers()
    MainFrame(None).Show()
    app.MainLoop()
于 2010-07-02T01:10:36.857 に答える