如何并行绘制到PaintDC和MemoryDC? [英] how to draw into a PaintDC and MemoryDC in parallel?

查看:300
本文介绍了如何并行绘制到PaintDC和MemoryDC?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一小段代码,如何并行使用wx.PaintDC()和wx.MemoryDC. 我的wxPython版本为2.8.12,但无法将其工作到将wx.PaintDC()绘制到wx.Window中,而 还有一个正在运行的线程,该线程将wx.MemoryDC绘制为位图.

I'm looking for a pice of code, how to use a wx.PaintDC() and wx.MemoryDC in parallel. 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.

赞:

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)

但是总是会出现类似这样的错误:

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.


这是一个完整的工作演示脚本,它显示了问题:


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()

为什么要在线程中生成位图:
我有一个类,为给定的窗口大小,缩放级别和纬度/经度坐标提供位图(显示OpenStreetMap-tiles). 该类还将GPS轨迹和点列表绘制到地图/位图上. 因为位图的尺寸大于窗口尺寸,所以我可以在窗口下移动位图,而无需构建新的位图. 要移动位图,调用dc.DrawBitmap(imgbuf,sx​​,sy)并对其(sx,sy)的值稍作更改.每次新剪辑需要0.1ms.构建新的位图最多需要150毫秒.
滚动从一个位置滚动到另一位置时,它滚动得非常平滑,直到需要新的位图为止.
如果有可能准备新的位图,同时在 old 位图上滚动,则可以在长距离上连续平滑地滚动.

why I want to build a bitmap in a thread:
I have a class providing a bitmap (showing OpenStreetMap-tiles) for a given window-size, zoom-level and lat/lon-coordinate. The class also draws GPS-tracks and point-lists onto the map/bitmap. 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). This takes 0.1ms per new clipping. Building a new bitmap takes up to 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.

推荐答案

除了主UI线程之外,您不应(而且在大多数情况下不能)操纵UI对象.其中包括DC和位图.您到底想完成什么?可能还有其他方法可以实现.

You should not (and in most cases, can not) manipulate UI objects from anything other than the main UI thread. That includes DCs and bitmaps. What exactly are you trying to accomplish? There is likely some other way to do it.

这篇关于如何并行绘制到PaintDC和MemoryDC?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆