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_()
运行结果:
来源:https://blog.csdn.net/xiaoyangyang20/article/details/55253667


猜你喜欢
- 一、安装redis 是一个 Key-Value 数据库Value 支持 string(字符串),list(列表),set(集合),zset(
- 为了查找这些存储过程,你可以花时间在互联网搜索,查看一些你还未知道的存储过程,也许在一两个小时您可能会发现你想要...也许你很幸运的找到,其
- 本文介绍了Vue2 SSR 缓存 Api 数据,分享给大家,具体如下:1. 安装缓存依赖: lru-cachenpm install lru
- df.fillna主要用来对缺失值进行填充,可以选择填充具体的数字,或者选择临近填充。官方文档DataFrame.fillna(self,
- 本文实例讲述了Python实现购物评论文本情感分析操作。分享给大家供大家参考,具体如下:昨晚上发现了snownlp这个库,很开心。先说说我开
- 该章节我们学习虚拟环境的相关知识,虚拟环境对于刚刚使用Python的初学者来说使用的概率可能会比较低。但是我们依然要对它有一定的了解。认识虚
- 在上一篇《服务器XMLHTTP(Server XMLHTTP in ASP)基础》中我介绍了一下ServerX
- 数据结构与算法将序列分解为单独的变量问题:现在有一个包含 N 个元素的元组或者是序列,怎样将它里面的值解压后同时赋值给 N 个变量?解答:任
- 异步编程一直是JavaScript 编程的重大事项。关于异步方案, ES6 先是出现了 基于状态管理的 Promise,然后出现了 Gene
- 动态添加表单项iview的动态添加表单很简单,只需设置好表单项为一个array,添加新项目的时候就push一个默认好的值,剩下的iview会
- 字符串是不可变类型,可以重新赋值,但不可以索引改变其中一个值,只能拼接字符串建立新变量索引和切片索引:越界会报错切片:越界会自动修改不包含右
- 前几天,使用python时遇到这么一个需求,删除一个列表中值为1的元素。我寻思着使用remove方法,但是remove方法只会删除第一个,于
- 优化算法时间复杂度算法的时间复杂度对程序的执行效率影响最大,在Python中可以通过选择合适的数据结构来优化时间复杂度,如list和set查
- 目录连接池是什么?为什么需要连接池?连接池的原理是什么?使用python语言自制简易mysql连接池开始使用自定义配置文件名 & 配
- Part.I 预备知识Chap.I 几个概念的区分Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了
- 说实话,对于移除这个旧有功能对于我来说,我是欢心鼓舞的。因为我在开发和应用当中一向不用expression来处理,虽然它确实是非常方便,比如
- Django功能强大不单在于他先进的编程理念,很多现有的功能模块更是可以直接拿来使用,比如这个牛掰的admin模块,可以作为一个很好的信息登
- 导言概述插入、更新和删除数据 里我们已经学习了如何使用GridView等控件来插入,更新删除数据。通过ObjectDataSource和其它
- 如下所示:node2:/django/mysite/blog#cat views.py1,# -*- coding: utf-8 -*-fr
- 在日常工作或生活中,总避免不了需要操作文件或文件夹,比如希望找出电脑中所有临时文件并清除,或者找到指定文件夹内所有图片文件并进行重新命名等等