'DirectFrame' object has no attribute '_optionInfo'

I’m writing a GUI using pixel based placement, so my windows listen for window-event to redraw themselves on resolution changes so they wont scale with the resize. When the panda3d window loses focus I get the following

Traceback (most recent call last):
  File "/usr/share/panda3d/direct/showbase/EventManager.py", line 61, in eventLoopTask
    self.doEvents()
  File "/usr/share/panda3d/direct/showbase/EventManager.py", line 55, in doEvents
    processFunc(self.eventQueue.dequeueEvent())
  File "/usr/share/panda3d/direct/showbase/EventManager.py", line 122, in processEvent
    messenger.send(eventName, paramList)
  File "/usr/share/panda3d/direct/showbase/Messenger.py", line 309, in send
    self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
  File "/usr/share/panda3d/direct/showbase/Messenger.py", line 371, in __dispatch
    method (*(extraArgs + sentArgs))
  File "/home/croxis/src/Outpost/PixelWindow.py", line 97, in draw
    self.window['frameSize'] = (left, right, bottom, top)
  File "/usr/share/panda3d/direct/gui/DirectGuiBase.py", line 435, in __setitem__
    apply(self.configure, (), {key: value})
  File "/usr/share/panda3d/direct/gui/DirectGuiBase.py", line 328, in configure
    optionInfo = self._optionInfo
AttributeError: 'DirectFrame' object has no attribute '_optionInfo'
:task(error): Exception occurred in PythonTask eventManager
Unhandled error in Deferred:
Traceback (most recent call last):
  File "/usr/lib/python2.6/dist-packages/twisted/internet/base.py", line 1128, in run
    self.mainLoop()
  File "/usr/lib/python2.6/dist-packages/twisted/internet/base.py", line 1137, in mainLoop
    self.runUntilCurrent()
  File "/usr/lib/python2.6/dist-packages/twisted/internet/base.py", line 757, in runUntilCurrent
    call.func(*call.args, **call.kw)
  File "/usr/lib/python2.6/dist-packages/twisted/internet/task.py", line 114, in __call__
    d = defer.maybeDeferred(self.f, *self.a, **self.kw)
--- <exception caught here> ---
  File "/usr/lib/python2.6/dist-packages/twisted/internet/defer.py", line 106, in maybeDeferred
    result = f(*args, **kw)
  File "/usr/share/panda3d/direct/task/TaskNew.py", line 429, in step
    self.mgr.poll()
  File "/usr/share/panda3d/direct/showbase/EventManager.py", line 61, in eventLoopTask
    self.doEvents()
  File "/usr/share/panda3d/direct/showbase/EventManager.py", line 55, in doEvents
    processFunc(self.eventQueue.dequeueEvent())
  File "/usr/share/panda3d/direct/showbase/EventManager.py", line 122, in processEvent
    messenger.send(eventName, paramList)
  File "/usr/share/panda3d/direct/showbase/Messenger.py", line 309, in send
    self.__dispatch(acceptorDict, event, sentArgs, foundWatch)
  File "/usr/share/panda3d/direct/showbase/Messenger.py", line 371, in __dispatch
    method (*(extraArgs + sentArgs))
  File "/home/croxis/src/Outpost/PixelWindow.py", line 97, in draw
    self.window['frameSize'] = (left, right, bottom, top)
  File "/usr/share/panda3d/direct/gui/DirectGuiBase.py", line 435, in __setitem__
    apply(self.configure, (), {key: value})
  File "/usr/share/panda3d/direct/gui/DirectGuiBase.py", line 328, in configure
    optionInfo = self._optionInfo
exceptions.AttributeError: 'DirectFrame' object has no attribute '_optionInfo'

Bug? User error?

self.window['frameSize'] = (left, right, bottom, top) 

At the time of calling that, the widget hasn’t been initialized yet.

Also see this thread:
discourse.panda3d.org/viewtopic.php?t=2495

Good to know, and while I attempted to make it fit my case, my class is only a DirectObject

class Window(DirectObject.DirectObject):
    def __init__ (self, title="Title", size=(0,0), position=(0,0), center=False, xcenter=False, ycenter=False):
        self.accept('window-event', self.draw)
        ...
        self.window = DirectFrame(
                                  parent = base.a2dBottomLeft,
                                  pos = (xpos, 0, ypos)
                                  )
        #self.window.initialiseoptions(self.window)
        self.window.setBin("gui-popup", 50)
        
        # Title bar
        ypos = self.px2float(self.size[1]/2 + self.title_height/2)
        self.titleBar = DirectButton(
                                     parent = self.window, 
                                     relief = DGG.FLAT,
                                     pos = (0, 0, ypos)
                                     )
        ...
        # Set up 
        self.draw()
    
    def draw(self, args=None):
       ...        
        self.window['frameSize'] = (left, right, bottom, top)

        ...
class DialogueWindow(Window):
    """
    Generates a dialogue window with custom Direct Objects
    Scales to encompass text and buttons
    """
    def __init__(self, text, title = "Title", buttons = [], entries = []):
        Window.__init__(self, title=title, size=(0,0), center = True)
        ...
        self.draw()

[/code]

Yes, but the exception is occurring on your self.window object, which is a DirectFrame. It’s probably already been destroyed, actually, rather than not-yet-initialized.

David

self.window is being destroyed, but the fiction that I have to destroy it isn’t being called. self.window.initialiseoptions(self.window) and self.initialiseoptions(self.window) doesn’t work, what would be the correct syntax for this (if it is appropriate). What else would cause DirectFrame to be destroyed?

I don’t understand what you mean. There’s no reason to call initialiseoptions explicitly on a DirectFrame or any other DirectGui object, except in the very specific case of inheritance, and then only within the object’s own init() method. The DirectFrame initializes itself within its own constructor.

A DirectGui object is destroyed when its destroy() method is called, or when a parent object’s destroy() method is called.

David

That’s the problem, I’m not calling destroy()

I tell a lie, I am calling destroy, but on a different window.

Pastebin: pastebin.com/f2567c73d

When I call the intro window (function line 283, called on 325 with 326 commented out) no problems. However when I use the main menu (line 309), click on the new game button, the main menu is destroyed (319). My intro window then throws the error posted in the OP. It seems like the destroy command continues to propagate, but I’m at a loss at how to stop it or if my conclusion is even correct.

[edit]Solution for those who care: Instead of putting directframe in self.window just parented the class to direct frame, and used the solution pro-soft linked to in his first post