473,783 Members | 2,287 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Showing a message dialog from a thread using GTK

6 New Member
I have a worker thread, and when the worker is done I want it to show a popup dialog. The sample application below demonstrates this. There are two buttons: a "Show dialog" button which immediately displays a dialog, and a "Do work" button which launches a worker thread. The worker thread simulates some work by sleeping a moment, and then attempts to display a dialog.

The problem is that when the worker thread attempts to display the popup the program freezes. What is the difference between showing a dialog from the event handler thread in the "connected" button2_click method, and showing a dialog in the run method of a custom thread?

Expand|Select|Wrap|Line Numbers
  1. import gobject
  2. import gtk
  3. import threading
  4. import time
  5.  
  6. class MessageBox(gtk.MessageDialog):
  7.     def __init__(self, parent, message):
  8.         gtk.MessageDialog.__init__(self, parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
  9.                                 gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message)
  10.         self.set_default_response(gtk.RESPONSE_OK)
  11.         self.connect('response', self._handle_clicked)
  12.  
  13.     def _handle_clicked(self, *args):
  14.         self.destroy()
  15.  
  16. class TestThread(threading.Thread):
  17.     def __init__(self, mainview):
  18.         threading.Thread.__init__(self)
  19.         self.mainview = mainview
  20.  
  21.     def run(self):
  22.         print "Some work is done here..."
  23.         time.sleep(3)
  24.         dialog = MessageBox(self.mainview, "Work completed")
  25.         dialog.show_all()
  26.         print "Work complete"
  27.  
  28. class MainView(gtk.Window):
  29.     def __init__(self):
  30.         gtk.Window.__init__(self)
  31.         self.connect('delete_event', self.handle_window_delete_event)
  32.         self.connect('destroy', self.quit)
  33.  
  34.         button1 = gtk.Button("Do work")
  35.         button1.connect('clicked', self.button1_click)
  36.         button2 = gtk.Button("Show dialog")
  37.         button2.connect('clicked', self.button2_click)
  38.         box = gtk.VBox()
  39.         box.pack_start(button1)
  40.         box.pack_start(button2)
  41.         self.add(box)
  42.  
  43.     def quit(self, *args):
  44.         gtk.main_quit()
  45.  
  46.     def handle_window_delete_event(self, *args):
  47.         return False
  48.  
  49.     def button1_click(self, *args):
  50.         worker = TestThread(self)
  51.         worker.start()
  52.  
  53.     def button2_click(self, *args):
  54.         dialog = MessageBox(self, "Just a message!")
  55.         dialog.show_all()
  56.  
  57. if __name__ == "__main__":
  58.     gobject.threads_init()
  59.     main = MainView()
  60.     main.show_all()
  61.     gtk.main()
  62.  
Oct 3 '07 #1
6 13510
ilikepython
844 Recognized Expert Contributor
I have a worker thread, and when the worker is done I want it to show a popup dialog. The sample application below demonstrates this. There are two buttons: a "Show dialog" button which immediately displays a dialog, and a "Do work" button which launches a worker thread. The worker thread simulates some work by sleeping a moment, and then attempts to display a dialog.

The problem is that when the worker thread attempts to display the popup the program freezes. What is the difference between showing a dialog from the event handler thread in the "connected" button2_click method, and showing a dialog in the run method of a custom thread?

Expand|Select|Wrap|Line Numbers
  1. import gobject
  2. import gtk
  3. import threading
  4. import time
  5.  
  6. class MessageBox(gtk.MessageDialog):
  7.     def __init__(self, parent, message):
  8.         gtk.MessageDialog.__init__(self, parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
  9.                                 gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message)
  10.         self.set_default_response(gtk.RESPONSE_OK)
  11.         self.connect('response', self._handle_clicked)
  12.  
  13.     def _handle_clicked(self, *args):
  14.         self.destroy()
  15.  
  16. class TestThread(threading.Thread):
  17.     def __init__(self, mainview):
  18.         threading.Thread.__init__(self)
  19.         self.mainview = mainview
  20.  
  21.     def run(self):
  22.         print "Some work is done here..."
  23.         time.sleep(3)
  24.         dialog = MessageBox(self.mainview, "Work completed")
  25.         dialog.show_all()
  26.         print "Work complete"
  27.  
  28. class MainView(gtk.Window):
  29.     def __init__(self):
  30.         gtk.Window.__init__(self)
  31.         self.connect('delete_event', self.handle_window_delete_event)
  32.         self.connect('destroy', self.quit)
  33.  
  34.         button1 = gtk.Button("Do work")
  35.         button1.connect('clicked', self.button1_click)
  36.         button2 = gtk.Button("Show dialog")
  37.         button2.connect('clicked', self.button2_click)
  38.         box = gtk.VBox()
  39.         box.pack_start(button1)
  40.         box.pack_start(button2)
  41.         self.add(box)
  42.  
  43.     def quit(self, *args):
  44.         gtk.main_quit()
  45.  
  46.     def handle_window_delete_event(self, *args):
  47.         return False
  48.  
  49.     def button1_click(self, *args):
  50.         worker = TestThread(self)
  51.         worker.start()
  52.  
  53.     def button2_click(self, *args):
  54.         dialog = MessageBox(self, "Just a message!")
  55.         dialog.show_all()
  56.  
  57. if __name__ == "__main__":
  58.     gobject.threads_init()
  59.     main = MainView()
  60.     main.show_all()
  61.     gtk.main()
  62.  
I'm not sure if this is the problem, but usually, child threads shouldn't do anything with the GUI in the maiin thread. Threads usually use the queue module to communicate between threads. What you need is a callback to listen from events from the queue in the main thread and the child thread to put some data on the queue.
Oct 3 '07 #2
bartonc
6,596 Recognized Expert Expert
In some frameworks, threads are allowed to post events to the event queue.
Using this technique, your main thread (which is usually the only thread allow to use GUI elements) can pop up the dialog. I'm not sure if this is also true of GTK, though.
Oct 3 '07 #3
kdikert
6 New Member
Thanks for the hints.I was expecting something like this, and it seems somewhat reasonable that the toolkit allows certain operatinons only from the main thread. I tested the callback approach, but i couldn't get it to work either. Here is some sample code for activating callbacks:

Expand|Select|Wrap|Line Numbers
  1. ...
  2. class TestThread(threading.Thread):
  3.     def __init__(self, mainview):
  4.         threading.Thread.__init__(self)
  5.         self.mainview = mainview
  6.  
  7.     def run(self):
  8.         print "Some work is done here..."
  9.         time.sleep(3)
  10.         print "worker " + str(threading.currentThread())
  11.         # Perform some action that will cause a 'notify' signal to be emitted
  12.         mainview.show_dialog = True
  13.         self.mainview.set_title("x")
  14.  
  15. ...
  16.  
  17. class MainView(gtk.Window):
  18.     def __init__(self):
  19.         gtk.Window.__init__(self)
  20.         self.connect('notify', self.do_notify)
  21.         self.show_dialog = False
  22. ...        
  23.     def do_notify(self, *args):
  24.         if self.show_dialog:
  25.             print "notify " + str(threading.currentThread())
  26.             dialog = MessageBox(self.mainview, "Work completed")
  27.             dialog.show_all()
  28. ...
  29.  
This did not work because the 'notify' signal is called in the same thread that performs the action that triggers the signal. The application will still freeze. Do you have any ideas for emitting a singnal in a way that will make it to be called in the main thread (running the gtk.main() loop)?
Oct 4 '07 #4
bartonc
6,596 Recognized Expert Expert
Thanks for the hints.I was expecting something like this, and it seems somewhat reasonable that the toolkit allows certain operatinons only from the main thread. I tested the callback approach, but i couldn't get it to work either. Here is some sample code for activating callbacks:

Expand|Select|Wrap|Line Numbers
  1. ...
  2. class TestThread(threading.Thread):
  3.     def __init__(self, mainview):
  4.         threading.Thread.__init__(self)
  5.         self.mainview = mainview
  6.  
  7.     def run(self):
  8.         print "Some work is done here..."
  9.         time.sleep(3)
  10.         print "worker " + str(threading.currentThread())
  11.         # Perform some action that will cause a 'notify' signal to be emitted
  12.         mainview.show_dialog = True
  13.         self.mainview.set_title("x")
  14.  
  15. ...
  16.  
  17. class MainView(gtk.Window):
  18.     def __init__(self):
  19.         gtk.Window.__init__(self)
  20.         self.connect('notify', self.do_notify)
  21.         self.show_dialog = False
  22. ...        
  23.     def do_notify(self, *args):
  24.         if self.show_dialog:
  25.             print "notify " + str(threading.currentThread())
  26.             dialog = MessageBox(self.mainview, "Work completed")
  27.             dialog.show_all()
  28. ...
  29.  
This did not work because the 'notify' signal is called in the same thread that performs the action that triggers the signal. The application will still freeze. Do you have any ideas for emitting a singnal in a way that will make it to be called in the main thread (running the gtk.main() loop)?
There is probably an event mechanism for this but in the mean time you could:
Use one of the "thread-safe" mechanisms provided by the threading module (like Event()) or a Queue.Queue() and poll the state of the thread from your main loop using a timer. That's what I do in wxPython, anyway. For that matter, you could just poll t.isAlive() where t is a reference to your thread.
Oct 4 '07 #5
kdikert
6 New Member
There is probably an event mechanism for this but in the mean time you could:
Use one of the "thread-safe" mechanisms provided by the threading module (like Event()) or a Queue.Queue() and poll the state of the thread from your main loop using a timer. That's what I do in wxPython, anyway. For that matter, you could just poll t.isAlive() where t is a reference to your thread.
As I see it, the Queue would not provide any help here, as it is intended for exchanging data between threads. The problem is rather that the thing I want to do can not be done in the worker thread, and so far I did not find the correct way of scheduling my own events to be executed in the main loop. It's the Widget.show_all () call that jams the system if it is not called in the GTK main loop.

However, now I found a solution to the problem. A recent post in the GTK mailing list relates to the same problem: http://mail.gnome.org/archives/gtk-a.../msg00034.html There is no specific example in the message, but here is mine:

Expand|Select|Wrap|Line Numbers
  1. class MessageBox(gtk.MessageDialog):
  2.     def __init__(self, parent, message):
  3.         gtk.MessageDialog.__init__(self, parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, message)
  4.         self.set_default_response(gtk.RESPONSE_OK)
  5.         self.connect('response', self._handle_clicked)
  6.  
  7.     def _handle_clicked(self, *args):
  8.         self.destroy()
  9.  
  10.     def show_dialog(self):
  11.         gobject.timeout_add(0, self._do_show_dialog)
  12.  
  13.     def _do_show_dialog(self):
  14.         self.show_all()
  15.         return False
  16.  
  17. ...
  18.  
  19. class TestThread(threading.Thread):
  20.     def __init__(self, mainview):
  21.         threading.Thread.__init__(self)
  22.         self.mainview = mainview
  23.  
  24.     def run(self):
  25.         time.sleep(3)
  26.         dialog = MessageBox(self.mainview, "Work completed")
  27.         dialog.show_dialog()
  28. ...
  29.  
The MessageBox.show _dialog() is now made thread safe from GTK point of view. The gobject.timeout _add() schedules a function to be called from the GTK main loop. The GTK main loop will call MessageBox._do_ show_dialog() which will make the dialog visible. The False return value must be included, as GTK would otherwise call the function repeatedly. Now I can call dialog.show_dia log() directly from the worker thread.
Oct 4 '07 #6
chipselect
1 New Member
With C, I use "g_idle_add ()", passing a function pointer and parameters, because I hear that GTK is thread aware, not thread safe.

GLib is thread safe (with "if (!g_thread_supp orted ()) g_thread_init (NULL);" in init) and solve this problem for me.
May 28 '09 #7

Sign in to post your reply or Sign up for a free account.

Similar topics

3
2855
by: Andrew Baker | last post by:
OK this has me perplexed, puzzled and bamboozled! I have a remoting service which I displayed a message box in. I then wondered what would happen if a client made a call to the service while the message box was being displayed. Since the call comes in on a different thread the client call was not blocked. This seemed to make sense to me. Next I thought, what will happen when the client calls into the server if I try to use a delegate...
8
3279
by: Raed Sawalha | last post by:
I have form with progress bar ,when application begin processing and progress bar moving if I minimized the form and try to restore it ,it is not showing until the processing completed ,how can I enabled minimize, maximize moving form while processing in underway?
5
1877
by: John | last post by:
Hi How can I show a dialog from within the main form? frmdialog.show? Thanks Regards
3
2246
by: mccoyn | last post by:
When I have a long process to run I can create a new thread to run it and create a modal dialog on my GUI thread. The modal dialog prevents any messages (like button clicks) from working on my main Form. It also provides a message loop, which allows paint messages and calls to the Control::Invoke function to run. I can use these to invalidate an area and update it with intermediate results of my process. When the process is done, I...
2
2070
by: Lars Netzel | last post by:
Hi I have a Form that on Form_Load() does some heavy database reading and I want to show that as a progressbar ontop of the main window.. I want to create a smaller Form with a progressbar.. and then in the main form, start a new thread that opens that small form and for each progress the heavy operation send a new value to the small form thru an event. I have managed to run a function or a sub in another thread but I can't
0
1158
by: Chukkalove | last post by:
I have a thread that sits polling a smart card status for the lifetime of an application using WinSCard API. It also performs asynchronous read and writes to the card as required and uses PostMessage for many of its callback functions. When i first wrote the application I used call backs with invoked methods but found there was a lot of coding involved and win api PostMessage turned out to be ample for most of the functionality that's...
1
1635
by: Claire | last post by:
Hi I need to set my main form as the owner of an error dialog box shown when there's an exception in a background thread. This is to make sure that the error form is closed down if the user pulls their security card while the error window is being shown. In visual studio 2003, my main form set a static "owner" variable within my frmWarning class definition and if the error form was needed (and null owner passed) then this static variable...
1
3121
by: Roland | last post by:
Hello, I am writing modal dialog box to display progress of downloading file. I am starting download of a file in constructor of dialog using some asynchronous method call which returns me an asynchronous object. I could use this object to get status. I will be using this status to update status message on dialog. Which method should I override to update the status message ? Can I follow the approach just like
2
3435
by: pandehrushikesh | last post by:
I am doing setup project in VS 2008. I used custom action to select file from local drives. On the button click of custom action form, I am launching Open file dialog as ofdGetNetPath.ShowDialog When I run the setup on Vista, and click the button to open the openFileDialog, it hanged, form becomes non responsive and I have to cancel the setup. on debugging I got following error "Current thread must be set to single thread apartment...
0
9643
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
1
10081
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9946
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8968
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7494
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5378
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3643
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2875
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.