這只是發生在Linux(可能OS X也不能ATM測試),工作正常的Windows。wx.ProgressDialog造成賽格故障和/或GTK_IS_WINDOW故障時被銷燬
我有一個催生與主線程wx.ProgressDialog。我將工作發送給另一個線程,並定期回調主線程中的回調函數,以更新ProgressDialog,或者在工作結束時將其銷燬。不過,我在Linux上得到一個有趣的消息時發生這種情況:
(python:12728): Gtk-CRITICAL **: IA__gtk_window_set_modal: assertion 'GTK_IS_WINDOW (window)' failed
對話確實接近,但如果我嘗試產卵再次,它看起來像它已經差不多完成了。有時候seg故障也會跟着這個消息。
我試圖用一個精簡版在這裏進行模擬:
import wxversion
wxversion.select("2.8")
import wx
import sys
import threading
MAX_COUNT = 100
## This class is in a different area of the codebase and
class WorkerThread(threading.Thread):
def __init__(self, callback):
threading.Thread.__init__(self)
self.callback = callback
def run(self):
# simulate work done. IRL, this calls another function in another
# area of the codebase. This function would generate an XML document,
# which loops through a list of items and creates a set of elements for
# each item, calling back after each item. Here, we simply set up a for
# loop and simulate work with wx.MilliSleep
for i in xrange(MAX_COUNT):
print i
wx.MilliSleep(30)
wx.CallAfter(self.callback, i)
# Send done signal to GUI
wx.CallAfter(self.callback, -1)
class Frame(wx.Frame):
def __init__(self, title):
wx.Frame.__init__(self, None, title=title, pos=(150,150), size=(350,200))
panel = wx.Panel(self)
box = wx.BoxSizer(wx.VERTICAL)
m_btn = wx.Button(panel, wx.ID_ANY, "Run Stuff")
m_btn.Bind(wx.EVT_BUTTON, self.OnRunButton)
box.Add(m_btn, 0, wx.ALL, 10)
panel.SetSizer(box)
panel.Layout()
def OnRunButton(self, event):
self.progressDialog = wx.ProgressDialog("Doing work",
"Doing Work",
maximum=MAX_COUNT, parent=self,
style=wx.PD_APP_MODAL | wx.PD_ELAPSED_TIME)
self.worker(self.threadCallback)
self.progressDialog.ShowModal()
def worker(self, callback):
# This bit is in another part of the codebase originally. In the test,
# I could have added it to OnRunButton, but I wanted function calls to
# be similar between test and actual code
thread = WorkerThread(callback)
thread.start()
def threadCallback(self, info):
# We update based on position, or destroy if we get a -1
if info == -1:
self.progressDialog.Destroy()
else:
self.progressDialog.Update(info)
app = wx.App(redirect=False)
top = Frame("ProgressDialog Test")
top.Show()
app.MainLoop()
(我們選擇2.8,但理想的任何修補程序應該在這兩個2.8和3.0工作,我其實一直沒能在Linux 3.0的測試由於壞的3.0版本)
這做得很好,在表示問題:在Windows中工作正常,但是當它試圖摧毀進度對話框賽格故障。但是,我不能得到的例子來說明GTK_IS_WINDOW
我用盡尋找解決方案。我讀過這可能是由於工作線程完成得太快的事實,從而使GUI在隊列中留下了一些消息。我不確定我是否完全理解了這一點(從來沒有得到良率和消息的等待),但是我認爲這意味着當員工達到100%時,ProgressDialog(速度較慢)可能只會在75%,仍然有額外的25%的消息用於「更新」GUI,但相反會被破壞。
我想澄清一下,如果我是否正確理解。
而且,我相信.Hide()
作品作爲變通,但我想摧毀它,而不是因爲這是做正確的事。
無論如何,任何幫助將不勝感激。 =)