Frank,

Understood. I'm going to try your example on CentOS 6.4 with PySide 1.2.1
and see what happens. Let me know what happens with future progress bars.
I'm going to start doing a lot of asynchronous stuff soon, so it would be
helpful to know.

Thanks,


--
Sean Fisk


On Wed, Dec 11, 2013 at 4:45 PM, Frank Rueter | OHUfx <[email protected]>wrote:

>  Hi Sean,
>
> I totally agree that it shouldn't work, and I paid little attention to it
> as I just wanted to provide an example for the signal.
>
> I am on Kubuntu 12.10 using PySide 1.2.1.
> I just ran the code on an OSX box with an old PySide installation (1.0.9)
> and the progressbar didn't move there.
>
> I have a few simple apps to write which will involve proper use of
> progressbar to indicate background image processing, so I'm sure I will run
> into it again.
>
>
> Cheers,
> frank
>
>
>
> On 12/12/13 09:56, Sean Fisk wrote:
>
> Janwillem,
>
>  I'm glad you were able to able to figure out the problem. Sorry for my
> red herrings!
>
>  Frank,
>
>  I thought about it, and I have no idea why the progress bar works fine
> for you and not for me. It hangs for me, which is exactly what I expected
> to happen. Maybe some platform difference? I'm on Mac OS 10.6 with PySide
> 1.2.1.
>
>
>  --
> Sean Fisk
>
>
> On Wed, Dec 11, 2013 at 9:16 AM, Janwillem van Dijk 
> <[email protected]>wrote:
>
>>  The solution Frank proposed yesterday works (after I found out that you
>> can get the output using selectedFiles()[0]).
>> No problems with the progressbar.
>> The actual processing can take a bit long because the exif's of digital
>> camera shots are analysed (GExiv2 for photos and exiftool for movies ) and
>> than copied to folders as
>> /camara_make/year/month/imagetype/yyyymmddhhmmss_fname. When copying more
>> than say 50 16MB raw photos the gui becomes blocked. In other apps I indeed
>> solved that with threading but, although not elegant, I decided to live
>> with that for this one.
>> Many thanks for teaching me this extra bit of Python.
>> Cheers, Janwillem
>>
>>
>> On 11/12/13 05:45, Sean Fisk wrote:
>>
>>  Frank,
>>
>> Your example is a good demonstration of QFileDialog‘s signals. However,
>> since the processing runs in the GUI thread, the progress bar is virtually
>> useless as the GUI has no time to update it. It starts empty, the
>> application hangs, and then it is filled when the processing is done.
>>
>> Janwillem,
>>
>> As I see it, if you would like a progress bar, you have three options:
>>
>>    1. Call 
>> QCoreApplication.processEvents()<http://seanfisk.github.io/pyside-docs/pyside/PySide/QtCore/QCoreApplication.html#PySide.QtCore.PySide.QtCore.QCoreApplication.processEvents>during
>>  your processing code. This is not always a great idea, and more of a
>>    hack than a solution. But it usually works.
>>    2. Split your processing into chunks as in this 
>> example<http://qt-project.org/wiki/Threads_Events_QObjects#72c9aabadf52900fbf3d4c1ff2b6008c>.
>>    However, the code is a bit convoluted and it still runs in the GUI thread.
>>    The whole page that contains that example is a great read for asynchronous
>>    programming.
>>    3. Send your processing to a thread, and dispatch events from the
>>    thread indicating the progress.
>>
>> The first two solutions involve running processing code within the GUI
>> thread. If any step of the processing takes longer than a second, then it’s
>> probably not a good idea as the user will see the application hang. Here is
>> an example implementation of the third solution:
>>
>> #!/usr/bin/env python
>> # Example: Asynchronously process a directory of files with a progress bar.
>> import sysimport osimport time
>> from PySide import QtCore, QtGui
>> class ProcessingThread(QtCore.QThread):
>>     # Fired when each file is processed.
>>     file_processed = QtCore.Signal(int, str)
>>
>>     def __init__(self, parent=None):
>>         super(ProcessingThread, self).__init__(parent)
>>         self.files = []
>>
>>     def run(self):
>>         # Code that's run in the thread.
>>         for i, filename in enumerate(self.files):
>>             # The actual code for one file goes here. Stubbed out with
>>             # time.sleep() for now.
>>             time.sleep(0.5)
>>             print 'Processed:', filename
>>             # Send update to the GUI thread.
>>             self.file_processed.emit(i + 1, filename)
>> class MyWidget(QtGui.QWidget):
>>     def __init__(self, parent=None):
>>         super(MyWidget, self).__init__(parent)
>>
>>         # Setup UI.
>>         self._layout = QtGui.QVBoxLayout(self)
>>         self._button = QtGui.QPushButton('Open files...')
>>         self._progress = QtGui.QProgressBar()
>>         self._filelist = QtGui.QPlainTextEdit()
>>         self._layout.addWidget(self._button)
>>         self._layout.addWidget(self._filelist)
>>         self._layout.addWidget(self._progress)
>>
>>         # Setup events.
>>         self._button.clicked.connect(self._button_clicked)
>>
>>         # Create the thread. Note that this doesn't actually _start_ it.
>>         self._thread = ProcessingThread()
>>         self._thread.file_processed.connect(self._file_processed)
>>
>>         # We need to wait for the thread before exiting. Either use this or
>>         # don't let the user close the window if processing is happening. See
>>         # the next method in this class.
>>         QtCore.QCoreApplication.instance().aboutToQuit.connect(
>>             self._thread.wait)
>>
>>     # def closeEvent(self, event):
>>     #     # This is an alternative to waiting for the threads. Just don't let
>>     #     # the user close the window.
>>     #     if self._thread.isRunning():
>>     #         QtGui.QMessageBox.critical(
>>     #             self, 'Processing',
>>     #             'Cannot exit while processing is happening.')
>>     #         event.ignore()
>>     #     else:
>>     #         event.accept()
>>
>>     def _button_clicked(self):
>>         # If we are already running the processing, produce an error.
>>         if self._thread.isRunning():
>>             QtGui.QMessageBox.critical(
>>                 self, 'Processing',
>>                 'Can only process one directory at a time.')
>>             return
>>
>>         # Get the directory name from the user.
>>         dir_name = QtGui.QFileDialog.getExistingDirectory(
>>             parent=self,
>>             caption='Choose files...',
>>             dir=os.getcwd())
>>
>>         # Activate the main dialog as it will be deactivated for some reason
>>         # after the file dialog closes (at least on my machine).
>>         self.activateWindow()
>>
>>         # Get the list of files in the directory and prime the progress bar.
>>         files = os.listdir(dir_name)
>>
>>         # Set values for progress bar.
>>         self._progress.setRange(0, len(files))
>>         self._progress.setValue(0)
>>
>>         # Create and start the thread.
>>         self._thread.files = files
>>         self._thread.start()
>>
>>     def _file_processed(self, num_files_processed, filename):
>>         # Called for each file that is processed.
>>         self._filelist.appendPlainText(filename)
>>         self._progress.setValue(num_files_processed)
>> if __name__ == '__main__':
>>     app = QtGui.QApplication(sys.argv)
>>     w = MyWidget()
>>     w.show()
>>     w.raise_()
>>     raise SystemExit(app.exec_())
>>
>> This is all fine, but it might not solve your original problem of the
>> file dialog not closing. On my Mac, the file dialog is gone as soon as the
>> call to getExistingDirectory() finishes. However, since I don’t have a
>> runnable portion of your code, I can’t really test it. I would recommend
>> attempting to run my example to see if it exhibits the same problem as your
>> program. Hope this helps!
>>
>> Cheers,
>>
>>
>>
>>  --
>> Sean Fisk
>>
>>
>> On Tue, Dec 10, 2013 at 4:43 PM, Frank Rueter | OHUfx <[email protected]>wrote:
>>
>>>  Here is an example using signals/slots
>>>
>>>
>>> On 11/12/13 09:56, Janwillem van Dijk wrote:
>>>
>>>  Here is the snippet: It reads the filenames in a folder and determines
>>> new names for photo's based on the exif info.
>>>
>>> I apreciate that threading might be a solution but the problem seems too
>>> simple for that. Can you give an example on how to use the signal concept?
>>>
>>>
>>> self.outFolder = QFileDialog.getExistingDirectory(
>>>
>>> caption='Destination folder', dir=self.defOutFolder)
>>>
>>> self.outFiles = []
>>>
>>> if self.outFolder:
>>>
>>> self.outFolder = self.outFolder.replace('\\', '/')
>>>
>>> self.lineEdit_dest.setText(self.outFolder)
>>>
>>> self.progressBar.setRange(0, self.numFiles)
>>>
>>> for i, fname in enumerate(self.inFiles):
>>>
>>> self.progressBar.setValue(i + 1)
>>>
>>> newpath, newfname = rename_photo(self.inFolder, fname)
>>>
>>> newpath = path.join(self.outFolder, newpath)
>>>
>>> self.outFiles.append([fname, newpath, newfname])
>>>
>>> s = fname + ' --> ' + self.outFolder + '\n'
>>>
>>> s += path.join(newpath, newfname).replace(self.outFolder, '')
>>>
>>> self.plainTextEdit_dest.appendPlainText(s)
>>>
>>>
>>>
>>> On 10/12/13 21:35, Sean Fisk wrote:
>>>
>>>  Hi Janwillem,
>>>
>>> Are you running the “lengthy part that processes a files list” within
>>> the GUI thread? If so, you will probably see your GUI hang while this is
>>> happening (you won’t be able to click or do anything). In this case, you
>>> should consider running the processing in a different thread using
>>> QThread<http://seanfisk.github.io/pyside-docs/pyside/PySide/QtCore/QThread.html>or
>>> QThreadPool<http://seanfisk.github.io/pyside-docs/pyside/PySide/QtCore/QThreadPool.html>
>>> .
>>>
>>> Can you post the relevant part of the code?
>>>
>>> Thanks,
>>>
>>>
>>>  --
>>> Sean Fisk
>>>
>>>
>>> On Tue, Dec 10, 2013 at 3:17 PM, Janwillem van Dijk <
>>> [email protected]> wrote:
>>>
>>>>  Hi, I have a PySide script that uses
>>>> QFileDialog.getExistingDirectory(). After clicking the Open button the
>>>> script proceeds with a lengthy part that processes a files list and writes
>>>> to a QPlainTextEdit. Unfortunately the QFileDialog widget does only
>>>> disappear after this processing is finished, hiding the QPlainTextEdit.
>>>>
>>>> How can I make that the QFileDialog widget is gone before the
>>>> processing starts?
>>>>
>>>> Cheers, Janwillem
>>>>
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> PySide mailing list
>>>> [email protected]
>>>> http://lists.qt-project.org/mailman/listinfo/pyside
>>>>
>>>>
>>>
>>>
>>>
>>
>>
>
>
_______________________________________________
PySide mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/pyside

Reply via email to