Окно PyGTK не скрывается, когда сказано - PullRequest
1 голос
/ 08 июля 2010

В моем приложении PyGTK я прошу пользователя найти файл, чтобы с ним можно было выполнять операции. Приложение запрашивает файл у пользователя и передает это имя файла необходимым методам. К сожалению, при вызове метода gtk.dispose() в этом диалоговом окне он просто висит там до тех пор, пока не будет вызван метод, вызываемый для выполнения файлового ввода-вывода. Я даже пытался поместить манипуляции с файлами внутри другого потока, но это не имело никакого эффекта.

Моя цель состоит в том, чтобы программа показала пользователю диалоговое окно, информирующее его о том, что файл, который они выбрали для манипулирования, имеет место. В текущей реализации диалоговое окно появляется после того, как уничтожен gtk.FileChooserDialog.

Ниже мой код:

def performFileManipulation(self, widget, data=None):
        # Create the file chooser dialog:
        dialog = gtk.FileChooserDialog("Open..", None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)

        # Display the file selector and obtain the response back
        response = dialog.run()

        # If the user selected a file, then get the filename:
        if response == gtk.RESPONSE_OK:
            dataLocation = dialog.get_filename()

        # If the file was not chosen, then just close the window:
        else:
            print "Closed, no files selected"   # Just for now

        ########## Problem Area ########## 
        # The dialog is told to get destroyed, however, it hangs here in an
        # unresponsive state until the the file-manipulations performed in a new thread
        # below are completed.  Then, the status dialog (declared below) is displayed.
        dialog.destroy()    # Close the dialog.

        ## Show a dialog informing the user that the file manipulation is taking place:
        statusDialog = gtk.Dialog("Performing File Operations...", parent=None, flags=0, buttons=None)
        statusLabel = gtk.Label("Performing File Operations.\nPlease wait...")
        statusLabel.set_justify(gtk.JUSTIFY_CENTER)
        statusLabel.show()
        statusDialog.vbox.pack_start(statusLabel, True, True, 0)
        statusDialog.set_default_size(350, 150)
        statusDialog.show()

        # Create the thread to perform the file conversion:
        errorBucket = Queue.Queue()             # Make a bucket to catch all errors that may occur:
        theFileOperationThread = doStuffToTheFile(dataLocation, errorBucket)     # Declare the thread object.

        ## Perform the file operations:
        theFileOperationThread.start()            # Begin the thread

        # Check on the thread.  See if it's still running:
        while True:
            theFileOperationThread.join(0.1)
            if theFileOperationThread.isAlive():
                continue
            else:
                break

        # Check if there was an error in the bucket:
        try:
            errorFound = errorBucket.get(False)

        # If no errors were found, then the copy was successful!
        except Queue.Empty:
            pass

        # There was an error in the bucket!  Alert the user
        else:
            print errorFound

        statusDialog.destroy()

Обратите внимание, что этот код еще не завершен, например, он еще неправильно обрабатывает пользователя, не выбрав файл и не отменив операцию.

РЕДАКТИРОВАТЬ: После дальнейшего изучения, кажется, есть проблема с потоками с PyGTK. Проблема возникает в цикле while True. Я заменил этот код на time.sleep(15), и аналогично, диалог выбора файла будет приостановлен. Это довольно странное поведение, и все должно работать внутри другого потока. Я предполагаю, что теперь вопрос состоит в том, чтобы выяснить, как разместить диалог выбора файла внутри его собственного потока.

Ответы [ 2 ]

2 голосов
/ 09 июля 2010

Вероятно, нет необходимости выполнять файловые операции в отдельном потоке, так как вы в действительности ничего не делаете в этом потоке, пока выполняются файловые операции - просто ожидание занято. И это подводит меня к тому, почему код не работает: обновления GUI обрабатываются в основном цикле GTK. Но все время, пока вы ожидаете завершения потока файлов, основной цикл GTK не выполняется, потому что он застрял в ожидании завершения вашей функции performFileManipulation.

Вам нужно выполнить итерации основного цикла GTK во время цикла while True. Это выглядит так:

while True:
    theFileOperationThread.join(0.1)
    if theFileOperationThread.isAlive():
        while gtk.events_pending():
            gtk.main_iteration(block=False)
    else:
        break

Но опять же, я хотел бы рассмотреть возможность выполнения файловых операций в этом потоке, кажется излишним запускать другой поток и ничего не делать во время его работы.

1 голос
/ 08 июля 2010

Смешивание потоков и приложений GTK (насколько я помню) имеет тенденцию приводить к странным результатам.

Проблема в том, что даже если вы вызываете gtk.dispose, вы, вероятно, вызываете методы напрямую, что блокирует следующую итерацию gtk.mainloop.

Вам нужно создать другую функцию для обработки файла и вызвать ее из функции обратного вызова:

def doFileStuff(filename):
   with open(filename, 'r') as f:
       for line in f:
            #do something
   return False # On success

А затем измените эту функцию:

def performFileManipulation(self, widget, data=None):
        # Create the file chooser dialog:
        dialog = gtk.FileChooserDialog("Open..", 
                                       None, 
                                       gtk.FILE_CHOOSER_ACTION_OPEN, 
                                       (gtk.STOCK_CANCEL, 
                                        gtk.RESPONSE_CANCEL, 
                                        gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        dialog.set_default_response(gtk.RESPONSE_OK)

        # Display the file selector and obtain the response back
        response = dialog.run()

        # If the user selected a file, then get the filename:
        if response == gtk.RESPONSE_OK:
            dataLocation = dialog.get_filename()

        # If the file was not chosen, then just close the window:
        else:
            print "Closed, no files selected"   # Just for now

        # You'll need to import gobject
        gobject.timeout_add(100, doFileStuff, dataLocation)

Это должно, по крайней мере, позволить вам закрыть диалог, и я думаю, что он запустит обработку файлов в фоновом режиме. Если нет, то он, по крайней мере, даст вам возможность начать новую тему.

НТН

...