wxPython: TextCtrl delayed update when using TE_RICH(2)

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • citronelu@yahoo.com

    #1

    wxPython: TextCtrl delayed update when using TE_RICH(2)

    I made a small wxPython app that retrieves web data; for visual
    logging I use a TextCtrl widget, and stdout is redirected to it,
    something like this:

    class RedirectOutput:
    def __init__(self, objectTxtCtrl):
    self.out = objectTxtCtrl

    def write(self, string):
    self.out.WriteT ext(string)

    [...]

    messages = wx.TextCtrl(pan el, -1, "", size = (-1, 200), style =
    wx.TE_MULTILINE | wx.TE_RICH, name = "messages")

    myout = RedirectOutput( messages)
    sys.stdout = myout


    The web query is inside a function (def Execute), binded to a button.
    To simplify the story, consider the function looks like this:

    def Execute(self, evt):
    print "Start query"
    time.sleep(5)

    The "Start query" message should show in the *messages* box when I
    press the button. Instead, it shows only after the time.sleep(5)
    delay.

    If I don't use the wx.TE_RICH / wx.TE_RICH2 style on *messages*, the
    text shows before the time.sleep(5)

    I want to use wx.TE_RICH / wx.TE_RICH2 because of the 64k limitation
    of the standard TextCtrl.

    I'm using python 2.4.3 and wxpython 2.8.1.1 unicode, on WinXP SP2.
    Windows extensions are also installed.

  • jean-michel bain-cornu

    #2
    Re: wxPython: TextCtrl delayed update when using TE_RICH(2)

    Hi,
    def Execute(self, evt):
    print "Start query"
    time.sleep(5)
    >
    The "Start query" message should show in the *messages* box when I
    press the button. Instead, it shows only after the time.sleep(5)
    delay.
    >
    If I don't use the wx.TE_RICH / wx.TE_RICH2 style on *messages*, the
    text shows before the time.sleep(5)
    For this kind of stuff, I'd try to put "self.out.Write Text(string)" in
    some 'Idle' event, which avoid to fall in focus loops or other objects
    events management problems not easy to solve.

    Did you try something like that :

    def write(self, string):
    self.outBuffer= string
    def onIdle(self,eve nt):
    if self.outBuffer != None:
    self.out.WriteT ext(self.outBuf fer)
    self.outBuffer= None

    Comment

    • Chris Mellon

      #3
      Re: wxPython: TextCtrl delayed update when using TE_RICH(2)

      On 2/4/07, jean-michel bain-cornu <pythonnews@nos pam.jmbc.frwrot e:
      Hi,
      def Execute(self, evt):
      print "Start query"
      time.sleep(5)

      The "Start query" message should show in the *messages* box when I
      press the button. Instead, it shows only after the time.sleep(5)
      delay.

      If I don't use the wx.TE_RICH / wx.TE_RICH2 style on *messages*, the
      text shows before the time.sleep(5)
      >
      For this kind of stuff, I'd try to put "self.out.Write Text(string)" in
      some 'Idle' event, which avoid to fall in focus loops or other objects
      events management problems not easy to solve.
      >
      This doesn't have anything to do with focus loops or otherwise, it's
      because the OP isn't familiar with event based programming.

      You're performing a long-running task which is preventing the event
      loop from processing, so your text isn't updating and your application
      is unresponsive. You need to rewrite your task - either do everything
      asynchronously, or use a threaded approach. If you use the thread
      approach, be sure to not call the updates directly, you can use the
      wx.CallAfter mechanism to call gui functions in a threadsafe manner.

      There is a lot of information about this on the wxPython wiki and in
      the archives of the wxpython-users ML.

      Comment

      • jean-michel bain-cornu

        #4
        Re: wxPython: TextCtrl delayed update when using TE_RICH(2)

        >For this kind of stuff, I'd try to put "self.out.Write Text(string)" in
        >some 'Idle' event, which avoid to fall in focus loops or other objects
        >events management problems not easy to solve.
        >>
        >
        This doesn't have anything to do with focus loops or otherwise, it's
        because the OP isn't familiar with event based programming.
        >
        You're performing a long-running task which is preventing the event
        loop from processing, so your text isn't updating and your application
        is unresponsive. You need to rewrite your task - either do everything
        asynchronously, or use a threaded approach. If you use the thread
        approach, be sure to not call the updates directly, you can use the
        wx.CallAfter mechanism to call gui functions in a threadsafe manner.
        So it is an event management problem.
        The event loop is not yet finished when the program want to display
        something, potentially initiating a new event loop.

        If you don't want to bother with threads, the idle event approach is not
        so bad. Put something to display in a buffer, and display it only one
        time the gui have nothing else to do.
        I use it every time I can, and it's very safe and easy to do.
        Furthermore, you can still step into the program with a debugger, which
        can be tricky if the program uses threads (I'd say impossible, but I
        didn't try in fact).

        Regards
        jm

        Comment

        • Chris Mellon

          #5
          Re: wxPython: TextCtrl delayed update when using TE_RICH(2)

          On 2/5/07, jean-michel bain-cornu <pythonnews@nos pam.jmbc.frwrot e:
          For this kind of stuff, I'd try to put "self.out.Write Text(string)" in
          some 'Idle' event, which avoid to fall in focus loops or other objects
          events management problems not easy to solve.
          >
          This doesn't have anything to do with focus loops or otherwise, it's
          because the OP isn't familiar with event based programming.

          You're performing a long-running task which is preventing the event
          loop from processing, so your text isn't updating and your application
          is unresponsive. You need to rewrite your task - either do everything
          asynchronously, or use a threaded approach. If you use the thread
          approach, be sure to not call the updates directly, you can use the
          wx.CallAfter mechanism to call gui functions in a threadsafe manner.
          >
          So it is an event management problem.
          The event loop is not yet finished when the program want to display
          something, potentially initiating a new event loop.
          >
          This is almost totally wrong. There is no "new event loop" involved.
          The OP is running a long task in the main thread, which is blocking
          the event loop. When the event loop is blocked, the application will
          not update and cannot be interacted with. It's that simple. The event
          loop in a gui application doesn't "finish" until the application
          exits.
          If you don't want to bother with threads, the idle event approach is not
          so bad. Put something to display in a buffer, and display it only one
          time the gui have nothing else to do.
          The problem is not putting the text into the control - the OP is
          mislead by the symptoms. The problem is the task he's perform in
          addition to the logging, which is a long running task (and in his
          sample code is represented by time.sleep). The logging issue is a red
          herring, the real problem is the way he's structured his application,
          with work blocking the event loop. Until he changes this, nothing
          about the way he writes to his log is going to fix the problem.
          I use it every time I can, and it's very safe and easy to do.
          Furthermore, you can still step into the program with a debugger, which
          can be tricky if the program uses threads (I'd say impossible, but I
          didn't try in fact).
          >
          Using idle events for continual calculation actually has several
          caveats you need to be aware of, and I don't recommend it. A
          background thread or a timer is generally a better solution.

          Comment

          • jean-michel bain-cornu

            #6
            Re: wxPython: TextCtrl delayed update when using TE_RICH(2)

            >
            This is almost totally wrong. There is no "new event loop" involved.
            The OP is running a long task in the main thread, which is blocking
            the event loop. When the event loop is blocked, the application will
            not update and cannot be interacted with. It's that simple. The event
            loop in a gui application doesn't "finish" until the application
            exits.
            I appreciate the fact that it is not *completely* wrong...
            Try to get out of your point of view, maybe you'll find something
            interesting. Maybe the 'true' part of mine.

            Regards
            jm

            Comment

            Working...