在不触发EVT_大小的情况下调整wxPython面板的大小

在不触发EVT_大小的情况下调整wxPython面板的大小,python,wxpython,wxwidgets,Python,Wxpython,Wxwidgets,Edit当我用下面的编辑更新它时,我在测试中意识到python的回溯功能似乎有问题。我将发布一个新问题 编辑:更新,使问题更简单 问题 问题是,当调用EVT_SIZE事件处理程序中的函数时,无论出于何种原因都必须调整面板大小,它将成为一个无限循环,从而导致递归错误 使用布尔真/假变量(关于函数是否在EVT_大小处理程序中)解决此问题(在2.8中)。但是,这在2.9中不起作用,因为事件似乎已变得异步(或者至少在某种程度上,它意味着允许SetSize调用返回,标志重置,然后调用事件处理程序) 情况示

Edit当我用下面的编辑更新它时,我在测试中意识到python的回溯功能似乎有问题。我将发布一个新问题

编辑:更新,使问题更简单

问题

问题是,当调用EVT_SIZE事件处理程序中的函数时,无论出于何种原因都必须调整面板大小,它将成为一个无限循环,从而导致递归错误

使用布尔真/假变量(关于函数是否在EVT_大小处理程序中)解决此问题(在2.8中)。但是,这在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是非同步的,所以它在将其重置为false后触发,然后导致无限循环

完整代码

# 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_)
就这样怎么样

    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)

它看起来很简单,但哇,你真是太棒了,也从来没有意识到有一个解除绑定,但谢谢你。当我庆祝得太早,它没有工作将更新代码。对不起,它应该是
self.unbind(wx.EVT_SIZE)
(修复)不,它现在似乎与python中的回溯函数无关。我将您的问题标记为答案,因为我不知道什么是可行的,因为python似乎被破坏了:PIt最终证明是与大小相关的递归问题(但与此完全无关)当涉及到递归时,python似乎试图找到启动循环的函数,但它是错误的。