2012-08-27 23 views
5

私が書いたプログラムにいくつかの問題がありました。いくつかの背景のために、私はストリーミングウェブカメラクライアントを行うためにPython 2.7とwxPythonを使用しています。クライアントは、自分のスレッドでサーバーからイメージを取得し、キューに入れます。 GUIスレッドは、それらのイメージをQueueから取得し、wxBitmapオブジェクトに変換します。これは0.5秒ごとに発生し、うまく動作します。 wxBitmapオブジェクトをファイルとして保存できるので、すべてが正しく動作していることがわかります。wxPythonを使用してwxBitmapsを表示する際の問題

私が抱えている問題は、実際にはwxBitmapオブジェクトがGUIに表示されていることです。私はGUIを作ることができるように思える唯一の事は、Webカム画像があるはずの灰色の矩形を表示することです。

は、ここで私は、画面をリフレッシュしたいときに呼び出される私のonPaint()次のとおりです。

def onPaint(self,e): 
      ## this is the function that actually draws and redraws the window 
      ## to be displayed. I think it is something similar to blit() 
      ## in other graphical display frameworks 
      print "in onPaint" 

      ## create the device context object (graphics painter) 
      dc = wx.PaintDC(self) 
      dc.BeginDrawing() 

      ## draw the bitmap to the screen 
      dc.DrawBitmap(self.imageBit,0,0,True) 
      dc.EndDrawing()    

      ## test code. 
      ## the following works and updates, which means that 
      ## everything is being converted properly and updated. 
      ## not sure why the dc won't paint it to the window. 
      self.imageBit.SaveFile("bit.bmp", wx.BITMAP_TYPE_BMP) 

簡単に言えば、私はなぜその動作していないのと途方に暮れてよ。私の研究から、私はWindowsマシン上にあるので、BeginDrawing()EndDrawing()の関数が必要なので、それらを追加しました。まだ動作しません。エラーや例外はスローされません。この問題を解決するのに役立つかもしれない

他の質問:

  • 私はwxFrameオブジェクトを更新しています。おそらくwxPaintDCは別のタイプのコンテナで動作する必要がありますか?

実際には、私の__init__機能が問題を抱えている可能性があります。私はこれを正しく設定していますか?

class viewWindow(wx.Frame): 
    imgSizer = (480,360) 
    def __init__(self, *args, **kw): 
      ## this is called when an instance of this class is created 
      super(viewWindow,self).__init__(*args,**kw) 

      ## here is where the actual stuff inside the frame is set up. 

      self.pnl = wx.Panel(self) 

      ## create a button that opens up a Connection Window 
      #test = wx.Button(self.pnl, label='Connection Settings') 
      ## test.Bind(wx.EVT_BUTTON, self.openConnectionWindow) 

      ## create the wxImage for the web cam pic 
      self.image = wx.EmptyImage(self.imgSizer[0],self.imgSizer[1]) 

      ## create the wxBitmap so that the wxImage can be displayed 
      self.imageBit = wx.BitmapFromImage(self.image) 

      ## create a timer that will update the window based of frame rate 
      self.timex = wx.Timer(self, wx.ID_OK) 
      self.timex.Start(500) 
      self.Bind(wx.EVT_TIMER, self.redraw, self.timex) 

      ## need to do the following in order to display images in wxPython: 
      self.Bind(wx.EVT_PAINT, self.onPaint) 

      self.SetSize(self.imgSizer) 
      self.SetTitle('View Window') 
      self.Show() 

とにかく、ありがとうございました。

EDIT:という行を削除して誤って問題を解決しました。

明らかに、それは適切にレンダリングされていましたが、ビットマップはパネルの下にありました。多分?私は本当にわからない。私はwxPython全体のこの新しいことです。

+1

パネルの下に表示される画像は可能性があります。明示的に使用位置を 'wx.Sizer'に設定しない限り、オブジェクトのデフォルトは(0,0)になります。だから私は1つのアイテムしか持っていなくてもサイザーを使うのです。 – acattle

答えて

1

これは、wxPythonのデモがやっているようです:dc.DrawBitmap。そしてそれはWindows上で動作します!少なくとも、AlphaDrawingのデモではそういったことがあります。 DrawImageデモでは、dc.Blit()を使用します。あなたはそれを試みるかもしれません。

しかし、私はphoto viewerと同じようにあなたがそれをすることができないのだろうかと思います。描画にDCを使用するのではなく、更新するwx.StaticBitmapを使用するだけです。

+0

私はこの質問をする前に実際に写真ビューアのコードを見ていました。私はそれを見て、それを働かせることができなかった。おそらく、wxPythonが画面にどのようにレンダリングするかについての私の理解にはいくつかの欠陥があり、wx.App、wx.Frame、およびwx.Panelがどのように連携して動作するかが関係していると思います。私は、写真ビューアのコードはwx.Sizerであり、wx.Panelの中​​のwx.Widgetsはwx.Frameの内側にあり、wx.Appの内側にあり、私は単なるwxです。フレームとDCオブジェクト。私は自分のコードをあなたのものと似て再構築しようとしています。 – user1626536

+0

小さな実行可能な例を見るとよいでしょう。それはすごく助けになるでしょう。 –

+0

ここに新しいコードがあります。あなたのブログの例である画像ビューアに基づいています。私はそれがうまくいけばうれしいですが、私はそれがリフレッシュするたびにちらつきで幸せではありません。しかたがない。 1つのバグを解決し、私が推測する別のバグを作成してください。 heres the code:edit:あまりにも多くの文字をコメントとして残す。 http://pastebin.com/WwHhTUAQ – user1626536

1

このコードは機能します。それは毎回、そしてすべてのイメージを表示します。しかし、それは "ちらつき"傾向があります。だから私が気づいていない、これを行うためのより良い方法があります。

class viewWindow(wx.Frame): 
    imgSizer = (480,360) 
    def __init__(self, parent, title="View Window"): 
      super(viewWindow,self).__init__(parent) 
      ## create the menu and its sub trees 
      menubar = wx.MenuBar() 
      filemenu = wx.Menu() 
      menubar.Append(filemenu, 'File') 
      self.fitem = filemenu.Append(wx.ID_ANY, 'Open Connection Window') 
      self.Bind(wx.EVT_MENU, self.openConnectionWindow, self.fitem) 
      self.SetMenuBar(menubar) 

      ## here is where the actual stuff inside the frame is set up. 
      self.pnl = wx.Panel(self) 
      self.vbox = wx.BoxSizer(wx.VERTICAL) 

      ## create the wxImage for the web cam pic 
      self.image = wx.EmptyImage(self.imgSizer[0],self.imgSizer[1]) 

      ## create the wxBitmap so that the wxImage can be displayed 
      self.imageBit = wx.BitmapFromImage(self.image) 
      self.staticBit = wx.StaticBitmap(self.pnl,wx.ID_ANY, self.imageBit) 

      ## add the staticBit to the sizer so it is rendered properly on resizes and such 
      ## note: not actually needed to get the image to display, but reccommended for ease 
      ## of layout 
      self.vbox.Add(self.staticBit) 

      ## register the sizer with the panel so the panel knows to use it. 
      self.pnl.SetSizer(self.vbox) 

      ## create a timer that will update the window based on frame rate 
      self.timex = wx.Timer(self, wx.ID_OK) 
      self.timex.Start(1000/framerate) 
      self.Bind(wx.EVT_TIMER, self.redraw, self.timex) 

      ## set the size of the frame itself when it is first opened 
      self.SetSize(self.imgSizer) 
      self.Show() 

    def openConnectionWindow(self, e): 
      ## this will open a new connection window 
      connect = connectionWindow(None) 

    def redraw(self,e): 
      ## this function updates the frame with the latest web cam image that has been 
      ## retrieved by the client thread from the server. 

      ## get the newest image in the queue 
      if not imgQ.empty():       
        picz = imgQ.get() 
        ## convert the image from a string to something usable (wxImage) 
        self.image.SetData(picz) 
        ## from wxImage to wxBitmap 
        self.imageBit = wx.BitmapFromImage(self.image) 
        self.staticBit = wx.StaticBitmap(self.pnl,wx.ID_ANY, self.imageBit) 
        ## refresh the frame 
        self.Refresh() 
関連する問題