Choice widget is not updating itself.

Hello everybody,

I am new to wxpython, have bought and am reading the book, but
seem to have been thrown in the deep end a bit as I am making an
editor to embed in another application.

As I am still working my way through the book, please excuse
my ignorance. I have been trolling google and the mailing
list archives before posting (this is the first of a few).

I have a choice that displays available font names.

This is the call to create the widget:
FontWidget('fontchoice', frame=self,
            handler=self.OnFont, update=self.OnUpdateFont),

Here are the classes themselves. Please excuse the mess, this needs
a lot of refactoring, as I thought I would be using more ListWidgets.:

class ListWidget(object):
   def __init__(self, name, items=[], handler=None):
      self.name = name
      self.items = items
      self.handler = handler

   def add(self, bar, initselect = None):
      id = wx.NewId()
      choice = wx.Choice(bar, id, choices=self.items)
      choice.name = self.name
      if self.handler is not None:
         bar.Bind(wx.EVT_CHOICE, self.handler, choice)
      if self.update is not None:
         choice.Bind(wx.EVT_UPDATE_UI, self.update, choice)
      if initselect is not None:
         choice.SetStringSelection(initselect)
      bar.AddControl(choice)
      return bar

   def EvtChoice(self, event):
      pprint(dir(event))

class FontWidget(ListWidget):
# This needs to use another widget that allows font sensitive text
  def __init__(self, name, frame, handler=None, update=None):
    self.name = name
    self.frame = frame
    f = wx.FontEnumerator()
    f.EnumerateFacenames()
    self.items = f.GetFacenames()
    self.handler = handler
    self.update = update
   def add(self, bar):
    # get the current font set.
    attr = self.frame.GetCurStyle(self.frame.rtc)
    name = attr.GetFont().GetFaceName()
    return ListWidget.add(self, bar, initselect=name)

If I do this alone without binding the event, or binding it to
something that does nothing the choice widget updates the selection,
but with this as the binding:

   def OnFont(self, event):
      """ Grab the value for the font from the selection list, and if
      it is a selection set the selected text to that font, if there
      is no selection, start using the chosen font"""
      choice = event.GetEventObject()
      newfacename = choice.GetStringSelection()
      attr = self.GetCurStyle(self.rtc)
      if attr:
         curfont = attr.GetFont()
         curfont.SetFaceName(newfacename)
         attr.SetFont(curfont)
         self.ApplyNewStyle(self.rtc, attr)
      choice.SetStringSelection(newfacename)
      self.rtc.Refresh()
       event.Skip()

   def OnUpdateFont(self, event):
      """ Check what the current font that the cursor is on is, and if
      it has changed, change the value in the fontlist to reflect the
      current font"""
      attr = self.GetCurStyle(self.rtc)
      if attr:
         facename = attr.GetFont().GetFaceName()
         event.GetEventObject().SetStringSelection(facename)

What now happens is that the choice does not update until I move the
cursor. At which point it displays the correct setting, but this is
terrible UI, because it makes you think that the selection is not
taking for some reason, in fact it is so disconcerting that it catches
me out, and I am the one debugging the problem!

I am very new to wxPython and its objects etc. so any constructive
criticism would also be appreciated. :slight_smile:

Thanks in advance for helping.

Rohan

Hi Rohan,

Hello everybody,

I am new to wxpython, have bought and am reading the book, but
seem to have been thrown in the deep end a bit as I am making an
editor to embed in another application.

As I am still working my way through the book, please excuse
my ignorance. I have been trolling google and the mailing
list archives before posting (this is the first of a few).

I have a choice that displays available font names. This is the call to create the widget:
FontWidget('fontchoice', frame=self,
           handler=self.OnFont, update=self.OnUpdateFont),

Here are the classes themselves. Please excuse the mess, this needs
a lot of refactoring, as I thought I would be using more ListWidgets.:

class ListWidget(object):
  def __init__(self, name, items=, handler=None):
     self.name = name
     self.items = items
     self.handler = handler

  def add(self, bar, initselect = None):
     id = wx.NewId()
     choice = wx.Choice(bar, id, choices=self.items)
     choice.name = self.name
     if self.handler is not None:
        bar.Bind(wx.EVT_CHOICE, self.handler, choice)
     if self.update is not None:
        choice.Bind(wx.EVT_UPDATE_UI, self.update, choice)
     if initselect is not None:
        choice.SetStringSelection(initselect)
     bar.AddControl(choice)
     return bar

  def EvtChoice(self, event):
     pprint(dir(event))

class FontWidget(ListWidget):
# This needs to use another widget that allows font sensitive text
def __init__(self, name, frame, handler=None, update=None):
   self.name = name
   self.frame = frame
   f = wx.FontEnumerator()
   f.EnumerateFacenames()
   self.items = f.GetFacenames()
   self.handler = handler
   self.update = update

def add(self, bar):
   # get the current font set.
   attr = self.frame.GetCurStyle(self.frame.rtc)
   name = attr.GetFont().GetFaceName()
   return ListWidget.add(self, bar, initselect=name)

If I do this alone without binding the event, or binding it to
something that does nothing the choice widget updates the selection,
but with this as the binding:

  def OnFont(self, event):
     """ Grab the value for the font from the selection list, and if
     it is a selection set the selected text to that font, if there
     is no selection, start using the chosen font"""
     choice = event.GetEventObject()
     newfacename = choice.GetStringSelection()
     attr = self.GetCurStyle(self.rtc)
     if attr:
        curfont = attr.GetFont()
        curfont.SetFaceName(newfacename)
        attr.SetFont(curfont)
        self.ApplyNewStyle(self.rtc, attr)
     choice.SetStringSelection(newfacename)
     self.rtc.Refresh()
      event.Skip()

  def OnUpdateFont(self, event):
     """ Check what the current font that the cursor is on is, and if
     it has changed, change the value in the fontlist to reflect the
     current font"""
     attr = self.GetCurStyle(self.rtc)
     if attr:
        facename = attr.GetFont().GetFaceName()
        event.GetEventObject().SetStringSelection(facename)

What now happens is that the choice does not update until I move the
cursor. At which point it displays the correct setting, but this is
terrible UI, because it makes you think that the selection is not
taking for some reason, in fact it is so disconcerting that it catches
me out, and I am the one debugging the problem!

I am very new to wxPython and its objects etc. so any constructive
criticism would also be appreciated. :slight_smile:

Thanks in advance for helping.

Rohan

I'm not sure what's going on here. As I said in my other post, see the demo. You may need a Layout() or some such somewhere. See also the wxPython Style Guide for coding style tips: wxPython Style Guide - wxPyWiki

You can learn a lot on the wiki here: http://wiki.wxpython.org/

···

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org
Python Extension Building Network: http://www.pythonlibrary.org

Mike Driscoll wrote:

Hi Rohan,

Hello everybody,

I am new to wxpython, have bought and am reading the book, but
seem to have been thrown in the deep end a bit as I am making an
editor to embed in another application.

As I am still working my way through the book, please excuse
my ignorance. I have been trolling google and the mailing
list archives before posting (this is the first of a few).

I have a choice that displays available font names. This is the call to create the widget:
FontWidget('fontchoice', frame=self,
           handler=self.OnFont, update=self.OnUpdateFont),

Here are the classes themselves. Please excuse the mess, this needs
a lot of refactoring, as I thought I would be using more ListWidgets.:

class ListWidget(object):
  def __init__(self, name, items=, handler=None):
     self.name = name
     self.items = items
     self.handler = handler

  def add(self, bar, initselect = None):
     id = wx.NewId()
     choice = wx.Choice(bar, id, choices=self.items)
     choice.name = self.name
     if self.handler is not None:
        bar.Bind(wx.EVT_CHOICE, self.handler, choice)
     if self.update is not None:
        choice.Bind(wx.EVT_UPDATE_UI, self.update, choice)
     if initselect is not None:
        choice.SetStringSelection(initselect)
     bar.AddControl(choice)
     return bar

  def EvtChoice(self, event):
     pprint(dir(event))

class FontWidget(ListWidget):
# This needs to use another widget that allows font sensitive text
def __init__(self, name, frame, handler=None, update=None):
   self.name = name
   self.frame = frame
   f = wx.FontEnumerator()
   f.EnumerateFacenames()
   self.items = f.GetFacenames()
   self.handler = handler
   self.update = update

def add(self, bar):
   # get the current font set.
   attr = self.frame.GetCurStyle(self.frame.rtc)
   name = attr.GetFont().GetFaceName()
   return ListWidget.add(self, bar, initselect=name)

If I do this alone without binding the event, or binding it to
something that does nothing the choice widget updates the selection,
but with this as the binding:

  def OnFont(self, event):
     """ Grab the value for the font from the selection list, and if
     it is a selection set the selected text to that font, if there
     is no selection, start using the chosen font"""
     choice = event.GetEventObject()
     newfacename = choice.GetStringSelection()
     attr = self.GetCurStyle(self.rtc)
     if attr:
        curfont = attr.GetFont()
        curfont.SetFaceName(newfacename)
        attr.SetFont(curfont)
        self.ApplyNewStyle(self.rtc, attr)
     choice.SetStringSelection(newfacename)
     self.rtc.Refresh()
      event.Skip()

  def OnUpdateFont(self, event):
     """ Check what the current font that the cursor is on is, and if
     it has changed, change the value in the fontlist to reflect the
     current font"""
     attr = self.GetCurStyle(self.rtc)
     if attr:
        facename = attr.GetFont().GetFaceName()
        event.GetEventObject().SetStringSelection(facename)

What now happens is that the choice does not update until I move the
cursor. At which point it displays the correct setting, but this is
terrible UI, because it makes you think that the selection is not
taking for some reason, in fact it is so disconcerting that it catches
me out, and I am the one debugging the problem!

I am very new to wxPython and its objects etc. so any constructive
criticism would also be appreciated. :slight_smile:

Thanks in advance for helping.

Rohan

I'm not sure what's going on here. As I said in my other post, see the demo. You may need a Layout() or some such somewhere. See also the wxPython Style Guide for coding style tips: wxPython Style Guide - wxPyWiki

You can learn a lot on the wiki here: http://wiki.wxpython.org/

Thanks Mike,

I have been trolling the wiki a lot already. But it looks like I will use a combobox for this, so hopefully it will not have the same problems.

Rohan