2013-07-08 18 views
1

編輯當我更新這與下面的編輯時,我意識到在我的測試過程中,這是python的回溯函數看起來是錯誤的。我將發佈一個新的問題調整一個wxPython面板沒有EVT_SIZE正在被觸發

編輯:更新,使其更簡單的一個問題

問題

調用具有EVT_SIZE事件處理函數時的問題是無論出於何種原因調整面板大小,它都將變成無限循環,導致遞歸錯誤。

此用法用於確定(在2.8中)帶有布爾型真/假變量的EVT_SIZE處理函數內部的函數。然而,這在2.9中不起作用,因爲它看起來事件已變成異步的(或者至少在某種程度上,這意味着允許SetSize調用返回,標誌重置,然後調用事件處理程序)。情況

默認(不處理它使用布爾標誌

任何方式

import wx 


class TestPanel(wx.Panel): 

    def __init__(self, parent): 
     wx.Panel.__init__(self, parent, -1) 
     self.Bind(wx.EVT_SIZE, self.OnSize, self) 

     wx.CallLater(10000, self.ResizeThing) 

    def ResizeThing(self): 
     print "Doing our resize thing...." 
     # calculate whatever we need to calculate 
     # seems we got to change it in some way 
     self.SetSize(self.GetSize() + (30, 30)) 
     return "whatever we'd return" 

    def OnSize(self, event): 
     print "Size event got to resize" 
     self.ResizeThing() 


if __name__ == '__main__': 
    app = wx.App(False) 
    f = wx.Frame(None, -1) 
    TestPanel(f) 
    f.Show() 
    app.MainLoop() 

2.8解決方案

例子有沒有辦法來調整一個沒有evt size事件觸發的面板,因爲當它發生時,它會導致無限循環(在2.9,但對於某些原因,不是2.8)兒子)。

值得注意的代碼

def __init__(...): 
     ..... other stuff.... 
     self.Bind(wx.EVT_SIZE, self.OnSize, self) 

    def OnSize(self, event): 
     # if we didn't have it we would have a infinite recursion going evt_size -> update -> evt_size -> update -> evt_size -> update... forever 
     if not self.setting_size: 
      # update current size and set artwork 
      print self.GetSize() 
      print self.current_size 
      print "OnSize" 
      self.current_size = self.GetSize() 
      print self.current_size 
      self.UpdateArtwork(self.current_img) 


     else: 
      event.Skip() 



    def UpdateArtwork(self, img): 
     ... get scaled image and set the bitmap 
     img = self.scale(img) 
     self.SetBitmap(img.ConvertToBitmap()) 

    def scale(self, img): 
     print "Calling Scale" 
     # size the window to the correct dimensions 
     # get the size the sizer thinks is best 

     wW = self.GetBestVirtualSize()[0] # the width that the sizer reccomends 
     wH = self.GetBestVirtualSize()[1] # the height the sizer recommends 
     W = img.GetWidth() 
     H = img.GetHeight() 

     # modifiy the sizer recommendations to fit the image aspect ratio 
     # use bigger side as the base 
     if wW > wH: 
      # round to nearest integer value sense we are using future division 
      # get the new wH base on the image aspect ratio 
      wH = round(H/W * wW) # H/W how many H pixels per one W 
     else: 
      wW = round(W/H * wH) # W/H how many W pixels per one H 

     ... this is SUPPOSE to prevent a loop by flagging it 
     self.setting_size = True 
     print time.time() 
     print "Setting size in scale..." 
     self.current_size = (wW, wH) 
     print self.current_size 
     self.SetSize((wW, wH)) 
     print time.time() 
     self.setting_size = False 
     print time.time() 
     # then scale the image based on the panel size 
     return img.Scale(wW, wH) 

然而,這不起作用感知的EVT是不同步的,因此在重新設定爲假後觸發,然後使一個無限循環!

的完整代碼

# for proper scaling calculations (such things as .6451 going becoming 0) 
from __future__ import division 
import time 

import wx 

from twisted.web import client 
from twisted.python import log 

try: 
    import cStringIO as StringIO 
except ImportError: 
    import StringIO 

class URLImage(wx.StaticBitmap): 
    '''Allows a easy mechanism for setting url images''' 
    def __init__(self, parent, default_image): 
     wx.StaticBitmap.__init__(self, parent, -1) 

     self.current_img = None 
     self.current_url = None 
     self.current_size = self.GetSize() 

     self.di_d = default_image 
     self.default_image = wx.Image(default_image, wx.BITMAP_TYPE_ANY) 
     self.current_img = self.default_image 
     self.SetArtwork(self.default_image) 

     self.Bind(wx.EVT_SIZE, self.OnSize, self) 

    def OnSize(self, event): 
     # if we didn't have it we would have a infinite recursion going evt_size -> update -> evt_size -> update -> evt_size -> update... forever 
     if not self.current_size == self.GetSize(): 
      # update current size and set artwork 
      print self.GetSize() 
      print self.current_size 
      print "OnSize" 
      self.current_size = self.GetSize() 
      print self.current_size 
      self.UpdateArtwork(self.current_img) 


     else: 
      event.Skip() 

    def SetArtwork(self, img): 
     # for bitmaps (use corresponding method for urls) 
     self.current_url = None # the current artwork isn't a url, it is a bitmap 
     print "SetArtwork Updating Artwork" 
     self.UpdateArtwork(img) 


    def SetDefaultImage(self): 
     # this is to change the image to the default 
     # NOT to change the default image to some other one 
     # ^(like Text SetLabel changes the Label) 
     # similiar to SetArtwork 
     self.current_url = None 
     print "SetDefault Updating Artwork" 
     self.UpdateArtwork(self.default_image) 


    def SetArtworkFromURL(self, url = None): 

     if url == self.current_url: 
      print "[URLImage] Duplicate URL" 
      return 

     else: 
      # set back the defualt art 
      print "Defaulting for URL loading" 
      self.UpdateArtwork(self.default_image) 
      # update current_url 
      self.current_url = url 

     if url == None: 
      return 

     d = client.getPage(url.encode("ascii"), method = "GET", agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2b4) Gecko/20091124 Firefox/3.6b4 (.NET CLR 3.5.30729)') 
     d.addCallback(lambda data: self.UpdateArtwork(wx.ImageFromStream(StringIO.StringIO(data)))) 
     d.addErrback(self.error) 

    def UpdateArtwork(self, img): 
     # ALBUM ART 
     # From: http://www.blog.pythonlibrary.org/2010/03/26/creating-a-simple-photo-viewer-with-wxpython/ 
     # scale the image, preserving the aspect ratio 
     self.current_img = img 
     print "Update Artwork" 
     img = self.scale(img) 
     self.SetBitmap(img.ConvertToBitmap()) 

    def scale(self, img): 
     print "Calling Scale" 
     # size the window to the correct dimensions 
     # get the size the sizer thinks is best 

     wW = self.GetBestVirtualSize()[0] # the width that the sizer reccomends 
     wH = self.GetBestVirtualSize()[1] # the height the sizer recommends 
     W = img.GetWidth() 
     H = img.GetHeight() 

     # modifiy the sizer recommendations to fit the image aspect ratio 
     # use bigger side as the base 
     if wW > wH: 
      # round to nearest integer value sense we are using future division 
      # get the new wH base on the image aspect ratio 
      wH = round(H/W * wW) # H/W how many H pixels per one W 
     else: 
      wW = round(W/H * wH) # W/H how many W pixels per one H 

     self.setting_size = True 
     print time.time() 
     print "Setting size in scale..." 
     self.current_size = (wW, wH) 
     print self.current_size 
     self.SetSize((wW, wH)) 
     print time.time() 
     self.setting_size = False 
     print time.time() 
     # then scale the image based on the panel size 
     return img.Scale(wW, wH) 


    def error(self, err_): 
     ''' Error callback for fetching the album art''' 
     self.current_url = None# no current (succesful) url artwork set 
     self.SetArtwork(self.default_image) 
     log.msg("Error getting Album Artwork") 
     log.err(err_) 

回答

2

如何回合剛剛

print "Setting size in scale..." 
    #unbind Size Event 
    self.UnBind(wx.EVT_SIZE) 

    self.current_size = (wW, wH) 
    print self.current_size 
    self.SetSize((wW, wH)) 
    print time.time() 
    self.Update() #force update so it does not trigger after rebind 
    #rebind Size Event 
    self.Bind(wx.EVT_SIZE, self.OnSize, self) 
+0

它似乎很簡單,但哇你真棒,也從來沒有意識到有解除綁定,但謝謝你。 – Zimm3r

+0

當時我似乎慶祝得太早,沒有工作會更新代碼。 – Zimm3r

+0

對不起,它應該是'self.Unbind(wx.EVT_SIZE)'(固定) –