网络编程
位置:首页>> 网络编程>> Python编程>> python3+PyQt5实现自定义分数滑块部件

python3+PyQt5实现自定义分数滑块部件

作者:basisworker  发布时间:2023-08-03 02:15:28 

标签:python3,PyQt5,分数滑块

本文通过Python3+PyQt5实现自定义部件–分数滑块。它既能支持键盘也支持鼠标,使用物理(视口)坐标通过绘制方式显示。


#!/usr/bin/env python3

import platform
from PyQt5.QtCore import (QPointF, QRectF, QSize, Qt,pyqtSignal)
from PyQt5.QtWidgets import (QApplication, QDialog,QSizePolicy,
    QGridLayout, QLCDNumber, QLabel,
   QSpinBox, QWidget)
from PyQt5.QtGui import QColor,QFont,QPainter,QFontMetricsF,QPalette, QPolygonF
X11 = True
try:
 from PyQt5.QtGui import qt_x11_wait_for_window_manager
except ImportError:
 X11 = False

class FractionSlider(QWidget):

XMARGIN = 12.0
 YMARGIN = 5.0
 WSTRING = "999"
 valueChanged = pyqtSignal(int,int)

def __init__(self, numerator=0, denominator=10, parent=None):
   super(FractionSlider, self).__init__(parent)
   self.__numerator = numerator
   self.__denominator = denominator
   self.setFocusPolicy(Qt.WheelFocus)
   self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding,
                   QSizePolicy.Fixed))

def decimal(self):
   return self.__numerator / float(self.__denominator)

def fraction(self):
   return self.__numerator, self.__denominator

def sizeHint(self):
   return self.minimumSizeHint()

def minimumSizeHint(self):
   font = QFont(self.font())
   font.setPointSize(font.pointSize() - 1)
   fm = QFontMetricsF(font)
   return QSize(fm.width(FractionSlider.WSTRING) *
          self.__denominator,
          (fm.height() * 4) + FractionSlider.YMARGIN)

def setFraction(self, numerator, denominator=None):
   if denominator is not None:
     if 3 <= denominator <= 60:
       self.__denominator = denominator
     else:
       raise ValueError("denominator out of range")
   if 0 <= numerator <= self.__denominator:
     self.__numerator = numerator
   else:
     raise ValueError("numerator out of range")
   self.update()
   self.updateGeometry()

def mousePressEvent(self, event):
   if event.button() == Qt.LeftButton:
     self.moveSlider(event.x())
     event.accept()
   else:
     QWidget.mousePressEvent(self, event)

def mouseMoveEvent(self, event):
   self.moveSlider(event.x())

def moveSlider(self, x):
   span = self.width() - (FractionSlider.XMARGIN * 2)
   offset = span - x + FractionSlider.XMARGIN
   numerator = int(round(self.__denominator *
           (1.0 - (offset / span))))
   numerator = max(0, min(numerator, self.__denominator))
   if numerator != self.__numerator:
     self.__numerator = numerator
     #self.emit(SIGNAL("valueChanged(int,int)"),
     #     self.__numerator, self.__denominator)
     self.valueChanged.emit(self.__numerator, self.__denominator)
     self.update()

def keyPressEvent(self, event):
   change = 0
   if event.key() == Qt.Key_Home:
     change = -self.__denominator
   elif event.key() in (Qt.Key_Up, Qt.Key_Right):
     change = 1
   elif event.key() == Qt.Key_PageUp:
     change = (self.__denominator // 10) + 1
   elif event.key() in (Qt.Key_Down, Qt.Key_Left):
     change = -1
   elif event.key() == Qt.Key_PageDown:
     change = -((self.__denominator // 10) + 1)
   elif event.key() == Qt.Key_End:
     change = self.__denominator
   if change:
     numerator = self.__numerator
     numerator += change
     numerator = max(0, min(numerator, self.__denominator))
     if numerator != self.__numerator:
       self.__numerator = numerator
       #self.emit(SIGNAL("valueChanged(int,int)"),
       #     self.__numerator, self.__denominator)
       self.valueChanged.emit(self.__numerator, self.__denominator)
       self.update()
     event.accept()
   else:
     QWidget.keyPressEvent(self, event)

def paintEvent(self, event=None):
   font = QFont(self.font())
   font.setPointSize(font.pointSize() - 1)
   fm = QFontMetricsF(font)
   fracWidth = fm.width(FractionSlider.WSTRING)
   indent = fm.boundingRect("9").width() / 2.0
   if not X11:
     fracWidth *= 1.5
   span = self.width() - (FractionSlider.XMARGIN * 2)
   value = self.__numerator / float(self.__denominator)
   painter = QPainter(self)
   painter.setRenderHint(QPainter.Antialiasing)
   painter.setRenderHint(QPainter.TextAntialiasing)
   painter.setPen(self.palette().color(QPalette.Mid))
   painter.setBrush(self.palette().brush(
       QPalette.AlternateBase))
   painter.drawRect(self.rect())
   segColor = QColor(Qt.green).darker(120)
   segLineColor = segColor.darker()
   painter.setPen(segLineColor)
   painter.setBrush(segColor)
   painter.drawRect(FractionSlider.XMARGIN,
            FractionSlider.YMARGIN, span, fm.height())
   textColor = self.palette().color(QPalette.Text)
   segWidth = span / self.__denominator
   segHeight = fm.height() * 2
   nRect = fm.boundingRect(FractionSlider.WSTRING)
   x = FractionSlider.XMARGIN
   yOffset = segHeight + fm.height()
   for i in range(self.__denominator + 1):
     painter.setPen(segLineColor)
     painter.drawLine(x, FractionSlider.YMARGIN, x, segHeight)
     painter.setPen(textColor)
     y = segHeight
     rect = QRectF(nRect)
     rect.moveCenter(QPointF(x, y + fm.height() / 2.0))
     #painter.drawText(rect, Qt.AlignCenter,
              #QString.number(i))
     painter.drawText(rect, Qt.AlignCenter,str(i))      
     y = yOffset
     rect.moveCenter(QPointF(x, y + fm.height() / 2.0))
     painter.drawText(rect, Qt.AlignCenter,
              str(self.__denominator))
     painter.drawLine(QPointF(rect.left() + indent, y),
              QPointF(rect.right() - indent, y))
     x += segWidth
   span = int(span)
   y = FractionSlider.YMARGIN - 0.5
   triangle = [QPointF(value * span, y),
         QPointF((value * span) +
             (2 * FractionSlider.XMARGIN), y),
         QPointF((value * span) +
             FractionSlider.XMARGIN, fm.height())]
   painter.setPen(Qt.yellow)
   painter.setBrush(Qt.darkYellow)
   painter.drawPolygon(QPolygonF(triangle))

if __name__ == "__main__":
 import sys

app = QApplication(sys.argv)
 form = QDialog()
 sliderLabel = QLabel("&Fraction")
 slider = FractionSlider(denominator=12)
 sliderLabel.setBuddy(slider)
 denominatorLabel = QLabel("&Denominator")
 denominatorSpinBox = QSpinBox()
 denominatorLabel.setBuddy(denominatorSpinBox)
 denominatorSpinBox.setRange(3, 60)
 denominatorSpinBox.setValue(slider.fraction()[1])
 denominatorSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
 numeratorLabel = QLabel("Numerator")
 numeratorLCD = QLCDNumber()
 numeratorLCD.setSegmentStyle(QLCDNumber.Flat)
 layout = QGridLayout()
 layout.addWidget(sliderLabel, 0, 0)
 layout.addWidget(slider, 0, 1, 1, 5)
 layout.addWidget(numeratorLabel, 1, 0)
 layout.addWidget(numeratorLCD, 1, 1)
 layout.addWidget(denominatorLabel, 1, 2)
 layout.addWidget(denominatorSpinBox, 1, 3)
 form.setLayout(layout)

def valueChanged(denominator):
   numerator = int(slider.decimal() * denominator)
   slider.setFraction(numerator, denominator)
   numeratorLCD.display(numerator)

#form.connect(slider, SIGNAL("valueChanged(int,int)"),
        #numeratorLCD, SLOT("display(int)"))
 slider.valueChanged[int,int].connect(numeratorLCD.display)
 #form.connect(denominatorSpinBox, SIGNAL("valueChanged(int)"),
        #valueChanged)
 denominatorSpinBox.valueChanged[int].connect(valueChanged)
 form.setWindowTitle("Fraction Slider")
 form.show()
 app.exec_()

运行结果:

python3+PyQt5实现自定义分数滑块部件

来源:https://blog.csdn.net/xiaoyangyang20/article/details/55253667

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com