Hi folks,
I’m running into a strange problem. I have a large program that uses wxpython for the GUI, and I use several threads to keep the GUI snappy. On occasion, I want to inform users about something (a result, error, etc) from one of those threads, so I show the user a dialog. To do so, I use the standard CallAfter formulation from a thread.
For a while I’ve also been using wx.CallAfter to Destroy these dialogs. This works fine on MacOS, Windows, and Debian. However, I’ve just had a user on Ubuntu report that the dialogs don’t work there.
I’ve been able to verify the issue. The code below is a minimal runnable example that creates a dialog from a thread. If you run this on most platforms it runs fine, and you see the dialog. If instead you run it on Ubuntu (I’ve tested 20.04 and 14.04) it gives the error:
(wx_example.py:4879): GLib-GObject-WARNING **: 13:54:01.989: invalid (NULL) pointer instance
(wx_example.py:4879): GLib-GObject-CRITICAL **: 13:54:01.989: g_signal_handlers_disconnect_matched: assertion 'G_TYPE_CHECK_INSTANCE (instance)' failed
(wx_example.py:4879): Gtk-CRITICAL **: 13:54:01.989: gtk_widget_destroy: assertion 'GTK_IS_WIDGET (widget)' failed
(wx_example.py:4879): GLib-GObject-CRITICAL **: 13:54:01.989: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
Traceback (most recent call last):
File "/home/jesse/miniconda3/envs/wx/lib/python3.8/site-packages/wx/core.py", line 3407, in <lambda>
lambda event: event.callable(*event.args, **event.kw) )
wx._core.wxAssertionError: C++ assertion ""Assert failure"" failed at /home/conda/feedstock_root/build_artifacts/wxpython_1616628602755/work/ext/wxWidgets/src/gtk/msgdlg.cpp(281) in ShowModal(): unexpected GtkMessageDialog return code
If you remove the Destroy call, it works fine (besides the dialog not being destroyed).
Any thoughts on what’s going on here? Is there a better way to destroy the dialog after showing it? I should say that in my actual application, for reasons I can’t quite figure out, the dialog not only fails to show but trying to do so actually crashes the application with a Seg fault.
More info:
Python: 3.7.10/3.8.8
Wxpython: 4.1.1
OS: Ubuntu 20.04/14.04
Installed by: Python installed via miniconda installer, wxpython installed from conda-forge
Here’s the example code:
import threading
import wx
class TestFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(TestFrame, self).__init__(*args, **kwargs)
pnl = wx.Panel(self)
show = wx.Button(pnl, label='Show Dialog from Thread')
show.Bind(wx.EVT_BUTTON, self._on_show_dialog)
sizer = wx.BoxSizer()
sizer.Add(show)
pnl.SetSizer(sizer)
def _on_show_dialog(self, evt):
t = threading.Thread(target=self._show_dialog)
t.start()
t.join()
def _show_dialog(self):
dlg = wx.MessageDialog(self, 'This is a test.', 'Test',
style=wx.ICON_INFORMATION|wx.OK|wx.STAY_ON_TOP)
wx.CallAfter(dlg.ShowModal)
wx.CallAfter(dlg.Destroy)
if __name__ == '__main__':
app = wx.App()
frm = TestFrame(None, title='TestFrame')
frm.Show()
app.MainLoop()