Ok, will report back if I stumble across anything interesting. For now I will just assume that my example simply shouldn't work :-D

On 12/12/13 12:07, Sean Fisk wrote:
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] <mailto:[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] <mailto:[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  sys
        import  os
        import  time

        from  PySideimport  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, filenamein  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] <mailto:[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] <mailto:[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] <mailto:[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