0

wxpythonを使用してリアルタイムの結果を表示するWebクローラーを作成しています。ウィンドウに名前が付けられたボタンが 1 つだけあると仮定しcrawlます。ボタンをクリックすると、新しいダイアログが出てきて、新しいダイアログの TextCtrl にクロール中の現在の URL が表示されます。

コードは次のように簡略化できます (関数にWebCrawlerスレッドを使用したUI のみ)。OnDisplayClick

# -*- coding: utf-8 -*- 

import wx
class Main ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer3 = wx.BoxSizer( wx.VERTICAL )

        self.Crawl = wx.Button( self, wx.ID_ANY, u"Crawl", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.Crawl.SetDefault() 
        bSizer3.Add( self.Crawl, 0, wx.ALL, 5 )

        self.SetSizer( bSizer3 )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.Crawl.Bind( wx.EVT_BUTTON, self.OnDisplayClick )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def OnDisplayClick( self, event ):

            #Show the display window
        newDisplay = Display(self)
            newDisplay.show()

            ############################################################
            ##          start a multi-threading webcrawler            ##
            ############################################################

            web_crawler = WebCrawler(newDisplay.current_url)
            web_crawler.startCrawl()



class Display ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 500,300 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )

        self.SetSizeHintsSz( wx.DefaultSize, wx.DefaultSize )

        bSizer4 = wx.BoxSizer( wx.VERTICAL )

        self.cur_url = wx.StaticText( self, wx.ID_ANY, u"Current_URL: ", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.cur_url.Wrap( -1 )
        bSizer4.Add( self.cur_url, 0, wx.ALL, 5 )

        self.current_url = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        bSizer4.Add( self.current_url, 0, wx.ALL, 5 )

        self.SetSizer( bSizer4 )
        self.Layout()

        self.Centre( wx.BOTH )

    def __del__( self ):
        pass

UI:

クロール 画面

WebCrawler はマルチスレッド クローラーです。TextCtrl( current_url) を WebCrawler に渡して、現在のクロール URL を表示ウィンドウに表示させますが、クロール ボタンをクリックすると、インターフェイスが死んでいるように見えます。マルチスレッド WebCrawler が実行されており、UI スレッドが新しいウィンドウを表示する機会を得ることができません。threading.Thread を使用して別の 2 つのスレッドを書き込もうとしました。1 つは新しいウィンドウを表示するために使用され、もう 1 つは WebCrawler に使用されますが、失敗しました。アプリはすぐに終了しましたが、ウィンドウを表示して数秒間クロール スレッドを実行できます。 、そして時々それは私に次のようなことを言いました:

(python2.7:5231): Pango-CRITICAL **: pango_layout_get_iter: assertion `PANGO_IS_LAYOUT (layout)' failed

(python2.7:5404): GLib-GObject-CRITICAL **: g_object_ref: assertion `object->ref_count > 0' failed

2 つのスレッドは次のとおりです。

class UpdateThread(threading.Thread):

    """ WebCrawler thread """

    def __init__(self, webCrawl):
        threading.Thread.__init__(self)
        self.webCrawl = webCrawl

    def run(self):
        self.webCrawl.start()

class CrawlShowThread(threading.Thread):

    """ Display thread """
    def __init__(self, crawl_display):
        threading.Thread.__init__(self)
        self.crawl_display = crawl_display

    def run(self):
        self.crawl_display.Show()

次に、両方とも OnCrawlClick() 関数で start() を実行します。しかし、私が上で言ったことと同じように、この方法は機能しません。

そのようなことを行う正しい方法は何ですか?どんな助けでも大歓迎です!

4

2 に答える 2

1

非メイン スレッドから GUI にアクセスすることはできません。この のドキュメンテーション wiki を参照してください。

于 2012-05-29T08:03:01.100 に答える
0

問題は、長いタスクを実行していて、GUI のメイン イベント ループをブロックしているため、基本的にフリーズしていることです。クローラーを別のスレッドに配置し、wxPython のスレッドセーフ メソッドを使用して GUI を更新する必要があります。wikiまたはこのチュートリアルを参照してください

于 2012-05-29T13:48:35.517 に答える