2012-08-27 35 views
5

Tôi đã gặp một số vấn đề với một chương trình mà tôi đã viết và sẽ đánh giá cao một số trợ giúp hoặc đầu vào. Đối với một số nền, tôi đang sử dụng Python 2,7 và wxPython để làm một khách hàng webcam streaming. Máy khách nhận các hình ảnh từ máy chủ theo chủ đề riêng của nó và đặt chúng vào một Hàng đợi. Chủ đề GUI sau đó lấy những hình ảnh đó từ Hàng đợi và chuyển đổi chúng thành một đối tượng wxBitmap. Điều này xảy ra sau mỗi giây và hoạt động rất tốt. Tôi có thể lưu đối tượng wxBitmap dưới dạng tệp để tôi biết rằng mọi thứ đều hoạt động bình thường.vấn đề hiển thị wxBitmaps bằng cách sử dụng wxPython

Sự cố mà tôi đang gặp là thực sự nhận được đối tượng wxBitmap để hiển thị trên GUI của tôi. Điều duy nhất tôi dường như có thể làm cho GUI làm là hiển thị một hình chữ nhật màu xám, nơi hình ảnh web cam nên được.

Đây là onPaint() tôi được gọi là khi tôi muốn làm mới màn hình:

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) 

một cách đơn giản, tôi đang ở một mất mát như lý do tại sao nó không làm việc. từ nghiên cứu của tôi, tôi đã tìm thấy rằng bởi vì tôi đang ở trên một máy cửa sổ, tôi cần các hàm BeginDrawing()EndDrawing(), vì vậy tôi đã thêm chúng. Vẫn không hoạt động. Không có lỗi hoặc ngoại lệ bị ném.

câu hỏi khác có thể giúp giải quyết vấn đề này:

  • tôi cập nhật một đối tượng wxFrame. Có lẽ các wxPaintDC cần phải hoạt động trong một loại container để làm việc?
  • ?

Thực ra, có thể chức năng __init__ của tôi là gì đang xảy ra sự cố. Tôi có thiết lập đúng cách này không?

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

Dù sao, cảm ơn trước sự giúp đỡ của bạn.

EDIT: Tôi đã giải quyết vấn đề vô tình bằng cách xóa dòng self.pnl = wx.Panel(self).

Vì vậy, dường như nó đã được hiển thị đúng cách, nhưng bitmap nằm bên dưới bảng điều khiển. Có lẽ? Tôi không chắc lắm. Tôi mới vào điều này toàn bộ wxPython.

+1

Hình ảnh xuất hiện bên dưới bảng điều khiển là khả năng. Trừ khi bạn đặt rõ ràng vị trí của việc sử dụng một 'wx.Sizer' các đối tượng mặc định là (0,0). Đó là lý do tại sao tôi sử dụng một sizer ngay cả khi tôi chỉ có 1 mục. – acattle

Trả lời

1

Điều đó dường như là bản demo wxPython cũng đang làm: dc.DrawBitmap. Và nó hoạt động trên Windows! Ít nhất, đó là những gì họ làm trong bản demo AlphaDrawing. Trong bản demo DrawImage, họ sử dụng dc.Blit(). Bạn có thể thử điều đó.

Tuy nhiên, tôi tự hỏi nếu bạn không thể làm điều đó giống như tôi đã làm với photo viewer của tôi. Tôi không sử dụng DC để vẽ, nhưng thay vì chỉ sử dụng một wx.StaticBitmap mà tôi cập nhật.

+0

Tôi đã thực sự xem mã của bạn cho trình xem ảnh trước khi tôi hỏi câu hỏi này. Tôi đã nhìn vào nó một không thể làm cho nó hoạt động được. Có lẽ một số lỗ hổng trong sự hiểu biết của tôi về cách wxPython hiển thị mọi thứ với màn hình, và tôi nghĩ rằng nó đã làm với cách wx.App, wx.Frame, và wx.Panel tất cả làm việc cùng nhau. Tôi nhận thấy rằng mã của bạn cho trình xem ảnh là một wx.Sizer và wx.Widgets bên trong một wx.Panel, bên trong một wx.Frame, bên trong một wx.App, trong khi tôi chỉ đơn thuần là một wx. Khung và đối tượng dc. Tôi sẽ cố gắng cơ cấu lại mã của tôi để tương tự với mã của bạn và lấy lại cho bạn. – user1626536

+0

Được rồi. Nó sẽ là tốt để xem một ví dụ runnable nhỏ. Điều đó sẽ giúp ích rất nhiều. –

+0

đây là mã mới của tôi hoạt động. dựa trên ví dụ từ blog của bạn, trình xem hình ảnh. Tôi vui vì nó hoạt động, nhưng tôi không vui khi nhấp nháy mỗi khi nó làm mới. Oh well. Giải quyết một lỗi và tạo một lỗi khác tôi đoán. heres mã: chỉnh sửa: quá nhiều ký tự để lại dưới dạng nhận xét. http://pastebin.com/WwHhTUAQ – user1626536

1

Mã này hoạt động. Nó hiển thị hình ảnh mọi lúc và mọi thứ. Nó có xu hướng 'nhấp nháy', mặc dù. Vì vậy, có lẽ một cách tốt hơn để làm điều này mà tôi không biết.

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() 
Các vấn đề liên quan