DirectGui focus problems

I’m trying to get to terms with DirectGui. I want the tab key to move between text fields. My first attempt involves hooking “focusIn” to set a “next field” variable, and then hooking “tab” to set the focus to the declared field.

The code is at the bottom, it has a “Name” and a “Password” field and a “Login” button. I get the “onTab()” call, but I can only tab from Password to Name; if focus is in Name, and I press Tab, it doesn’t go to Password.

What am I doing wrong?

Note that while the manual does talk about a few things for these classes, there are a lot of things it doesn’t talk about – like, how can I find out what is the current focus? Also, there is no “help()” on the DirectGui classes, and they are not in the reference section – is this known/intended?

class LoginDialog(DirectObject):
  def __init__(self):
    self.loginFrame = DirectGui.DirectFrame(pos=(0.3,0,-0.5), \
      frameSize=(-0.3,0.6,-0.37,0.1),relief=DirectGui.DGG.RAISED, \
      borderWidth=(0.01,0.01))
    self.text1 = DirectGui.DirectLabel(pos=(-0.25,0,-0.02), \
      text="Name",scale=0.05,text_align=TextProperties.ALeft)
    self.text1.reparentTo(self.loginFrame)
    self.text2 = DirectGui.DirectLabel(pos=(-0.25,0,-0.12), \
      text="Password",scale=0.05,text_align=TextProperties.ALeft)
    self.text2.reparentTo(self.loginFrame)
    self.myNameEdit = DirectGui.DirectEntry(numLines=1,focus=1, \
      width=10,scale=0.05,cursorKeys=1,pos=(0,0,-0.02), \
      relief=DirectGui.DGG.SUNKEN,borderWidth=(0.05,0.05), \
      focusInCommand=self.onFocus,focusInExtraArgs=[2])
    self.myNameEdit.reparentTo(self.loginFrame)
    self.myPasswordEdit = DirectGui.DirectEntry(numLines=1,focus=0, \
      width=10,scale=0.05,cursorKeys=1,pos=(0,0,-0.12), \
      relief=DirectGui.DGG.SUNKEN,borderWidth=(0.05,0.05), \
      focusInCommand=self.onFocus,focusInExtraArgs=[1])
    self.myPasswordEdit.reparentTo(self.loginFrame)
    self.myPasswordButton = DirectGui.DirectButton(text="Login", \
      frameSize=(-1.5,1.6,-0.7,1.1),pos=(0.37,0,-0.27), \
      scale=0.05,pressEffect=1,borderWidth=(0.1,0.1), \
      relief=DirectGui.DGG.RAISED)
    self.myPasswordButton.reparentTo(self.loginFrame)
    self.accept("tab", self.onTab)
    self.focusNextField = 1
  
  def onFocus(self, widget):
    print("onFocus(" + str(widget) + ")")
    self.focusNextField = widget
  
  def onTab(self):
    print("onTab(" + str(self.focusNextField) + ")")
    if self.focusNextField == 1:
      self.myNameEdit.setFocus()
    else:
      self.myPasswordEdit.setFocus()
  
  def showHide(self, visible):
    if visible:
      self.loginFrame.reparentTo(aspect2d)
    else:
      self.loginFrame.deatchNode()

loginDialog = LoginDialog()

run()

The thing you are missing is the misleading method names on DirectEntry. In general, you almost never call DirectGuiObject.setBlah(newValue). Instead, you do DirectGuiObject[‘blah’] = newValue.

I’m not entirely sure why the DirectGui interface is so weird in this way. I think the developer who originally designed it was patterning the design after a tool called Python Mega-Widgets, which I’m told is similarly weird.

In any case, the correct modification to your code is:

  def onTab(self):
    print("onTab(" + str(self.focusNextField) + ")")
    if self.focusNextField == 1:
      self.myNameEdit['focus'] = 1
    else:
      self.myPasswordEdit['focus'] = 1

Similarly, you can query whether a particular DirectEntry has focus via something like self.myNameEdit[‘focus’], which returns either 0 or 1. I don’t think there is a way to directly ask which item has focus without querying all of them one at a time.

Yeah, this part of the code doesn’t live up to Panda’s normal standards of documentation, either. What can you do. Maybe one day, a motivated Panda community member will document it properly. :wink:

David

Thanks for the reply! I’ll plow on.