gpt4 book ai didi

python - 无闪烁可绘制的 ScrolledWindow

转载 作者:行者123 更新时间:2023-12-01 11:08:13 26 4
gpt4 key购买 nike

我正在尝试构建一个可以使用鼠标绘制的 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),或绑定(bind) EVT_ERASE_BACKGROUND,或使用 RefreshRect 而不是 Refresh,但闪烁仍然存在。知道我接下来会尝试什么吗?

我的环境:Xubuntu 9.04,wxPython 2.8.9.1(但也在 Ubuntu 10.04 上测试过)

非常感谢您的宝贵时间!

最佳答案

来自罗宾·邓恩本人:

First, a Refresh() by default will erase the background before sending the paint event (although setting the BG style or catching the erase event would have taken care of that.) The second and probably most visible problem in this case is that in your on_motion handler you are not offsetting the ClientDC by the scroll offsets, just the position in the buffer that you are drawing the line segment at. So when the buffer is flushed out to the client DC it is drawn at the physical (0,0), not the virtual (0,0). In other words, the flicker you are seeing is coming from drawing the buffer at the wrong position after every mouse drag event, and then it immediately being drawn again at the right position in the on_paint triggered by the Refresh().

You should be able to fix this by calling PrepareDC on the client DC before using it, like this:

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

However since you are doing a Refresh or RefreshRect anyway, there is no need to use a client DC here at all, just let the flushing of the buffer to the screen be done in on_paint instead:

    dc = wx.BufferedDC(None, self.buffer)

关于python - 无闪烁可绘制的 ScrolledWindow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3147613/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com