<html>
<head>
<meta content="text/html; charset=windows-1252"
http-equiv="Content-Type">
</head>
<body bgcolor="#FFFFFF" text="#000000">
<div class="moz-cite-prefix">The solution Frank proposed yesterday
works (after I found out that you can get the output using
<meta name="qrichtext" content="1">
selectedFiles()[0]).<br>
No problems with the progressbar.<br>
The actual processing can take a bit long because the exif's of
digital camera shots are analysed
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252">
<style type="text/css">
p, li { white-space: pre-wrap; }
</style>(GExiv2 for photos and exiftool for movies
<meta name="qrichtext" content="1">
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252">
<style type="text/css">
p, li { white-space: pre-wrap; </style>)
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252">
<style type="text/css">
p, li { white-space: pre-wrap; } </style> 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.<br>
Many thanks for teaching me this extra bit of Python.<br>
Cheers, Janwillem<br>
<br>
On 11/12/13 05:45, Sean Fisk wrote:<br>
</div>
<blockquote
cite="mid:CAF-FwG-9OeLZUv+xvXGf5z=WXtrFK+Fcbj_P6BFtr+v+24nwEQ@mail.gmail.com"
type="cite">
<div dir="ltr">
<div class="markdown-here-wrapper"
id="markdown-here-wrapper-176634" style="">
<p style="margin:1.2em 0px!important">Frank,</p>
<p style="margin:1.2em 0px!important">Your example is a good
demonstration of <code
style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px
0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px
solid
rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;display:inline">QFileDialog</code>‘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.</p>
<p style="margin:1.2em 0px!important">Janwillem,</p>
<p style="margin:1.2em 0px!important">As I see it, if you
would like a progress bar, you have three options:</p>
<ol style="margin:1.2em 0px;padding-left:2em">
<li style="margin:0.5em 0px">Call <a moz-do-not-send="true"
href="http://seanfisk.github.io/pyside-docs/pyside/PySide/QtCore/QCoreApplication.html#PySide.QtCore.PySide.QtCore.QCoreApplication.processEvents"><code
style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px
0.15em;padding:0px
0.3em;white-space:pre-wrap;border:1px solid
rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;display:inline">QCoreApplication.processEvents()</code></a>
during your processing code. This is not always a great
idea, and more of a hack than a solution. But it usually
works.</li>
<li style="margin:0.5em 0px">Split your processing into
chunks as in <a moz-do-not-send="true"
href="http://qt-project.org/wiki/Threads_Events_QObjects#72c9aabadf52900fbf3d4c1ff2b6008c">this
example</a>. 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.</li>
<li style="margin:0.5em 0px">Send your processing to a
thread, and dispatch events from the thread indicating the
progress.</li>
</ol>
<p style="margin:1.2em 0px!important">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:</p>
<pre style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="language-python" style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;display:inline;white-space:pre;overflow:auto;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block;padding:0.5em;color:rgb(51,51,51);background-color:rgb(248,248,255);background-repeat:initial initial"><span class="comment" style="color:rgb(153,153,136);font-style:italic">#!/usr/bin/env python</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Example: Asynchronously process a directory of files with a progress bar.</span>
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">import</span> sys
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">import</span> os
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">import</span> time
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">from</span> PySide <span class="keyword" style="color:rgb(51,51,51);font-weight:bold">import</span> QtCore, QtGui
<span class="class" style="color:rgb(68,85,136);font-weight:bold"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">class</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">ProcessingThread</span><span class="params">(QtCore.QThread)</span>:</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Fired when each file is processed.</span>
file_processed = QtCore.Signal(int, str)
<span class="function"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">def</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold">__init__</span><span class="params">(self, parent=None)</span>:</span>
super(ProcessingThread, self).__init__(parent)
self.files = []
<span class="function"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">def</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold">run</span><span class="params">(self)</span>:</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Code that's run in the thread.</span>
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">for</span> i, filename <span class="keyword" style="color:rgb(51,51,51);font-weight:bold">in</span> enumerate(self.files):
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># The actual code for one file goes here. Stubbed out with</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># time.sleep() for now.</span>
time.sleep(<span class="number" style="color:rgb(0,153,153)">0.5</span>)
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">print</span> <span class="string" style="color:rgb(221,17,68)">'Processed:'</span>, filename
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Send update to the GUI thread.</span>
self.file_processed.emit(i + <span class="number" style="color:rgb(0,153,153)">1</span>, filename)
<span class="class" style="color:rgb(68,85,136);font-weight:bold"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">class</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">MyWidget</span><span class="params">(QtGui.QWidget)</span>:</span>
<span class="function"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">def</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold">__init__</span><span class="params">(self, parent=None)</span>:</span>
super(MyWidget, self).__init__(parent)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Setup UI.</span>
self._layout = QtGui.QVBoxLayout(self)
self._button = QtGui.QPushButton(<span class="string" style="color:rgb(221,17,68)">'Open files...'</span>)
self._progress = QtGui.QProgressBar()
self._filelist = QtGui.QPlainTextEdit()
self._layout.addWidget(self._button)
self._layout.addWidget(self._filelist)
self._layout.addWidget(self._progress)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Setup events.</span>
self._button.clicked.connect(self._button_clicked)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Create the thread. Note that this doesn't actually _start_ it.</span>
self._thread = ProcessingThread()
self._thread.file_processed.connect(self._file_processed)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># We need to wait for the thread before exiting. Either use this or</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># don't let the user close the window if processing is happening. See</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># the next method in this class.</span>
QtCore.QCoreApplication.instance().aboutToQuit.connect(
self._thread.wait)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># def closeEvent(self, event):</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># # This is an alternative to waiting for the threads. Just don't let</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># # the user close the window.</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># if self._thread.isRunning():</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># QtGui.QMessageBox.critical(</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># self, 'Processing',</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># 'Cannot exit while processing is happening.')</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># event.ignore()</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># else:</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># event.accept()</span>
<span class="function"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">def</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold">_button_clicked</span><span class="params">(self)</span>:</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># If we are already running the processing, produce an error.</span>
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">if</span> self._thread.isRunning():
QtGui.QMessageBox.critical(
self, <span class="string" style="color:rgb(221,17,68)">'Processing'</span>,
<span class="string" style="color:rgb(221,17,68)">'Can only process one directory at a time.'</span>)
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">return</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Get the directory name from the user.</span>
dir_name = QtGui.QFileDialog.getExistingDirectory(
parent=self,
caption=<span class="string" style="color:rgb(221,17,68)">'Choose files...'</span>,
dir=os.getcwd())
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Activate the main dialog as it will be deactivated for some reason</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># after the file dialog closes (at least on my machine).</span>
self.activateWindow()
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Get the list of files in the directory and prime the progress bar.</span>
files = os.listdir(dir_name)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Set values for progress bar.</span>
self._progress.setRange(<span class="number" style="color:rgb(0,153,153)">0</span>, len(files))
self._progress.setValue(<span class="number" style="color:rgb(0,153,153)">0</span>)
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Create and start the thread.</span>
self._thread.files = files
self._thread.start()
<span class="function"><span class="keyword" style="color:rgb(51,51,51);font-weight:bold">def</span> <span class="title" style="color:rgb(153,0,0);font-weight:bold">_file_processed</span><span class="params">(self, num_files_processed, filename)</span>:</span>
<span class="comment" style="color:rgb(153,153,136);font-style:italic"># Called for each file that is processed.</span>
self._filelist.appendPlainText(filename)
self._progress.setValue(num_files_processed)
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">if</span> __name__ == <span class="string" style="color:rgb(221,17,68)">'__main__'</span>:
app = QtGui.QApplication(sys.argv)
w = MyWidget()
w.show()
w.raise_()
<span class="keyword" style="color:rgb(51,51,51);font-weight:bold">raise</span> SystemExit(app.exec_())</code></pre>
<p style="margin:1.2em 0px!important">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 <code
style="font-size:0.85em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px
0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px
solid
rgb(234,234,234);background-color:rgb(248,248,248);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;display:inline">getExistingDirectory()</code>
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!</p>
<p style="margin:1.2em 0px!important">Cheers,</p>
</div>
<div>
<div><br>
</div>
</div>
</div>
<div class="gmail_extra"><br clear="all">
<div>
<div><br>
</div>
<div>--</div>
<div>Sean Fisk</div>
</div>
<br>
<br>
<div class="gmail_quote">On Tue, Dec 10, 2013 at 4:43 PM, Frank
Rueter | OHUfx <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:frank@ohufx.com" target="_blank">frank@ohufx.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"> Here is an example
using signals/slots
<div>
<div class="h5"><br>
<br>
<div>On 11/12/13 09:56, Janwillem van Dijk wrote:<br>
</div>
<blockquote type="cite">
<div>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">Here
is the snippet: It reads the filenames in a
folder and determines new names for photo's
based on the exif info.</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">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?<br>
</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px"><br>
self.outFolder =
QFileDialog.getExistingDirectory(</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
caption='Destination folder',
dir=self.defOutFolder)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.outFiles = []</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
if self.outFolder:</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.outFolder = self.outFolder.replace('\\',
'/')</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.lineEdit_dest.setText(self.outFolder)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.progressBar.setRange(0, self.numFiles)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
for i, fname in enumerate(self.inFiles):</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.progressBar.setValue(i + 1)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
newpath, newfname = rename_photo(self.inFolder,
fname)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
newpath = path.join(self.outFolder, newpath)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.outFiles.append([fname, newpath, newfname])</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
s = fname + ' --> ' + self.outFolder + '\n'</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
s += path.join(newpath,
newfname).replace(self.outFolder, '')</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px">
self.plainTextEdit_dest.appendPlainText(s)</p>
<p
style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px;text-indent:0px"><br>
</p>
<br>
On 10/12/13 21:35, Sean Fisk wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr">
<div>
<p style="margin:1.2em 0px!important">Hi
Janwillem,</p>
<p style="margin:1.2em 0px!important">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 <a
moz-do-not-send="true"
href="http://seanfisk.github.io/pyside-docs/pyside/PySide/QtCore/QThread.html"
target="_blank">QThread</a> or <a
moz-do-not-send="true"
href="http://seanfisk.github.io/pyside-docs/pyside/PySide/QtCore/QThreadPool.html"
target="_blank">QThreadPool</a>.</p>
<p style="margin:1.2em 0px!important">Can you
post the relevant part of the code?</p>
<p style="margin:1.2em 0px!important">Thanks,</p>
</div>
</div>
<div class="gmail_extra"><br clear="all">
<div>
<div><br>
</div>
<div>--</div>
<div>Sean Fisk</div>
</div>
<br>
<br>
<div class="gmail_quote">On Tue, Dec 10, 2013 at
3:17 PM, Janwillem van Dijk <span dir="ltr"><<a
moz-do-not-send="true"
href="mailto:jwevandijk@xs4all.nl"
target="_blank">jwevandijk@xs4all.nl</a>></span>
wrote:<br>
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px
#ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"> 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.<br>
<br>
How can I make that the QFileDialog widget
is gone before the processing starts?<br>
<br>
Cheers, Janwillem<br>
<br>
<br>
<br>
</div>
<br>
_______________________________________________<br>
PySide mailing list<br>
<a moz-do-not-send="true"
href="mailto:PySide@qt-project.org"
target="_blank">PySide@qt-project.org</a><br>
<a moz-do-not-send="true"
href="http://lists.qt-project.org/mailman/listinfo/pyside"
target="_blank">http://lists.qt-project.org/mailman/listinfo/pyside</a><br>
<br>
</blockquote>
</div>
<br>
</div>
</blockquote>
<br>
</blockquote>
<br>
</div>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</blockquote>
<br>
</body>
</html>