实战PyQt5: 115-画笔类QPen

QPen简介

QPen定义了用于QPainter应该怎样画线或者轮廓线。画笔具有样式、宽度、画刷、笔帽样式和连接样式等属性。画笔的样式style()定义了线的样式。画刷brush()用于填充画笔所绘制的线条。笔帽样式capStyle()定义了使用QPainter绘制的线的末端;连接样式joinStyle()则定义了两条线如何连接起来。画笔宽度width()或widthF()定义了画笔的宽。注意,不存在宽度为 0 的线。假设你设置 width 为 0,QPainter依然会绘制出一条线,而这个线的宽度为 1 像素。也就是说,画笔宽度通常至少是 1 像素。

可以使用setStyle(), setWidth(), setBrush(), setCapStyle()和setJoinStyle()函数来修改各种设置,例如:

painter = QPainter(self)
pen = QPen(Qt.green, 3, Qt.DashDotLine, Qt.RoundCap, Qt.RoundJoin)
painter.setPen(pen)

上述代码等价于:

painter = QPainter(self)
pen = QPen()
pen.setStyle(Qt.DashDotLine)
pen.setWidth(3)
pen.setBrush(Qt.green)
pen.setCapStyle(Qt.RoundJoin)
painter.setPen(pen)

 

默认的笔是宽度为1的纯黑色画笔,方帽样式(Qt.quareCap)和斜角连接样式(Qt.BevelJoin)。

线型样式(Pen Style)

Qt提供了以枚举变量Qt.PenStyle表示的几种线型内置样式:

实战PyQt5: 115-画笔类QPen

图片来源:doc.qt.io

除了Qt.CustomDashLine样式外,只需使用setStyle()函数就可以将线型转换成任何一种内置样式。如果将线型设置为Qt.NoPen则表示不绘制线条或者轮廓,默认的线型是Qt.SolidLine。还可以使用setDashPattern()函数指定自定义虚线图案,注意该函数将线型隐式转换成Qt.CustomDashLine样式。

笔帽样式(Cap Style)

笔帽定义了画笔末端的样式,笔帽样式仅适用于宽线的情况(即线宽大于等于1的时候)。Qt.PenCapStyle枚举变量提供了以下三种样式。

实战PyQt5: 115-画笔类QPen

图片来源:doc.qt.io

他们之间的区别是,Qt.SquareCap是一种包含了最后一个点的方形端点,使用半个线宽覆盖;Qt.FlatCap不包含最后一个点;Qt.RoundCap是包含最后一个点的圆形端点。具体可以参考下面的示例:

实战PyQt5: 115-画笔类QPen

图片来源:《C++ GUI Programming with Qt 4, 2nd Edition》

连接样式(Join Style)

连接样式定义了两条线连接时的样式,样式仅适用于宽线的情况(即线宽大于等于1的时候)。Qt.PenJoinStyle枚举变量提供了以下三种样式。

实战PyQt5: 115-画笔类QPen

图片来源:doc.qt.io

同样,可以参考下面图示来理解这几种连接样式的细节:

实战PyQt5: 115-画笔类QPen

图片来源:《C++ GUI Programming with Qt 4, 2nd Edition》

QPen常用函数

  • setJoinStyle(self, pjs: Qt.PenJoinStyle): 设置连接样式
  • joinStyle(self): 获取连接样式
  • setCapStyle(self, pcs: Qt.PenCapStyle): 设置笔帽样式
  • capStyle(self): 获取笔帽样式
  • setBrush(self, brush): 设置画刷
  • brush(self): 获取画刷
  • setColor(self, color): 设置画笔演示
  • color(self): 获得画笔的颜色
  • setWidth(self, width: int): 设置线宽
  • width(self): 获得线宽
  • setWidthF(self, width: float): 设置浮点数线宽
  • widthF(self): 获得浮点数线宽
  • setStyle(self, a0: Qt.PenStyle): 设置线型
  • style(self): 获得线型

测试

测试程序演示了,改变画笔线宽,颜色, 线型,笔帽样式和连接样式,完整代码如下:

import sys, math
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QPoint, QPointF
from PyQt5.QtGui import QColor,QPen, QPainter, QPainterPath, QPolygonF
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout, QFormLayout, 
                             QLabel, QFrame, QSizePolicy, QSpinBox, QPushButton,
                             QColorDialog, QComboBox)
 
class MyFrame(QFrame):
    def __init__(self, parent = None):
        super(MyFrame, self).__init__(parent)
        self.setFrameShape(QFrame.Box)
        self.setFrameShadow(QFrame.Plain)
        self.setLineWidth(1)
        self.setMidLineWidth(0)
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        
        self.penColor = Qt.black
        self.lineWidth = 4
        self.penStyle = Qt.SolidLine
        self.capStyle = Qt.FlatCap
        self.joinStyle = Qt.MiterJoin
        
    def setPenColor(self, color):
        self.penColor = color
        self.update()
        
    def setLineWidth(self, width):
        self.lineWidth = width
        self.update()
        
    def setPenStyle(self, style):
        self.penStyle = style
        self.update()
        
    def setCapStyle(self, style):
        self.capStyle = style
        self.update()
        
    def setJoinStyle(self, style):
        self.joinStyle = style
        self.update()
        
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        
        #绘制边框线
        painter.drawRect(self.rect())
        
        pen = QPen()
        pen.setColor(self.penColor)
        pen.setWidth(self.lineWidth)
        pen.setStyle(self.penStyle)
        pen.setCapStyle(self.capStyle)
        pen.setJoinStyle(self.joinStyle)
        
        painter.setPen(pen)
        
        #绘制曲线
        start_pos = QPoint(400, 20)
        end_pos = QPoint(40, 200)   
        path = QPainterPath(start_pos)
        
        c1 = QPoint((start_pos.x() + end_pos.x()) // 2, start_pos.y())
        c2 = QPoint((start_pos.x() + end_pos.x()) // 2, end_pos.y())
        path.cubicTo(c1, c2, end_pos)
        painter.drawPath(path)
        
        #绘制五角星
        #添加一个多边形(五角星)
        #外点:x=Rcos(72°*k)  y=Rsin(72°*k)   k=0,1,2,3,4
        #内点:r=Rsin18°/sin36°  x=rcos(72°*k+36°)  y=rsin(72°*k+36°)   k=0,1,2,3,4
        deg_18 = 18 * math.pi / 180
        deg_36 = 36 * math.pi / 180
        deg_72 = 72 * math.pi / 180
        r_out = 100 #半径
        r_inner = r_out * math.sin(deg_18) / math.sin(deg_36)
        polygon = QPolygonF()
        for i in range (5) :   
            #外点
            out_angle = deg_72 * i - deg_18   
            polygon.append(QPointF(r_out * math.cos(out_angle), r_out * math.sin(out_angle))) 
            #内点
            in_angle =  deg_72 * i + deg_18
            polygon.append(QPointF(r_inner * math.cos(in_angle), r_inner * math.sin(in_angle)))
        
        painter.translate(260, 260)
        painter.drawPolygon(polygon)
        
        
class DemoPen(QWidget):
    def __init__(self, parent=None):
        super(DemoPen, self).__init__(parent)   
        
        # 设置窗口标题
        self.setWindowTitle('实战PyQt5: QPen演示') 
        
        #设置尺寸
        self.resize(720, 400)    
              
        self.initUi()
        
    def initUi(self):
        layout = QHBoxLayout()
        
        self.canvas = MyFrame()
        
        #线宽
        lineWidth = QSpinBox()
        lineWidth.setRange(1, 40)
        lineWidth.setValue(4)
        lineWidth.valueChanged.connect(self.canvas.setLineWidth)
        
        #颜色设置
        btnSetColor = QPushButton('设置颜色')
        btnSetColor.clicked.connect(self.onSetPenColor)
        
        #线型设置
        cmbPenStyle = QComboBox()
        cmbPenStyle.addItems(['SolidLine', 'DashLine', 'DotLine', 'DashDotLine', 'DashDotDotLine'])
        cmbPenStyle.currentTextChanged.connect(self.onPenStyleChanged)
        
        #笔帽样式设置
        cmbCapStyle = QComboBox()
        cmbCapStyle.addItems(['FlatCap', 'SquareCap', 'RoundCap'])
        cmbCapStyle.currentTextChanged.connect(self.onCapStyleChanged)
        
        #连接样式设置
        cmbJoinStyle = QComboBox()
        cmbJoinStyle.addItems(['MiterJoin','BevelJoin','RoundJoin'])
        cmbJoinStyle.currentTextChanged.connect(self.onJoinStyleChanged)
        
        fLayout = QFormLayout()
        fLayout.setContentsMargins(0,0,0,0)
        fLayout.addRow('线宽: ', lineWidth)
        fLayout.addRow('颜色: ', btnSetColor)
        fLayout.addRow('线型: ', cmbPenStyle)
        fLayout.addRow('笔帽样式: ', cmbCapStyle)
        fLayout.addRow('连接样式: ', cmbJoinStyle)
        
        wid_left = QWidget()
        wid_left.setMaximumWidth(200)
        wid_left.setLayout(fLayout)
                  
        layout.addWidget(wid_left)
        layout.addWidget(self.canvas)
        
        self.setLayout(layout)
        
    def onSetPenColor(self):
       color = QColorDialog.getColor()
       self.canvas.setPenColor(color)
       
    def onPenStyleChanged(self, style):
        if style == 'SolidLine':
            self.canvas.setPenStyle(Qt.SolidLine)
        elif style == 'DashLine':
            self.canvas.setPenStyle(Qt.DashLine)
        elif style == 'DotLine':
            self.canvas.setPenStyle(Qt.DotLine)
        elif style == 'DashDotLine':
            self.canvas.setPenStyle(Qt.DashDotLine)
        elif style == 'DashDotDotLine':
            self.canvas.setPenStyle(Qt.DashDotDotLine)
        else:
            self.canvas.setPenStyle(Qt.NoPen)
            
    def onCapStyleChanged(self, style):
        if style == 'FlatCap':
            self.canvas.setCapStyle(Qt.FlatCap)
        elif style == 'SquareCap':
            self.canvas.setCapStyle(Qt.SquareCap)
        elif style == 'RoundCap':
            self.canvas.setCapStyle(Qt.RoundCap)
        else:
            self.canvas.setCapStyle(Qt.FlatCap)
            
    def onJoinStyleChanged(self, style):
        if style == 'MiterJoin':
            self.canvas.setJoinStyle(Qt.MiterJoin)
        elif style == 'BevelJoin':
            self.canvas.setJoinStyle(Qt.BevelJoin)
        elif style == 'RoundJoin':
            self.canvas.setJoinStyle(Qt.RoundJoin)
        else:
            self.canvas.setJoinStyle(Qt.MiterJoin)
    
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = DemoPen()
    window.show()
    sys.exit(app.exec())   

运行结果如下图:

实战PyQt5: 115-画笔类QPen

QPen演示

本文知识点

  • QPen 线型
  • QPen 笔帽样式
  • QPen 线连接样式

前一篇: 实战PyQt5: 114-颜色类QColor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值