Update QWidget every minutes - python

Is their a way possible to update a Qwidget in PyQT4 every 15 minutes ? I know their is something like a Qtimer but is it also possible to make a QWidget update itself at a specific time,for example 00h00 00h15 00h30 00h45 01h00,... . So is their a way to make the Qtimer depend on the time?

The QTimer class has a setInterval method. You can utilize this to change the wait time on the fly. As a short example, this block of code will show the current second. However, if the second is a multiple of 10 it will wait 5 seconds before starting again:
import sys
from PyQt4 import QtGui, QtCore
from time import strftime
class Main(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.initUI()
def initUI(self):
self.timer = QtCore.QTimer(self)
self.timer.timeout.connect(self.Time)
self.timer.start(1000)
self.lcd = QtGui.QLCDNumber(self)
self.lcd.display(strftime("%S"))
self.setCentralWidget(self.lcd)
self.setGeometry(300,300,250,100)
def Time(self):
if int(strftime("%S")) % 10 == 0:
self.timer.setInterval(5000)
else:
self.timer.setInterval(1000)
self.lcd.display(strftime("%S"))
def main():
app = QtGui.QApplication(sys.argv)
main = Main()
main.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
(This was modified slightly from a tutorial showing how to build a digital clock)
It looks like this for 4 consecutive changes of the display:
For your particular problem, when you start the application, you can find how long it is until the next quarter hour via a function like is presented in this answer:
def next_quarter_hour(self):
dt = datetime.datetime.now()
nsecs = dt.minute*60+dt.second+dt.microsecond*1e-6
delta = (nsecs//900)*900+900-nsecs
return delta * 1000.0
This would change the following:
def initUI(self):
...
self.timer.start(next_qt_hour)
...
def Time(self):
if int(strftime("%M")) % 15 == 0:
self.timer.setInterval(900000)
self.lcd.display(strftime("%M"))
Use this to set your first interval. Then once that timer has been exhausted, reset your interval to 15 minutes.

Related

PyQt4: use a QTimer to continually update progress bars

I have a simple dialog with three progress bars that I want to continually update (displaying system resource usage). From reading around the docs, QTimer is the right way to fire a function every x milliseconds (which would update the progress bars). However, I am not able to get it to work and I don't quite know why. It seems relatively simple to connect up the timer timeout signal to an update function, but it never seems to fire.
Here's my code:
import sys
from PyQt4 import QtGui, QtCore
import psutil
class Tiny_System_Monitor(QtGui.QWidget):
def __init__(self):
super(Tiny_System_Monitor, self).__init__()
self.initUI()
def initUI(self):
mainLayout = QtGui.QHBoxLayout()
self.cpu_progressBar = QtGui.QProgressBar()
self.cpu_progressBar.setTextVisible(False)
self.cpu_progressBar.setOrientation(QtCore.Qt.Vertical)
mainLayout.addWidget(self.cpu_progressBar)
self.vm_progressBar = QtGui.QProgressBar()
self.vm_progressBar.setOrientation(QtCore.Qt.Vertical)
mainLayout.addWidget(self.vm_progressBar)
self.swap_progressBar = QtGui.QProgressBar()
self.swap_progressBar.setOrientation(QtCore.Qt.Vertical)
mainLayout.addWidget(self.swap_progressBar)
self.setLayout(mainLayout)
timer = QtCore.QTimer()
timer.timeout.connect(self.updateMeters)
timer.start(1000)
def updateMeters(self):
cpuPercent = psutil.cpu_percent()
vmPercent = getattr(psutil.virtual_memory(), "percent")
swapPercent = getattr(psutil.swap_memory(), "percent")
self.cpu_progressBar.setValue(cpuPercent)
self.vm_progressBar.setValue(vmPercent)
self.swap_progressBar.setValue(swapPercent)
print "updated meters"
def main():
app = QtGui.QApplication(sys.argv)
ex = Tiny_System_Monitor()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
You must keep a reference to the timer object, otherwise it will be immediately garbage-collected when initUI returns:
class Tiny_System_Monitor(QtGui.QWidget):
...
def initUI(self):
...
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updateMeters)
self.timer.start(1000)

Stopwatch (chronometre) doesn't work

I make a stopwatch (chronometre) in python using the library pyqt, but I have a problem when I press the reset button and then the start button, I see the time increase of two, and repeat the process I see that increase in threes and so on.
I do not understand why this happens. I hope some can help me.
This is the code:
# -*- coding: utf-8 -*-
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4 import uic
class Cronometro(QWidget):
def __init__(self):
QWidget.__init__(self)
uic.loadUi("cronometro.ui", self)
self.sec = 0
self.timer = QTimer()
self.set_time()
# Conexion
self.btnStart.clicked.connect(self.start)
self.btnReset.clicked.connect(self.reset)
self.btnExit.clicked.connect(self.close)
def start(self):
self.timer.timeout.connect(self.counter)
self.timer.start(1000)
def reset(self):
self.timer.stop()
self.sec = 0
def counter(self):
self.sec += 1
self.set_time()
def is_timer_active(self):
return self.timer.isActive()
def set_time(self):
hora = self.sec / 3600
minutos = (self.sec % 3600) / 60
segundos = (self.sec % 3600) % 60
self.label.setText("%02d:%02d:%02d" % (hora, minutos, segundos))
app = QApplication(sys.argv)
ventana = Cronometro()
ventana.show()
sys.exit(app.exec_())
Thank you very much !!!
The problem is here, in your start method:
def start(self):
self.timer.timeout.connect(self.counter)
self.timer.start(1000)
Every time you start the timer, you connect the timer's timeout signal to your counter method. So if you start the timer twice, there are two connections from the timer to your counter method, so the counter method gets called twice on every tick of the timer.
The fix is fairly straightforward: move the line
self.timer.timeout.connect(self.counter)
into your __init__ method, so that the connection is only ever made once.

How to get a value of QTimeEdit,QCheckBox and QDateTimeEdit into a variable. (Python)

I'm starting with PyQt4 and I'm making a program for practice. In that program I have QDateTimeEdit, QTimeEdit and QCheckBox.
How would I pull values from them into a string using signals and slots.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class main_frame(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.initUI()
def initUI(self):
# A push buttnon
btn_get = QPushButton("Get Time", self)
btn_get.move(100, 250)
#
time = QTime()
# Find what is the local/system time
curent_t = time.currentTime()
# Convert it to a str
# The output shoud be HH:MM:SS , eg 10:45:28
curent_t_str = curent_t.toString()
# Create a timeEdit widget
time_widget = QTimeEdit(time, self)
time_widget.setTime(curent_t)
def get_time():
print(curent_t_str)
btn_get.clicked.connect(get_time)
### At the end of the day you got curent_t_str variable
### which you can use it in your code down the road
### so I belive that`s helpful for your needs
### implement this may vary, depending your needs ...
# Set a costom size for the mainWindow
self.setFixedSize(300, 300)
def main():
app = QApplication(sys.argv)
myapp = main_frame()
myapp.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Does that help you out ? Note that for QDateTimeEdit the procedure is the same, after you got your value into format like 10:45:28 is up to you how you gonna format the string or for what you gonna use

Python: How to Link Multi-Processes to Multi-Progress Bars

It seems I've got dangerously close to being able to link all the sub-processes initiated by subprocessing's Pool() to PyQt Progress Bar widgets. Here is the example code. Apparently there are few flows that stop my dream from happening.
The concept:
externalFunc() performs all the main tasks. From time to time it sends its 'progress values' to MainWindow() instance by storing its VALUE into poolDict variable declared with:
poolDict=manager.dict()
Meanwhile myEvenListener() method is running at the background awaiting for VALUE to be 'posted'. As soon as VALUE "received" myEvenListener() updates a ProgressBar to a received VALUE and resets it back to zero (to avoid the duplicate progressBar updates).
myEvenListener(self) before trying to update ProgressBar verifies the ProgressBar didn't yet reach its 100 maximum value before proceeding by using:
if pb.value()>=100: continue
Unfortunately even while externalFunc() supplies with more than enough values (160) the ProgressBar never reaches 100. Aside from it there is no way to exit MainWindow() while loop.
Please be carefull running this code before you read it since it may generate multi-python-processes on your machine that will have to be terminated.
Question:
Why does ProgressBar never reach its maximum 100
How to make sure myEvenListener() method is not running when it is not needed.
How to make sure all the sub-processes die after:
a. all the progressBars are at their 100%
b. user closes dialog box or terminates main process.
import sys, time
from PyQt4 import QtCore, QtGui
import multiprocessing as mp
from multiprocessing import Pool
manager = mp.Manager()
poolDict=manager.dict()
class PbWidget(QtGui.QProgressBar):
def __init__(self, parent=None, total=20):
super(PbWidget, self).__init__()
self.setMinimum(1)
self.setMaximum(total)
self._active = False
def update_bar(self, to_add_number):
while True:
time.sleep(0.01)
value = self.value() + to_add_number
self.setValue(value)
QtGui.qApp.processEvents()
if (not self._active or value >= self.maximum()):
break
self._active = False
def closeEvent(self, event):
self._active = False
def externalFunc(each):
for i in range(16):
print i
poolDict[each]=10+i
time.sleep(0.5)
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
# self.myList=[.1, .3, .5, 1.0, 1.5, 2.9, 3.1]
self.myList=[1]
self.main_layout = QtGui.QVBoxLayout()
self.pBars={}
self.state=True
for each in self.myList:
pb=PbWidget(total=101)
self.main_layout.addWidget(pb)
self.pBars[each]={'pb':pb, 'value':0, 'total_value':0}
ok_button = QtGui.QPushButton("OK")
ok_button.clicked.connect(self.OK)
self.main_layout.addWidget(ok_button)
central_widget = QtGui.QWidget()
central_widget.setLayout(self.main_layout)
self.setCentralWidget(central_widget)
def myEvenListener(self):
"""This function runs at the background as an infinite while loop. It constantly reads
a value stored in poolDict variable to which externalFunc() writes a new value every second.
The value represents a 'Progress' and needs to be passes to Progress Bar widget to which only MainWindow()
class has an access. After a Value was read it is used to update a Progress Bar.
After a progress bar was updated the Value is reset to zero.
The Problem: 'if pb.value()>=100' statement is used to make sure the function doesn't loop if the ProgressBar
is already reached 100. By some reason the bar never reaches its maximum 100 even while externalFunc() calls
enough times to reach this number. An ussue # 2: There is no meachanism to exit this while loop without adding
three more variables... Can it be achieved with what we already have?
"""
while self.state:
for each in self.pBars:
pb = self.pBars[each]['pb']
print "\n Current Bar value =", pb.value()
if pb.value()>=100:
print 'skipping'
continue
value=None
if each in poolDict.keys():
# read delivered value
delivered_value=poolDict[each]
# reset delivered value
poolDict[each]=0
# update bar with delivered value
if ( 101-pb.value() ) < delivered_value:
print "\n\t UPDATING WITH "
pb.update_bar( 101-pb.value() )
print "\n\t AFTER ", pb.value()
else:
pb.update_bar( delivered_value )
# print '\n\t\t\t Updating bar using this value', delivered_value
def OK(self):
pool = Pool(processes=3)
pool.map_async( externalFunc, self.myList)
self.myEvenListener()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.resize(480, 320)
window.show()
sys.exit(app.exec_())
Here is a revised code. It seems to be working well and it is quite stable.
import sys, time
from PyQt4 import QtCore, QtGui
import multiprocessing as mp
from multiprocessing import Pool
manager = mp.Manager()
poolDict=manager.dict()
class PbWidget(QtGui.QProgressBar):
def __init__(self, parent=None, total=20):
super(PbWidget, self).__init__()
self.setMinimum(1)
self.setMaximum(total)
self._active = False
def update_bar(self, to_add_number):
while True:
time.sleep(0.01)
value = self.value() + to_add_number
self.setValue(value)
QtGui.qApp.processEvents()
if (not self._active or value >= self.maximum()):
break
self._active = False
def closeEvent(self, event):
self._active = False
def externalFunc(each):
for i in range(16):
value =10+i
poolDict[each]=value
time.sleep(each)
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.myList=[.5, .8, 1.2, 1.8, 2.2, .3, .1]
self.main_layout = QtGui.QVBoxLayout()
self.pBars={}
self.state=True
self.name=None
for each in self.myList:
pb=PbWidget(total=101)
self.main_layout.addWidget(pb)
self.pBars[each]={'pb':pb, 'name':each}
ok_button = QtGui.QPushButton("Distribute")
ok_button.clicked.connect(self.OK)
self.main_layout.addWidget(ok_button)
central_widget = QtGui.QWidget()
central_widget.setLayout(self.main_layout)
self.setCentralWidget(central_widget)
def myEvenListener(self):
"""This function runs at the background as an infinite loop. It is constantly reading
a value stored in poolDict variable to which externalFunc() writes a new value.
The value represents a 'Progress' and needs to be passed to Progress Bar widget to which MainWindow()
class has an access. After a Value was read and used to update a Progress Bar it is reset to zero.
"""
entities = self.pBars.keys()
while self.state:
for each in entities:
if each not in self.pBars.keys(): continue
pb = self.pBars[each]['pb']
if pb.value()>=100:
self.pBars.pop(each, None)
value=None
if each in poolDict.keys():
# read delivered value
delivered_value=poolDict[each]
# reset delivered value
poolDict[each]=0
# update bar with delivered value
if ( 101-pb.value() ) < delivered_value:
pb.update_bar( 101-pb.value() )
elif delivered_value>0:
pb.update_bar( delivered_value )
if len(self.pBars.keys())==0:
self.state=False
def OK(self):
pool = Pool(processes=3)
pool.map_async( externalFunc, self.myList)
self.myEvenListener()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.resize(480, 320)
window.show()
sys.exit(app.exec_())

Strange behavior of QProgressBar with PyQt4

I have this sample of code:
import sys
import time
from PyQt4.QtGui import *
from PyQt4.QtCore import *
class Bar(QDialog):
def __init__(self, parent=None):
super(Bar, self).__init__()
self.pbar = QProgressBar(self)
self.pbar.setValue(0)
layout = QHBoxLayout()
layout.addWidget(self.pbar)
self.setLayout(layout)
def main(self):
for value in range(1, 100):
time.sleep(1)
print value
self.pbar.setValue(value)
app = QApplication(sys.argv)
form = Bar()
form.show()
form.main()
app.exec_()
I expect progressbar's value to increased by 1 every second.
Instead, although that all values printed on the screen, the progressbar shows only some of them. Also, the bar appears just when value == 5. I know how to achieve the appropriate result with QBasicTimer(), but why this one does not work? Did i make a stupid mistake?
Try adding a
QApplication.processEvents()
just after print value (this should force the UI to update).

Categories