找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

PyQt 自定义窗口部件(三)

admin 2019-5-10 17:38 572人围观 Qt相关

本篇介绍用如何QPainter()画出一个可以显示混合流体流速的Y形管控件。



Y形管由abci、edcf 以及cihgf三部分组成,内部的颜色由流体的流速决定。各个部分均使用逻辑坐标系绘制。



代码如下:

    from PyQt5.QtWidgets import (QApplication,QFrame, QLabel,QSizePolicy, QSpinBox, QWidget)from PyQt5.QtGui import QColor,QPainter,QFontMetricsF,QBrush,QLinearGradient,QPolygon,QPolygonFfrom PyQt5.QtCore import QPointF, QSize, Qt,pyqtSignal
    class YPipeWidget(QWidget): signal_valuechanged = pyqtSignal(int,int) def __init__(self, leftFlow=0, rightFlow=0, maxFlow=100, parent=None):super(YPipeWidget, self).__init__(parent)self.leftSpinBox = QSpinBox(self)self.leftSpinBox.setRange(0, maxFlow)self.leftSpinBox.setValue(leftFlow)self.leftSpinBox.setSuffix(" l/s")#设置后缀self.leftSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)self.leftSpinBox.valueChanged.connect(self.valueChanged)self.rightSpinBox = QSpinBox(self)self.rightSpinBox.setRange(0, maxFlow)self.rightSpinBox.setValue(rightFlow)self.rightSpinBox.setSuffix(" l/s")#设置后缀self.rightSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)self.rightSpinBox.valueChanged.connect(self.valueChanged)self.label = QLabel(self)self.label.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken)self.label.setAlignment(Qt.AlignCenter) fm = QFontMetricsF(self.font())self.label.setMinimumWidth(fm.width(" 999 l/s "))self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding))#横向竖向均可放大self.setMinimumSize(self.minimumSizeHint())self.valueChanged()
    def valueChanged(self): a = self.leftSpinBox.value() b = self.rightSpinBox.value()self.label.setText("{0} l/s".format(a + b))self.signal_valuechanged.emit(a,b)self.update()
    def values(self):returnself.leftSpinBox.value(), self.rightSpinBox.value() def minimumSizeHint(self):return QSize(self.leftSpinBox.width() * 3,self.leftSpinBox.height() * 5) def resizeEvent(self, event=None): fm = QFontMetricsF(self.font()) x = (self.width() - self.label.width()) / 2 y = self.height() - (fm.height() * 1.5)self.label.move(x, y) y = self.height() / 60.0 x = (self.width() / 4.0) - self.leftSpinBox.width()self.leftSpinBox.move(x, y) x = self.width() - (self.width() / 4.0)self.rightSpinBox.move(x, y) def paintEvent(self, event=None): LogicalSize = 100.0 def logicalFromPhysical(length, side):return (length / side) * LogicalSize fm = QFontMetricsF(self.font()) ymargin = ((LogicalSize / 30.0) +logicalFromPhysical(self.leftSpinBox.height(),self.height())) ymax = (LogicalSize - logicalFromPhysical(fm.height() * 2, self.height())) width = LogicalSize / 4.0#设置Y形管 9 个角点的坐标 cx, cy = LogicalSize / 2.0, LogicalSize / 3.0 ax, ay = cx - (2 * width), ymargin bx, by = cx - width, ay dx, dy = cx + width, ay ex, ey = cx + (2 * width), ymargin fx, fy = cx + (width / 2), cx + (LogicalSize / 24.0) gx, gy = fx, ymax hx, hy = cx - (width / 2), ymax ix, iy = hx, fy painter = QPainter(self)# 创建QPainter实例,注意self! painter.setRenderHint(QPainter.Antialiasing)#抗锯齿 side = min(self.width(), self.height())#设置绘图“视口”(使用物理坐标系),参数(整形)分别为左上角的x和y,以及视口的宽和高 painter.setViewport((self.width() - side) / 2, (self.height() - side) / 2, side, side)#设置绘图“窗口”(使用逻辑坐标系),参数(整形)分别为左上角的x和y,以及“窗口”的宽和高#之后逻辑坐标系 (Qpainter自动会将逻辑坐标按比例映射到物理坐标) painter.setWindow(0, 0, LogicalSize, LogicalSize) painter.setPen(Qt.NoPen) #无线条 gradient = QLinearGradient(QPointF(0, 0),QPointF(0, 100))#线性梯度 gradient.setColorAt(0, Qt.white) a = self.leftSpinBox.value() gradient.setColorAt(1, (Qt.red if a != 0else Qt.white)) #流速非零时,左边流体为红色 painter.setBrush(QBrush(gradient)) #画刷#绘制左边多边形(4边形) painter.drawPolygon(QPolygonF([QPointF(ax, ay), QPointF(bx, by), QPointF(cx, cy), QPointF(ix, iy)])) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) b = self.rightSpinBox.value() gradient.setColorAt(1, (Qt.blue if b != 0else Qt.white)) #流速非零时,右边流体为蓝色 painter.setBrush(QBrush(gradient))#绘制右边多边形(4边形) painter.drawPolygon(QPolygonF([QPointF(cx, cy), QPointF(dx, dy),QPointF(ex, ey),QPointF(fx, fy)]))#计算混合流体的颜色if (a + b) == 0: color = QColor(Qt.white)else: ashare = (a / (a + b)) * 255.0 bshare = 255.0 - ashare color = QColor(ashare, 0, bshare) gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100)) gradient.setColorAt(0, Qt.white) gradient.setColorAt(1, color) painter.setBrush(QBrush(gradient))#绘制下部多边形(5边形) painter.drawPolygon(QPolygonF([QPointF(cx, cy),QPointF(fx, fy),QPointF(gx, gy), QPointF(hx, hy),QPointF(ix, iy)]))#绘制Y形管边界(黑色粗实线) painter.setPen(Qt.black) painter.drawPolyline(QPolygonF([QPointF(ax, ay), QPointF(ix, iy),QPointF(hx, hy)])) painter.drawPolyline(QPolygonF([QPointF(gx, gy), QPointF(fx, fy), QPointF(ex, ey)])) painter.drawPolyline(QPolygonF([QPointF(bx, by), QPointF(cx, cy), QPointF(dx, dy)]))
    if __name__ == "__main__": import sys def valueChanged(a, b): print(a, b) app = QApplication(sys.argv) form = YPipeWidget() form.signal_valuechanged.connect(valueChanged) form.setWindowTitle("YPipe") form.move(0, 0) form.show() form.resize(400, 400)    app.exec_()
    本篇的例子来自《Python Qt Gui 快速编程 ----PyQt 编程指南》,原文是PyQt4的,现已改为PyQt5 版本。

    ----------------------------------------------------------------------------------------------------------------------
    我们尊重原创,也注重分享,文章来源于微信公众号:Python编程 pyqt matplotlib,建议关注公众号查看原文。如若侵权请联系qter@qter.org。
    ----------------------------------------------------------------------------------------------------------------------

    鲜花

    握手

    雷人

    路过

    鸡蛋

    yafeilinux和他的朋友们微信公众号二维码

    微信公众号

    专注于Qt嵌入式Linux开发等。扫一扫立即关注。

    Qt开源社区官方QQ群二维码

    QQ交流群

    欢迎加入QQ群大家庭,一起讨论学习!

    我有话说......