简体   繁体   English

如何并行绘制到PaintDC和MemoryDC?

[英]how to draw into a PaintDC and MemoryDC in parallel?

I'm looking for a pice of code, how to use a wx.PaintDC() and wx.MemoryDC in parallel. 我正在寻找一些代码,如何并行使用wx.PaintDC()和wx.MemoryDC。 My wxPython is in version 2.8.12 and I do not get it work to draw to a wx.PaintDC() into a wx.Window, while also having a thread running, that draws to a wx.MemoryDC into a bitmap. 我的wxPython的版本是2.8.12,我无法使它工作到将wx.PaintDC()绘制到wx.Window,同时还运行线程,从而将wx.MemoryDC绘制到位图。

Like this: 像这样:

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 and self.bmpbuf are not the same object. imgbufself.bmpbuf 不是同一对象。

self.bmpbuf is copied with this: 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)

But always getting errors like: 但总是会出现类似以下错误:

[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.

EDIT: 编辑:
here is a fully working demonstrator-script, that shows the problem: 这是一个可以正常工作的演示脚本,它显示了该问题:

#!/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: why I want to build a bitmap in a thread: EDIT2:为什么我要在线程中构建位图:
I have a class providing a bitmap (showing OpenStreetMap-tiles) for a given window-size, zoom-level and lat/lon-coordinate. 我有一类为给定的窗口大小,缩放级别和纬度/经度坐标提供位图(显示OpenStreetMap-tiles)。 The class also draws GPS-tracks and point-lists onto the map/bitmap. 该类还将GPS轨迹和点列表绘制到地图/位图上。 Because the dimensions of the bitmap are higher than the window-dimensions, I can move the bitmap under the window without building a new bitmap. 因为位图的尺寸大于窗口尺寸,所以我可以在窗口下移动位图,而无需构建新的位图。 To move the bitmap, dc.DrawBitmap(imgbuf, sx, sy) is called with slightly changed values for (sx, sy). 要移动位图,调用dc.DrawBitmap(imgbuf,sx​​,sy)并对其(sx,sy)的值稍作更改。 This takes 0.1ms per new clipping. 每次新裁剪需要0.1ms。 Building a new bitmap takes up to 150ms. 建立新的位图最多需要150ms。
When scrolling from one to another position, it scrolls very smooth until a new bitmap is needed. 从一个位置滚动到另一位置时,它滚动得非常平滑,直到需要新的位图为止。
If it would be possible to prepare the new bitmap, while scrolling over the old bitmap, a continuously smooth scrolling over a long distance should be possible. 如果有可能准备新的位图,同时在旧的位图上滚动,则在长距离上连续平滑的滚动应该是可能的。

You should not (and in most cases, can not) manipulate UI objects from anything other than the main UI thread. 除了主UI线程之外,您不应(而且在大多数情况下不能)操纵UI对象。 That includes DCs and bitmaps. 其中包括DC和位图。 What exactly are you trying to accomplish? 您到底想完成什么? There is likely some other way to do it. 可能还有其他方法可以做到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM