2012-08-27 14 views
5

का उपयोग कर wxBitmaps को प्रदर्शित करने में समस्याएं मुझे एक प्रोग्राम के साथ कुछ समस्याएं आई हैं जो मैं लिख रहा हूं और कुछ मदद या इनपुट की सराहना करता हूं। कुछ पृष्ठभूमि के लिए, मैं स्ट्रीमिंग वेबकैम क्लाइंट करने के लिए पाइथन 2.7 और wxPython का उपयोग कर रहा हूं। ग्राहक सर्वर से छवियों को अपने धागे में प्राप्त करता है, और उन्हें एक कतार में रखता है। जीयूआई थ्रेड तब उन छवियों को कतार से प्राप्त करता है और उन्हें wxBitmap ऑब्जेक्ट में परिवर्तित करता है। यह हर 5 सेकंड होता है और बहुत अच्छा काम करता है। मैं wxBitmap ऑब्जेक्ट को फ़ाइल के रूप में सहेजने में सक्षम हूं इसलिए मुझे पता है कि सब ठीक से काम कर रहा है।WxPython

मुझे जो समस्या है वह वास्तव में wxBitmap ऑब्जेक्ट को मेरे जीयूआई पर दिखाने के लिए प्राप्त कर रहा है। एकमात्र चीज जो मुझे लगता है कि जीयूआई करने में सक्षम होना एक ग्रे आयताकार प्रदर्शित करता है जहां वेब कैमरा छवि होना चाहिए।

यहाँ मेरी 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) 

सीधे शब्दों में कहें, मैं क्यों अपने काम नहीं कर के रूप में एक नुकसान में हूँ। मेरे शोध से मैंने पाया है कि क्योंकि मैं विंडोज़ मशीन पर हूं, मुझे 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() 

वैसे भी, आपकी मदद के लिए अग्रिम धन्यवाद।

संपादित करें: मैंने लाइन self.pnl = wx.Panel(self) को हटाकर गलती से समस्या हल की।

तो जाहिर है कि यह ठीक से प्रस्तुत कर रहा था, लेकिन बिटमैप पैनल के नीचे था। शायद? मैं बहुत पक्का नहीं हूँ। मैं इस पूरे wxPython बात के लिए नया हूँ।

+1

पैनल के नीचे दिखाई देने वाली छवि एक संभावना है। जब तक आप स्पष्ट रूप से उपयोग की स्थिति को 'wx.Sizer' ऑब्जेक्ट को डिफ़ॉल्ट रूप से सेट नहीं करते हैं (0,0)। यही कारण है कि मैं एक साइज़र का उपयोग करता हूं भले ही मेरे पास केवल 1 आइटम हो। – acattle

उत्तर

1

ऐसा लगता है कि WxPython डेमो भी क्या कर रहा है: dc.DrawBitmap। और यह विंडोज पर काम करता है! कम से कम, अल्फा ड्रॉइंग डेमो में वे यही करते हैं। DrawImage डेमो में, वे dc.Blit() का उपयोग करते हैं। आप कोशिश कर सकते हैं।

हालांकि, मुझे आश्चर्य है कि आप ऐसा नहीं कर पाएंगे जैसे मैंने अपने photo viewer के साथ किया था। मैं डीसी को आकर्षित करने के लिए उपयोग नहीं करता, लेकिन इसके बजाय बस एक wx.StaticBitmap का उपयोग करें जो मैं अद्यतन करता हूं।

+0

मैंने इस सवाल से पहले मैंने वास्तव में फोटो व्यूअर के लिए अपना कोड देखा था। मैंने इसे देखा था इसे काम करने के लिए नहीं मिल सका। WxPython स्क्रीन पर चीजें कैसे प्रस्तुत करता है, इस बारे में मेरी समझ में शायद कुछ दोष है, और मुझे लगता है कि इसे wx.App, wx.frame, और wx.Panel सभी के साथ मिलकर काम करना है। मैंने देखा है कि फोटो व्यूअर के लिए आपका कोड एक wx.Sizer और wx.Widgets wx.Panel के अंदर है, जो wx.Frame के अंदर है, जो wx.App के अंदर है, जबकि मेरा केवल एक wx है। फ्रेम और एक डीसी वस्तु। मैं अपने कोड को पुन: व्यवस्थित करने की कोशिश करने जा रहा हूं ताकि आप अपने जैसा हो सकें और वापस आ सकें। – user1626536

+0

ठीक है। एक छोटे से चलने योग्य उदाहरण देखना अच्छा होगा। इससे जबरदस्त मदद मिलेगी। –

+0

यहां मेरा नया कोड है जो काम करता है। यह आपके ब्लॉग, छवि दर्शक से उदाहरण के आधार पर है। मुझे खुशी है कि यह काम करता है, लेकिन हर बार जब यह ताज़ा होता है तो मैं झिलमिलाहट से खुश नहीं हूं। ओह अच्छा। एक बग हल करें और मुझे लगता है कि एक और बनाओ। कोड का पालन करता है: संपादित करें: टिप्पणी के रूप में छोड़ने के लिए बहुत से वर्ण। 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()