disable input on a window whitout using Enable()

Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

Oswaldo,

<div class="moz-text-flowed" style="font-family: -moz-fixed">Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

http://www.wxpython.org/docs/api/wx.Window-class.html

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

···

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

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

Mike Driscoll escribió:

Oswaldo,

<div class="moz-text-flowed" style="font-family: -moz-fixed">Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

wxPython API Documentation — wxPython Phoenix 4.2.2 documentation

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

Thanks for your reply, but, Freeze and Thaw don't solve my problem.

Is there another way?

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

Oswaldo,

Mike Driscoll escribió:

Oswaldo,

Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

wxPython API Documentation — wxPython Phoenix 4.2.2 documentation

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

Thanks for your reply, but, Freeze and Thaw don't solve my problem.

Is there another way?

How is it not working? You could use it in combination with your trick. Something like this:

frame.Freeze()
frame.Disable()
# do stuff
frame.Enable()
frame.Thaw()

The freezing of the frame will stop the frame from re-drawing itself, so when you call Disable/Enable, you won't see a flicker.

···

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

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

Mike Driscoll escribió:

Oswaldo,

Mike Driscoll escribió:

Oswaldo,

Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

wxPython API Documentation — wxPython Phoenix 4.2.2 documentation

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

Thanks for your reply, but, Freeze and Thaw don't solve my problem.

Is there another way?

How is it not working? You could use it in combination with your trick. Something like this:

frame.Freeze()
frame.Disable()
# do stuff
frame.Enable()
frame.Thaw()

The freezing of the frame will stop the frame from re-drawing itself, so when you call Disable/Enable, you won't see a flicker.

Yes, but Disable() cancel the cursor change.
If i do:

oldcursor = frame.GetCursor()
frame.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
frame.Freeze()
frame.Disable()
# do job
frame.Enable()
frame.Thaw()
frame.SetCursor(oldcursor)

The frame do not flick but the cursor do not change to CURSOR_WAIT, Disable() change it to normal arrow cursor.

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

Instead of disabling the whole frame, if you want to prevent undue inputs by the user you could disable only the widgets where the input may occur.

···

2008/9/11 Oswaldo Hernández listas@soft-com.es

Mike Driscoll escribió:

Oswaldo,

Mike Driscoll escribió:

Oswaldo,

Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

http://www.wxpython.org/docs/api/wx.Window-class.html

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

Thanks for your reply, but, Freeze and Thaw don’t solve my problem.

Is there another way?

How is it not working? You could use it in combination with your trick. Something like this:

frame.Freeze()

frame.Disable()

do stuff

frame.Enable()

frame.Thaw()

The freezing of the frame will stop the frame from re-drawing itself, so when you call Disable/Enable, you won’t see a flicker.

Yes, but Disable() cancel the cursor change.

If i do:

oldcursor = frame.GetCursor()

frame.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))

frame.Freeze()

frame.Disable()

do job

frame.Enable()

frame.Thaw()

frame.SetCursor(oldcursor)

The frame do not flick but the cursor do not change to CURSOR_WAIT, Disable() change it to normal arrow cursor.


Oswaldo Hernández

oswaldo (@) soft-com (.) es


PD:

Antes de imprimir este mensaje, asegúrese de que es necesario.

El medio ambiente está en nuestra mano.


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Oswaldo Hernández wrote:

<div class="moz-text-flowed" style="font-family: -moz-fixed">Mike Driscoll escribió:

Oswaldo,

Mike Driscoll escribió:

Oswaldo,

Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

wxPython API Documentation — wxPython Phoenix 4.2.2 documentation

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

Thanks for your reply, but, Freeze and Thaw don't solve my problem.

Is there another way?

How is it not working? You could use it in combination with your trick. Something like this:

frame.Freeze()
frame.Disable()
# do stuff
frame.Enable()
frame.Thaw()

The freezing of the frame will stop the frame from re-drawing itself, so when you call Disable/Enable, you won't see a flicker.

Yes, but Disable() cancel the cursor change.
If i do:

oldcursor = frame.GetCursor()
frame.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
frame.Freeze()
frame.Disable()
# do job
frame.Enable()
frame.Thaw()
frame.SetCursor(oldcursor)

The frame do not flick but the cursor do not change to CURSOR_WAIT, Disable() change it to normal arrow cursor.

I'm not sure what you're talking about. On Windows XP with wxPython 2.8.8.1 and Python 2.5.2, this works fine. When I mouse over the program, it shows the busy mouse icon. Here's some test code:

<code>

import wx
import time
class MyForm(wx.Frame):
     def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")
         # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        btn = wx.Button(panel, wx.ID_ANY, 'Push me!')
        self.Bind(wx.EVT_BUTTON, self.onButton, btn)

    def onButton(self, event):
        oldcursor = self.GetCursor()
        print 'Setting CURSOR_WAIT...'
        self.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
        self.Freeze()
        self.Disable()
        for x in range(10):
            time.sleep(1)
            print x
        self.Enable()
        self.Thaw()
        print 'Thawed and resetting cursor!'
        self.SetCursor(oldcursor)
       
# Run the program
if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MyForm().Show()
    app.MainLoop()

</code>

See also Raffaello's post.

Mike

BTW, if the widget is a wx.TextCtrl and instead of «disabling» it you block it with SetEditable(False), there is no redrawing and therefore no flickering.

···

2008/9/11 Mike Driscoll mike@pythonlibrary.org

Oswaldo Hernández wrote:

Mike Driscoll escribió:

Oswaldo,

Mike Driscoll escribió:

Oswaldo,

Hello,

When I update a frame with data form database, or make some tasks, to prevent user input while the task is running I disable the frame and enable it when the task is done, but it makes a strange flick.

How can disable the keyboard and mouse input on a frame whitout using Enable()?.

Thanks.

You could probably use the Freeze and Unfreeze methods. These methods are made for just this sort of thing. See the docs here:

http://www.wxpython.org/docs/api/wx.Window-class.html

FYI: wx.Frame subclasses wx.Window (if I understand correctly).

Thanks for your reply, but, Freeze and Thaw don’t solve my problem.

Is there another way?

How is it not working? You could use it in combination with your trick. Something like this:

frame.Freeze()

frame.Disable()

do stuff

frame.Enable()

frame.Thaw()

The freezing of the frame will stop the frame from re-drawing itself, so when you call Disable/Enable, you won’t see a flicker.

Yes, but Disable() cancel the cursor change.

If i do:

oldcursor = frame.GetCursor()

frame.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))

frame.Freeze()

frame.Disable()

do job

frame.Enable()

frame.Thaw()

frame.SetCursor(oldcursor)

The frame do not flick but the cursor do not change to CURSOR_WAIT, Disable() change it to normal arrow cursor.

I’m not sure what you’re talking about. On Windows XP with wxPython 2.8.8.1 and Python 2.5.2, this works fine. When I mouse over the program, it shows the busy mouse icon. Here’s some test code:

import wx

import time

class MyForm(wx.Frame):

def init(self):

   wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")



   # Add a panel so it looks the correct on all platforms

   panel = wx.Panel(self, wx.ID_ANY)

   btn = wx.Button(panel, wx.ID_ANY, 'Push me!')

   self.Bind(wx.EVT_BUTTON, self.onButton, btn)

def onButton(self, event):

   oldcursor = self.GetCursor()

   print 'Setting CURSOR_WAIT...'

   self.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))

   self.Freeze()

   self.Disable()

   for x in range(10):

       time.sleep(1)

       print x

   self.Enable()

   self.Thaw()

   print 'Thawed and resetting cursor!'

   self.SetCursor(oldcursor)

Run the program

if name == “main”:

app = wx.PySimpleApp()

frame = MyForm().Show()

app.MainLoop()

See also Raffaello’s post.

Mike


wxpython-users mailing list

wxpython-users@lists.wxwidgets.org

http://lists.wxwidgets.org/mailman/listinfo/wxpython-users

Mike Driscoll escribió:
....

Mike, test these code:

<code>

import wx

frame = None
frame2 = None

class MyForm(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        btn = wx.Button(panel, wx.ID_ANY, 'Push me!')
        self.Bind(wx.EVT_BUTTON, self.onButton, btn)

    def onButton(self, event):
        oldcursor = self.GetCursor()
        print 'Setting CURSOR_WAIT...'
        self.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
        self.Freeze()
        self.Disable()
        for x in range(1000):
            wx.GetApp().Yield()
            wx.MilliSleep(25)
            frame2.text.SetValue(str(x))
        self.Enable()
        self.Thaw()
        print 'Thawed and resetting cursor!'
        self.SetCursor(oldcursor)

class From2(wx.Frame):
     def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Form2")
        panel = wx.Panel(self, wx.ID_ANY)
        self.text = wx.TextCtrl(panel, -1)

# Run the program
if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = MyForm()
    frame2 = From2()
    frame.Show()
    frame2.Show()
    app.MainLoop()

</code>

If I do not use Yield(), frame2 is not updated and also it is blocked until the process in frame has finished.

If do not use Enable/Disable the cursor is OK.

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

raffaello escribió:

BTW, if the widget is a wx.TextCtrl and instead of «disabling» it you block it with SetEditable(False), there is no redrawing and therefore no flickering.

Hello Raffaello,

I would like to make a two generic method that works on any frame:

def Working(win)
     Disable win
     change cursor

def EndWork(win)
     Enable win
     restore cursor

But the cursor state fail as a put in the other message.

Thanks.

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

Oswaldo,

<code>

import wx

frame = None
frame2 = None

class MyForm(wx.Frame):

   def __init__(self):
       wx.Frame.__init__(self, None, wx.ID_ANY, "wx.Menu Tutorial")

       # Add a panel so it looks the correct on all platforms
       panel = wx.Panel(self, wx.ID_ANY)
       btn = wx.Button(panel, wx.ID_ANY, 'Push me!')
       self.Bind(wx.EVT_BUTTON, self.onButton, btn)

   def onButton(self, event):
       oldcursor = self.GetCursor()
       print 'Setting CURSOR_WAIT...'
       self.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
       self.Freeze()
       self.Disable()
       for x in range(1000):
           wx.GetApp().Yield()
           wx.MilliSleep(25)
           frame2.text.SetValue(str(x))
       self.Enable()
       self.Thaw()
       print 'Thawed and resetting cursor!'
       self.SetCursor(oldcursor)

class From2(wx.Frame):
    def __init__(self):
       wx.Frame.__init__(self, None, wx.ID_ANY, "Form2")
       panel = wx.Panel(self, wx.ID_ANY)
       self.text = wx.TextCtrl(panel, -1)

# Run the program
if __name__ == "__main__":
   app = wx.PySimpleApp()
   frame = MyForm()
   frame2 = From2()
   frame.Show()
   frame2.Show()
   app.MainLoop()

</code>

If I do not use Yield(), frame2 is not updated and also it is blocked until the process in frame has finished.

If do not use Enable/Disable the cursor is OK.

If you use wx.Sleep(1) or wx.Sleep(2) and you move your mouse quickly enough, you'll see that the cursor on the second frame is set correctly, but then the Yield takes effect and seems to reverse that. I tried pubsub too, but Yield() continues to cause that issue. You'll probably just want to look at threads instead. See the following wiki article:

http://wiki.wxpython.org/LongRunningTasks

Mike

Mike Driscoll escribió:

If you use wx.Sleep(1) or wx.Sleep(2) and you move your mouse quickly enough, you'll see that the cursor on the second frame is set correctly, but then the Yield takes effect and seems to reverse that. I tried pubsub too, but Yield() continues to cause that issue. You'll probably just want to look at threads instead. See the following wiki article:

LongRunningTasks - wxPyWiki

I don't want to launch a thread when the user press a load button to populate a listctrl, etc ....

Making more tests i observed that: Freeze() disable the input !!!

If you try this code, the objects in MyForm are locked while the frame is freezed whitout using Disable() and the cursor is also OK.

This is what i'm looking for.
Thanks.

<code>

import wx

class WorkFrame(wx.Frame):
     def Working(self):
         self._OldCursor = self.GetCursor()
         self.SetCursor(wx.StockCursor(wx.CURSOR_WAIT))
         self.Freeze()

     def EndWork(self):
         if hasattr(self, "_OldCursor"):
             self.SetCursor(self._OldCursor)
         if self.IsFrozen():
             self.Thaw()

class MyForm(WorkFrame):

     def __init__(self):
         wx.Frame.__init__(self, None, wx.ID_ANY, "Disable Test")
         panel = wx.Panel(self, wx.ID_ANY)
         btn = wx.Button(panel, wx.ID_ANY, "Start")
         btn.Bind(wx.EVT_BUTTON, self.onButton)
         btn2 = wx.Button(panel, wx.ID_ANY, "Try me while working!", pos=wx.Point(0,30))
         btn2.Bind(wx.EVT_BUTTON, self.onButton2)
         txt = wx.TextCtrl(panel, -1, pos=wx.Point(0,60), value="Write here while working")

         self.OutFrame = OutForm(self)
         self.OutFrame.Show()

     def onButton(self, event):
         self.Working()
         print "Work in progress .."

         for x in range(500):
            self.OutFrame.text.SetValue(str(x))
            wx.GetApp().Yield()
            wx.MilliSleep(25)

         self.EndWork()
         print "Finished"

     def onButton2(self, evt):
         print "Button2"

class OutForm(wx.Frame):
     def __init__(self, parent):
         wx.Frame.__init__(self, parent, wx.ID_ANY, "OutFrame")
         panel = wx.Panel(self, wx.ID_ANY)
         self.text = wx.TextCtrl(panel, -1)

if __name__ == "__main__":
     app = wx.PySimpleApp()
     frame = MyForm().Show()
     app.MainLoop()

</code>

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

Oswaldo,

Oswaldo Hernández wrote:

Mike Driscoll escribió:

If you use wx.Sleep(1) or wx.Sleep(2) and you move your mouse quickly enough, you'll see that the cursor on the second frame is set correctly, but then the Yield takes effect and seems to reverse that. I tried pubsub too, but Yield() continues to cause that issue. You'll probably just want to look at threads instead. See the following wiki article:

LongRunningTasks - wxPyWiki

I don't want to launch a thread when the user press a load button to populate a listctrl, etc ....

Making more tests i observed that: Freeze() disable the input !!!

If you try this code, the objects in MyForm are locked while the frame is freezed whitout using Disable() and the cursor is also OK.

This is what i'm looking for.
Thanks.

You could also use:

wx.BeginBusyCursor()

do whatever

wx.EndBusyCursor()

Werner

Werner F. Bruhin escribió:

Oswaldo,

Oswaldo Hernández wrote:

Mike Driscoll escribió:

If you use wx.Sleep(1) or wx.Sleep(2) and you move your mouse quickly enough, you'll see that the cursor on the second frame is set correctly, but then the Yield takes effect and seems to reverse that. I tried pubsub too, but Yield() continues to cause that issue. You'll probably just want to look at threads instead. See the following wiki article:

LongRunningTasks - wxPyWiki

I don't want to launch a thread when the user press a load button to populate a listctrl, etc ....

Making more tests i observed that: Freeze() disable the input !!!

If you try this code, the objects in MyForm are locked while the frame is freezed whitout using Disable() and the cursor is also OK.

This is what i'm looking for.
Thanks.

You could also use:

wx.BeginBusyCursor()

do whatever

wx.EndBusyCursor()

BeginBusyCursor() show the Hourglass cursor in all windows in the application.
I only need it in the working frame.

Thanks.

···

--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.

Oswaldo Hernández wrote:

Werner F. Bruhin escribió:

Oswaldo,

Oswaldo Hernández wrote:

Mike Driscoll escribió:

If you use wx.Sleep(1) or wx.Sleep(2) and you move your mouse quickly enough, you'll see that the cursor on the second frame is set correctly, but then the Yield takes effect and seems to reverse that. I tried pubsub too, but Yield() continues to cause that issue. You'll probably just want to look at threads instead. See the following wiki article:

LongRunningTasks - wxPyWiki

I don't want to launch a thread when the user press a load button to populate a listctrl, etc ....

Making more tests i observed that: Freeze() disable the input !!!

If you try this code, the objects in MyForm are locked while the frame is freezed whitout using Disable() and the cursor is also OK.

This is what i'm looking for.
Thanks.

You could also use:

wx.BeginBusyCursor()

do whatever

wx.EndBusyCursor()

BeginBusyCursor() show the Hourglass cursor in all windows in the application.
I only need it in the working frame.

Well, if you are blocking the return to the MainLoop by some long running task then the other frames in the application will not be receiving events either, so it would be best to let the user know that those frames can't be used either.

···

--
Robin Dunn
Software Craftsman
http://wxPython.org Java give you jitters? Relax with wxPython!