Article Outline
Python pyqt (gui) example 'counterlabel'
counterlabel
Python pyqt example: counterlabel
#!/usr/bin/env python
"""
counterlabel.py
A PyQt custom widget example for Qt Designer.
Copyright (C) 2006 David Boddie <[email protected]>
Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QRectF, QSize, Qt
from PyQt5.QtGui import QFont, QFontMetricsF, QPainter
from PyQt5.QtWidgets import QApplication, QWidget
class CounterLabel(QWidget):
"""CounterLabel(QWidget)
Provides a custom label widget to be used as a counter, with signals
similar to those provided by QAbstractSlider subclasses and properties
similar to those provided by QLabel.
"""
# We define two signals that are used to indicate changes to the status
# of the widget.
valueChanged = pyqtSignal((int, ), (str, ))
def __init__(self, parent=None):
super(CounterLabel, self).__init__(parent)
self.setAutoFillBackground(False)
self._font = QFont()
self._minimum = 1
self._maximum = 1
self._value = 1
self._offset = 0
self.rescale()
self.reposition()
def paintEvent(self, event):
p = QPainter()
p.begin(self)
p.setRenderHint(QPainter.Antialiasing)
p.setFont(self._font)
p.translate(self.width()/2.0, self.height()/2.0)
p.scale(self._scale, self._scale)
p.drawText(self._xpos, self._ypos, str(self._value))
p.end()
def sizeHint(self):
return QSize(32, 32)
def rescale(self):
fm = QFontMetricsF(self._font, self)
maxRect = fm.boundingRect(QRectF(self.rect()), Qt.AlignCenter,
str(self._maximum))
xscale = float(self.width())/maxRect.width()
yscale = float(self.height())/maxRect.height()
self._scale = min(xscale, yscale)
def reposition(self):
fm = QFontMetricsF(self._font, self)
rect = fm.boundingRect(QRectF(self.rect()), Qt.AlignCenter,
str(self._value))
self._xpos = -rect.width()/2.0
self._ypos = rect.height()/2.0 - fm.descent()
self.update()
# Provide getter and setter methods for the font property.
def getFont(self):
return self._font
def setFont(self, font):
self._font = font
self.rescale()
self.reposition()
font = pyqtProperty(QFont, getFont, setFont)
# Provide getter and setter methods for the minimum and maximum properties.
def getMinimum(self):
return self._minimum
def setMinimum(self, value):
self._minimum = value
if self._minimum > self._maximum:
self.setMaximum(self._minimum)
if self._minimum > self._value:
self.setValue(self._minimum)
minimum = pyqtProperty(int, getMinimum, setMinimum)
def getMaximum(self):
return self._maximum
def setMaximum(self, value):
self._maximum = value
self._minimum = min(self._minimum, self._maximum)
if self._maximum < self._value:
self.setValue(self._maximum)
self.rescale()
self.reposition()
maximum = pyqtProperty(int, getMaximum, setMaximum)
# We provide an offset property to allow the value shown to differ from
# the internal value held by the widget.
def getOffset(self):
return self._offset
def setOffset(self, value):
self._offset = value
offset = pyqtProperty(int, getOffset, setOffset)
# The value property is implemented using the getValue() and setValue()
# methods.
def getValue(self):
return self._value
# The setter method for the value property can also be used as a slot.
@pyqtSlot(int)
def setValue(self, value):
if not self._minimum <= value <= self._maximum:
return
self._value = value
self.valueChanged[int].emit(value + self._offset)
self.valueChanged[str].emit(str(value + self._offset))
self.reposition()
value = pyqtProperty(int, getValue, setValue)
# Like QAbstractSpinBox, we provide stepUp() and stepDown() slots to
# enable the value to be incremented and decremented.
@pyqtSlot()
def stepUp(self):
self.setValue(self._value + 1)
@pyqtSlot()
def stepDown(self):
self.setValue(self._value - 1)
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
widget = CounterLabel()
widget.setValue(123)
widget.show()
sys.exit(app.exec_())
Useful links
- Learn PyQt: https://pythonbasics.org/pyqt-hello-world/
- Install PyQt: https://pythonbasics.org/install-pyqt/