Frage

Ich habe ein Programm (Zeitrafferhersteller) mit zwei Threads, die a aktualisiert werden wx.StaticBitmap. Wenn die beiden Threads auf die zugreifen wx.StaticBitmap Es stürzt mit dem Fehler ab

Python: xcb_io.c: 221: poll_for_event: asssertion `(((lang) (Event_sequence) - (lang) (dpy-> request) <= 0) 'fehlgeschlagen.

Ich habe es ausprobiert Google-Suche Für die Antwort und ich habe versucht, es selbst zu lösen, aber ich kann es immer noch nicht herausfinden.

Einfacher Code, der diesen Fehler reproduziert (Dies ist nicht das eigentliche Programm):

#!/usr/bin/env python

import wx
import time,os.path,glob,threading

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):

        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.bitmap_1 = wx.StaticBitmap(self, -1, wx.NullBitmap)

        self.__set_properties()
        self.__do_layout()

        wx.CallAfter(self._img)
    def __set_properties(self):

        self.SetTitle("frame_1")


    def __do_layout(self):

        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.bitmap_1, 0, 0, 0)
        self.SetSizer(sizer_1)
        sizer_1.Fit(self)
        self.Layout()



    def _img(self):
             Thread1= threading.Thread(target=self._img1)
             Thread1.start()
             Thread2 = threading.Thread(target=self._img2)
             Thread2.start()

    def _img1(self):
            frames = glob.glob("/path/to/pngs/*.png")
        frames.sort()
        for i in range(len(frames)):
            if os.path.isfile(frames[i]) and i%2 == 0:
                print frames[i]
                wx.Yield()
                ##time.sleep(0.5)
                wx.CallAfter(self.bitmap_1.SetBitmap,wx.Bitmap(frames[i], wx.BITMAP_TYPE_ANY))
                wx.CallAfter(self.Update)
    def _img2(self):
            frames = glob.glob("/path/to/pngs/*.png")
        frames.sort()
        for i in range(len(frames)):
            if os.path.isfile(frames[i]) and i%2 == 1:
                print frames[i]
                wx.Yield()
                ##time.sleep(0.5)
                wx.CallAfter(self.bitmap_1.SetBitmap,wx.Bitmap(frames[i], wx.BITMAP_TYPE_ANY))
                wx.CallAfter(self.Update)

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

Ich habe es mit gelöst wx.PostEvent Siehe meine Antwort.

War es hilfreich?

Lösung 2

Ich habe es mit gelöst wx.PostEvent:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# generated by wxGlade 0.6.3 on Mon Oct 17 19:59:55 2011

import wx
import time,os.path,glob,threading
# begin wxGlade: extracode
# end wxGlade


ID_START = wx.NewId()
ID_STOP = wx.NewId()

# Define notification event for thread completion
EVT_RESULT_ID = wx.NewId()

def EVT_RESULT(win, func):
    """Define Result Event."""
    win.Connect(-1, -1, EVT_RESULT_ID, func)

class ResultEvent(wx.PyEvent):
    """Simple event to carry arbitrary result data."""
    def __init__(self, data):
        """Init Result Event."""
        wx.PyEvent.__init__(self)
        self.SetEventType(EVT_RESULT_ID)
        self.data = data
class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        # begin wxGlade: MyFrame.__init__
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        self.bitmap_1 = wx.StaticBitmap(self, -1, wx.NullBitmap)
        self.__set_properties()
        self.__do_layout()
        # end wxGlade
    self.frames = ""
    EVT_RESULT(self,self.OnResult)
        wx.CallAfter(self._img)
    def __set_properties(self):
        # begin wxGlade: MyFrame.__set_properties
        self.SetTitle("frame_1")
        # end wxGlade

    def __do_layout(self):
        # begin wxGlade: MyFrame.__do_layout
        sizer_1 = wx.BoxSizer(wx.VERTICAL)
        sizer_1.Add(self.bitmap_1, 0, 0, 0)
        self.SetSizer(sizer_1)
        sizer_1.Fit(self)
        self.Layout()
        # end wxGlade
    def OnResult(self, event):
        """Show Result status."""
        if event.data is None:
            pass
        else:
        self.bitmap_1.SetBitmap(wx.Bitmap(event.data, wx.BITMAP_TYPE_ANY))
# end of class MyFrame
    def _img(self):
             Thread1= threading.Thread(target=self._img1)
             Thread1.start()
             Thread2 = threading.Thread(target=self._img2)
             Thread2.start()

    def _img1(self):
            frames = glob.glob("/home/mitch/Pictures/*.png")
        frames.sort()

        for i in range(len(frames)):
            if os.path.isfile(frames[i]) and i%2 == 0:
                print frames[i]
                ##wx.Yield()
                ##time.sleep(0.5)
                wx.PostEvent(self, ResultEvent(frames[i]))

    def _img2(self):
            frames = glob.glob("/home/mitch/Pictures/*.png")
        frames.sort()

        for i in range(len(frames)):
            if os.path.isfile(frames[i]) and i%2 == 1:
                print frames[i]
                ##wx.Yield()
                ##time.sleep(0.5)
                wx.PostEvent(self, ResultEvent(frames[i]))

if __name__ == "__main__":
    app = wx.PySimpleApp(0)
    wx.InitAllImageHandlers()
    frame_1 = MyFrame(None, -1, "")
    app.SetTopWindow(frame_1)
    frame_1.Show()
    app.MainLoop()

Andere Tipps

Der einfachste Weg, um Abstürze und anomales Verhalten aller Art zu vermeiden, besteht darin, sicherzustellen, dass nur der Hauptfaden die GUI behandelt. Sie könnten versuchen, es zu tun, indem Sie kritische Codeblöcke finden und sperren, aber meiner Meinung nach ist das ein verlorenes Spiel. Viel einfacher, den Verarbeitungs -Thread (n) mit dem Haupt -Thread mit Ereignissen zu synchronisieren:

while run:
    self.timer_evt.wait()        # wait for main thread to unblock me
    self.timer_evt.clear()
    <process stuff, put results in queue or shared variables>

im Verarbeitungs -Thread und

def tick(self):
    if run:
        <update GUI from queued data or shared variables>
        self.timer_evt.set()            # unblock processing thread
        self.root.after(ms, self.tick)  # reschedule the GUI update

im Hauptfaden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top