To zdarza się tylko na Linuksie (również w systemie OS X, nie można przetestować atm), działa poprawnie w systemie Windows.wx.ProgressDialog powodujący błąd seg i/lub błąd GTK_IS_WINDOW podczas niszczenia
Mam wx.ProgressDialog, który jest spawn z głównym wątku. Wysyłam pracę do innego wątku i okresowo oddzwoni do funkcji wywołania zwrotnego w głównym wątku, która zaktualizuje ProgressDialog lub, pod koniec pracy, zniszczy go. Jednak mam ciekawą wiadomość na Linuksie, kiedy to nastąpi:
(python:12728): Gtk-CRITICAL **: IA__gtk_window_set_modal: assertion 'GTK_IS_WINDOW (window)' failed
Okno ma blisko, ale gdy próbuję go tarło ponownie wygląda na to, że już prawie zakończone. Czasami komunikat o błędzie seg również występuje po tym komunikacie.
Próbowałem zasymulować z uproszczoną wersję tutaj.
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()
(możemy wybrać 2.8, ale idealnie dowolny fix powinien działać zarówno w 2,8 i 3,0 I rzeczywiście nie była w stanie przetestuj go w wersji 3.0 w Linuksie z powodu złej wersji 3.0)
To dobrze ilustruje problem: działa dobrze w systemie Windows, ale wykreśla błąd, gdy próbuje zniszczyć okno dialogowe postępu. Jednak nie mogę uzyskać przykładu pokazującego, że próbowałem szukać rozwiązań. Czytałem, że może to wynikać z faktu, że wątek roboczy kończy się zbyt szybko, a zatem pozostawia GUI z wiadomościami w jego kolejce. Nie jestem pewien, czy całkowicie to rozumiem (nigdy nie zrozumiałem kwestii wydajności i komunikatów itp.), Ale wierzę, że oznacza to, że gdy pracownik ma 100%, ProgressDialog (wolniejszy) może być tylko na poziomie 75% i nadal ma dodatkowe 25% wiadomości, których można użyć do "aktualizacji" GUI, ale zamiast tego zostanie zniszczony.
Chciałbym wyjaśnienia, jeśli dobrze rozumiem, czy nie.
Poza tym uważam, że .Hide()
działa jak dzieło, ale chciałbym je zniszczyć, ponieważ jest to właściwe.
Bez względu na to, jakakolwiek pomoc byłaby bardzo doceniana. =)