[PyQt] First bottom-up GUI, acting strange

Nonyaz cheech at nonyaz.com
Sun Apr 19 18:37:30 BST 2009


On Sun, Apr 19, 2009 at 3:05 AM, Geert Vancompernolle
<geert.vancompernolle at gmail.com> wrote:
> Could it be that you need a QApplication.processEvents() call in your
> "while" loop?  This command gives some CPU to the GUI to update itself.  I'm
> afraid the "while" loop eats all CPU and there's no time/possibility to
> update the UI...

I stuck a QApplication.processEvents() in the loop just like you said
and it freed the GUI right up!  I'ts still not quite 100% fluid, but
its to be expected, and without threading, probably the best I can do.


On Sun, Apr 19, 2009 at 3:22 AM, Demetrius Cassidy
<dcassidy36 at mass.rr.com> wrote:
> Looking over your code, I suspect the problem is with this line:
>
> data = webPage.read(8192)
>      if not data:
>          break
>
> Unless data is 0 or None, it will go into an infinite loop. From your
> description, it does not sound like it will ever return 0. It is also not
> good programming practice to write loops that are by nature always True. I
> suggest you use the total number of bytes instead as the condition for your
> loop, so after x amount of bytes is read or written, the loop finishes.
>
> I also suggest making the download in a separate thread, to avoid locking up
> the GUI during long downloads (because the while loop is going to be using
> up all the CPU time for your app, without giving the Qt event loop a chance
> to run).

It wont infinite loop, it just keeps reading until it EOL's and then
breaks out of the loop.  The problem with using the headers from the
server, is that I've had situations where that information is not
available and thus I wouldn't be able to construct my loop.

I agree with the threading idea, that is the ideal fix, unfortunately
threading is in chapter 19 of my book, and I'm currently on 5 :)

Thanks again for all your help!

-Adam

On Sun, Apr 19, 2009 at 3:05 AM, Geert Vancompernolle
<geert.vancompernolle at gmail.com> wrote:
> Nonyaz wrote:
>>
>> I made an attempt to port over a little command line file DL script I
>> wrote into a GUI as a practice working with PyQt.
>> While I have seemingly achieved that goal, the resulting product is
>> not acting as I suspected. When I start a download,
>> the GUI will continue to update as long as I don't click it, as soon
>> as I do, the OS throws up "Not Responding" in the
>> title bar and the GUI no longer updates.  Even when I don't click it,
>> I can tell somethings not right, the start button never
>> releases, and the progress bar effects on vista are not apparent.
>>
>> Hopefully someone can point out to me what I'm doing wrong, I have a
>> feeling its just bad event loop execution, although
>> I'm not quite sure how I could rewrite it so it wouldn't have this
>> problem.
>>
>> import urllib, os, time, sys, win32con
>> import win32clipboard as w
>> from PyQt4.QtCore import *
>> from PyQt4.QtGui import *
>>
>> class Window(QDialog):
>>   def __init__(self, parent=None):
>>       super(Window, self).__init__(parent)
>>
>>       self.lineedit = QLineEdit()
>>       self.getclip = QCommandLinkButton("Poll Clipboard")
>>       self.progbar = QProgressBar()
>>       self.speed = QLabel()
>>       self.status = QLabel()
>>       self.startb = QPushButton("Start DL")
>>
>>       grid = QGridLayout()
>>       buttlay = QHBoxLayout()
>>       buttlay.addStretch()
>>       buttlay.addWidget(self.startb)
>>       grid.addWidget(self.lineedit,0,0)
>>       grid.addWidget(self.getclip,0,1)
>>       grid.addWidget(self.progbar,1,0,1,0)
>>       grid.addWidget(self.status,3,0)
>>       grid.addWidget(self.speed,3,1)
>>       grid.addLayout(buttlay,4,1)
>>       self.setLayout(grid)
>>
>>       self.setWindowTitle("Clipboard DL V.001")
>>       self.lineedit.setText(getText())
>>       self.lineedit.setMinimumSize(300,0)
>>       self.startb.setMaximumSize(75,300)
>>
>>       self.connect(self.startb, SIGNAL("clicked()"),
>>                    fileDL)
>>       self.connect(self.getclip, SIGNAL("clicked()"),
>>                    setClipText)
>>
>>
>> class myURLOpener(urllib.FancyURLopener):
>>   def http_error_206(self, url, fp, errcode, errmsg, headers, data=None):
>>       print "I've been 206'd!"
>>       pass
>>
>> def getText():
>>   w.OpenClipboard()
>>   try:
>>       d = w.GetClipboardData(win32con.CF_TEXT)
>>   except:
>>       d = "None."
>>   w.CloseClipboard()
>>   if d[:7] != "http://":
>>       d = "Clipboard does not contain a valid URL."
>>   return d
>>
>> def fileDL():
>>   loop = 1
>>   existSize = 0
>>   dlFile = getFilename()
>>   url = str(daprog.lineedit.text())
>>
>>   myUrlclass = myURLOpener()
>>   webPage = myUrlclass.open(url)
>>   contentLength = int(webPage.headers['Content-Length'])
>>
>>   if os.path.exists(str(dlFile)):
>>       outputFile = open(dlFile,"ab")
>>       existSize = os.path.getsize(dlFile)
>>
>>       if existSize < contentLength:
>>           webPage.close()
>>           myUrlclass = None
>>           myUrlclass = myURLOpener()
>>           myUrlclass.addheader("Range","bytes=%s-" % (existSize))
>>           webPage = myUrlclass.open(url)
>>
>>   else:
>>       try:
>>           outputFile = open(dlFile,"wb")
>>       except:
>>           os.mkdir(dldir+'/'+show)
>>       outputFile = open(dlFile,"wb")
>>       existSize = 0
>>
>>
>>   if existSize == contentLength:
>>       daprog.status.setText("All %s bytes already downloaded!\n" %
>> (contentLength))
>>       raw_input()
>>       loop = 0
>>   elif existSize == 0:
>>       pass
>>   elif existSize < contentLength:
>>       daprog.status.setText("Resuming download....")
>>
>>   numBytes = existSize
>>   daprog.status.setText("Download Started")
>>   counterr = 0
>>   while loop:
>>       if counterr == 0:
>>           intime = time.time()
>>
>> daprog.progbar.setValue((float(numBytes)/float(contentLength)*100))
>>       data = webPage.read(8192)
>>       if not data:
>>           break
>>       outputFile.write(data)
>>       numBytes += len(data)
>>       if counterr == 10:
>>           counterr = -1
>>           outtime = time.time()
>>           lab = "%.2f KB/s" % (((8192*10)/(outtime-intime))/1000)
>>           daprog.speed.setText(lab)
>>       counterr += 1
>>
>>
>>   daprog.progbar.setValue(100)
>>   daprog.status.setText("Done")
>>   webPage.close()
>>   outputFile.close()
>>
>>
>>
>> def getFilename():
>>   hack_fin = 0
>>   fname = ''
>>   for x in str(daprog.lineedit.text())[::-1]:
>>       if x == "/":
>>           hack_fin = 1
>>       if x != "/":
>>           if hack_fin == 0:
>>               fname += x
>>   return fname[::-1]
>>
>> def setClipText():
>>   daprog.lineedit.setText(getText())
>>
>>
>> app = QApplication(sys.argv)
>> daprog = Window()
>> daprog.show()
>> daprog.exec_()
>>
>>
>> Thanks for your help,
>> - Adam
>> _______________________________________________
>> PyQt mailing list    PyQt at riverbankcomputing.com
>> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
>>
>>
>
> Could it be that you need a QApplication.processEvents() call in your
> "while" loop?  This command gives some CPU to the GUI to update itself.  I'm
> afraid the "while" loop eats all CPU and there's no time/possibility to
> update the UI...
>
> From the documentation (QCoreApplication.processEvents()):
>
> "
> You can call this function occasionally when your program is busy performing
> a long operation (e.g. copying a file).
> "
>
> QApplication inherits QCoreApplication.
>
> Just a thought...
>
> --
> Best rgds,
>
> Geert
> ________________________________________________
>
> *Use EcoCho <http://www.ecocho.com>: environmentally friendly search the
> internet!*
>



More information about the PyQt mailing list