我正在寻找一些代码,如何并行使用wx.PaintDC()和wx.MemoryDC。 我的wxPython是在2.8.12版本中,我无法将wx.PaintDC()绘制到wx.Window中,而 也有一个线程在运行,它将wx.MemoryDC绘制成一个位图。
像这样:
def onPaint(self, evt):
self.dc=wx.PaintDC(self)
imgbuf, (sx, sy), self.refresh_needed=self.osm.getBitmap()
self.dc.DrawBitmap(imgbuf, sx, sy)
as_thread()
w, h=self.__getBitmapSize()
self.bmpbuf=wx.EmptyBitmapRGBA(w, h, 204, 204, 204, 1)
self.mdc=wx.MemoryDC()
self.mdc.SelectObject(self.bmpbuf)
[.....]
y=0
for yi in imgs:
x=0
for tn, (status, xi) in yi:
if status!=self.status["GOOD"]:
xi=wx.EmptyBitmapRGBA(256, 256, red=255, alpha=1)
if status!=self.status["INVALID"]:
needs_refresh=True
self.mdc.DrawBitmap(xi, x, y)
x+=self.ts
y+=self.ts
imgbuf 和 self.bmpbuf 是不是相同的对象。
用以下方法复制self.bmpbuf :
w, h=self.__getBitmapSize()
buf=numpy.empty((w, h, 3), dtype=numpy.uint8)
self.bmpbuf.CopyToBuffer(buf)
self.v[handle].bmpbuf=wx.BitmapFromBuffer(w, h, buf)
但总是得到错误:
[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: xcb_io.c:165: dequeue_pending_request: Zusicherung »!xcb_xlib_unknown_req_in_deq« nicht erfüllt.
修改
这是一个完全工作演示脚本,它显示了问题:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wx
import random
import time
import threading
class TestWin(wx.Window):
def __init__(self, parent, title, size):
wx.Window.__init__(self, parent)
self.Bind(wx.EVT_PAINT, self.onPaint)
self.Bind(wx.EVT_TIMER, self.onTimer)
t=threading.Thread(target=self.asThread, name="draw")
t.setDaemon(True)
t.start()
self.timer=wx.Timer(self)
self.timer.Start(100)
def onPaint(self, evt):
dc=wx.PaintDC(self)
dc.SetPen(wx.Pen("BLACK"))
dc.SetBrush(wx.Brush("BLUE"))
w, h=self.GetSize()
dc.DrawCirclePoint((random.randint(0, w), random.randint(0, h)), 5)
def onTimer(self, evt):
self.Refresh()
def asThread(self):
w, h=self.GetSize()
bmpbuf=wx.EmptyBitmapRGBA(w, h, 204, 204, 204, 1)
mdc=wx.MemoryDC()
mdc.SelectObject(bmpbuf)
time.sleep(1)
mdc.SetPen(wx.Pen("BLACK"))
mdc.SetBrush(wx.Brush("RED"))
print "now writing to MemoryDC"
while True:
#time.sleep(0.0001)
mdc.DrawCirclePoint((random.randint(0, w), random.randint(0, h)), 5)
wx.Yield()
class TestFrame(wx.Frame):
def __init__(self, parent, title, size):
wx.Frame.__init__(self, None, wx.ID_ANY, title)
win=TestWin(self, title, size)
if __name__=="__main__":
app=wx.App(False)
frame=TestFrame(None, "Test", size=(200, 200))
frame.Show()
app.MainLoop()
EDIT2:为什么我要在线程中构建位图:
我有一个类为给定的窗口大小,缩放级别和纬度/经度坐标提供位图(显示OpenStreetMap-tiles)。
该课程还将GPS轨迹和点列表绘制到地图/位图上。
因为位图的尺寸高于窗口尺寸,所以我可以在窗口下移动位图而不构建新的位图。
要移动位图,将调用dc.DrawBitmap(imgbuf,sx,sy),并为(sx,sy)略微更改值。每个新剪辑需要0.1ms。构建新的位图需要150毫秒
当从一个位置滚动时,它会滚动得非常平滑,直到需要新的位图。
如果可以准备新的位图,在滚动旧位图时,应该可以在长距离上连续平滑滚动。
答案 0 :(得分:1)
您不应该(并且在大多数情况下,不能)从主UI线程以外的任何操作UI对象。这包括DC和位图。你到底想要完成什么?可能还有其他一些方法可以做到。