【问题标题】:QPaint draw lines with offsetQPaint 绘制带偏移的线条
【发布时间】:2019-04-03 21:42:58
【问题描述】:

我想用QPainter 画一些线,然后将线的起点(x1,y1) 坐标移动到centerpoint 和其他一些想要从中心偏移的线。这些线应该基于椭圆的值或其他值以编程方式运行。我已经尝试过不同的方法来解决它,但不起作用。

QRect可以使用

等代码
moveCenter, moveTopLeft, etc...

但是对于Qline,没有这样的方法。根据PyQt doc,可以这样画一条线:

QLine(int x1, int y1, int x2, int y2)
QLine(const QPoint &p1, const QPoint &p2)

也许应该使用这条线来抵消它。但不知道怎么做。

translated(const QPoint &offset)

另一方面想绘制一些文本并以与Qline类似的方式偏移它们。

看看下面的图,看看我到底想做什么?

可视化

到目前为止我所取得的成就。

我想要达到的目标。

代码:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Foo(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Foo, self).__init__(parent)
        self.setGeometry(QtCore.QRect(200, 100, 700, 600))        
        self.paint = Paint()
        self.sizeHint()
        self.lay = QtWidgets.QVBoxLayout()
        self.lay.addWidget(self.paint)
        self.setLayout(self.lay)

class Paint(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Paint, self).__init__(parent)
        self.setBackgroundRole(QtGui.QPalette.Base)     
        self.setAutoFillBackground(True)

        xl = self.rect().center().x()
        yl = self.rect().center().y()

        self.e = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(250, 250))
        self.l = QtCore.QLine(QtCore.QPoint(xl, yl) , QtCore.QPoint(self.width(), self.height()/2))



    def paintEvent(self, event):
        pen = QtGui.QPen()
        brush = QtGui.QBrush( QtCore.Qt.darkCyan, QtCore.Qt.Dense7Pattern)
        painter = QtGui.QPainter(self)
        painter.setBrush(brush)
        painter.setPen(pen)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        self.e.moveCenter(self.rect().center())

        painter.drawEllipse(self.e)
        painter.drawLine(self.l)
#        painter.drawText('D')

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Foo()
    w.show()
    sys.exit(app.exec_())

更新问题:

我已经更新了代码,我设法画出我想要的东西。但面临另一个挑战。如下图所示。

代码运行和显示时

Widget最小化或最大化时,有些线条消失了?

更新代码:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Foo(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Foo, self).__init__(parent)
        self.setGeometry(QtCore.QRect(200, 100, 700, 600))        
        self.paint = Paint()
        self.sizeHint()
        self.lay = QtWidgets.QVBoxLayout()
        self.lay.addWidget(self.paint)
        self.setLayout(self.lay)

class Paint(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Paint, self).__init__(parent)
        self.setBackgroundRole(QtGui.QPalette.Base)     
        self.setAutoFillBackground(True)


        self.e = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(250, 250))
        self.l1 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(200, 0))
        self.l2 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(0, -200))

        self.vl = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(0, -125))
        delta = QtCore.QPoint(20, 0)
        self.hl = QtCore.QLine(-delta, self.e.topRight() + delta)
        self.al = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(-20, -20))
        self.a2 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(-20, 20))
        self.a3 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(20, 20))
        self.a4 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(-20, 20))
        self._factor = 1.0

    def paintEvent(self, event):
        pen = QtGui.QPen()
        brush = QtGui.QBrush( QtCore.Qt.darkCyan, QtCore.Qt.Dense7Pattern)
        painter = QtGui.QPainter(self)
        painter.setBrush(brush)
        painter.setPen(pen)
        painter.setRenderHint(QtGui.QPainter.Antialiasing)

        self.e.moveCenter(self.rect().center())
        self.l1.translate(self.rect().center() - self.l1.p1())
        self.l2.translate(self.rect().center() - self.l2.p1())

        self.al.translate(self.l1.p2())
        self.a2.translate(self.l1.p2())

        painter.translate(self.rect().center())
        painter.scale(self._factor, self._factor)
        painter.translate(-self.rect().center())

        painter.drawEllipse(self.e)
        painter.drawLine(self.l1)
        painter.drawLine(self.l2)

        fnt = painter.font() 
        fnt.setPointSize(20) 
        painter.setFont(fnt) 
        h = QtGui.QFontMetrics(painter.font()).height() 
        p = QtCore.QPoint(self.rect().center().x(), self.e.top() - 3*h) 
        u = QtCore.QPoint(self.e.right() + 3*h, self.rect().center().y()) 
        painter.drawText(p, "y")
        painter.drawText(u, "x")

        r = QtCore.QRect(QtCore.QPoint(self.e.x(), self.e.bottom()), QtCore.QSize(self.e.width(), h)) 
        painter.drawText(r, QtCore.Qt.AlignCenter, "D = 350mm")
        offset = QtCore.QPoint(0, 1.5*h)

        self.vl.translate(self.e.bottomLeft() - self.vl.p1() + offset)
        painter.drawLine(self.vl)
        self.vl.translate(self.e.width(), 0)
        painter.drawLine(self.vl)
        self.hl.translate(self.e.bottomLeft() +  offset - QtCore.QPoint(0, 0.4*h))

        self.a3.translate(self.l2.p2())
        self.a4.translate(self.l2.p2())

        painter.drawLine(self.hl)
        painter.drawLine(self.al)
        painter.drawLine(self.a2)
        painter.drawLine(self.a3)
        painter.drawLine(self.a4)       


    def wheelEvent(self, event):
        self._factor *= 1.01**(event.angleDelta().y()/15.0)
        self.update()
        super(Paint, self).wheelEvent(event)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    w = Foo()
    w.show()
    sys.exit(app.exec_())

我不知道它为什么会这样?任何评论或帮助我都非常感谢。

【问题讨论】:

    标签: python python-3.x pyqt pyqt5 qpainter


    【解决方案1】:

    Qt 不知道小部件在开始时的大小,因此self.rect() 将具有任何大小,例如在我的测试中self.rect()__init__ 返回PyQt5.QtCore.QRect(0, 0, 640, 480) 但在paintEvent() 它返回@987654330 @所以这就是计算不正确的原因。

    解决方案是用translate()移动线(不要使用translated(),因为这会创建一个新的QLine,这就是我不想要的)

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Foo(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Foo, self).__init__(parent)
            self.setGeometry(QtCore.QRect(200, 100, 700, 600))        
            self.paint = Paint()
            self.sizeHint()
            self.lay = QtWidgets.QVBoxLayout()
            self.lay.addWidget(self.paint)
            self.setLayout(self.lay)
    
    class Paint(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Paint, self).__init__(parent)
            self.setBackgroundRole(QtGui.QPalette.Base)     
            self.setAutoFillBackground(True)
    
            self.e = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(250, 250))
            self.l1 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(200, 0))
            self.l2 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(0, -200))
    
        def paintEvent(self, event):
            pen = QtGui.QPen()
            brush = QtGui.QBrush( QtCore.Qt.darkCyan, QtCore.Qt.Dense7Pattern)
            painter = QtGui.QPainter(self)
            painter.setBrush(brush)
            painter.setPen(pen)
            painter.setRenderHint(QtGui.QPainter.Antialiasing)
    
            self.e.moveCenter(self.rect().center())
            self.l1.translate(self.rect().center() - self.l1.p1())
            self.l2.translate(self.rect().center() - self.l2.p1())
            painter.drawEllipse(self.e)
            painter.drawLine(self.l1)
            painter.drawLine(self.l2)
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        w = Foo()
        w.show()
        sys.exit(app.exec_())
    

    更新:

    class Paint(QtWidgets.QWidget):
        def __init__(self, parent=None):
            super(Paint, self).__init__(parent)
            self.setBackgroundRole(QtGui.QPalette.Base)     
            self.setAutoFillBackground(True)
    
            self.e = QtCore.QRect(QtCore.QPoint(), QtCore.QSize(250, 250))
            self.l1 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(200, 0))
            self.l2 = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(0, -200))
    
            self.vl = QtCore.QLine(QtCore.QPoint(), QtCore.QPoint(0, -125))
            delta = QtCore.QPoint(20, 0)
            self.hl = QtCore.QLine(-delta, self.e.topRight() + delta)
    
        def paintEvent(self, event):
            pen = QtGui.QPen()
            brush = QtGui.QBrush( QtCore.Qt.darkCyan, QtCore.Qt.Dense7Pattern)
            painter = QtGui.QPainter(self)
            painter.setBrush(brush)
            painter.setPen(pen)
            painter.setRenderHint(QtGui.QPainter.Antialiasing)
    
            self.e.moveCenter(self.rect().center())
            self.l1.translate(self.rect().center() - self.l1.p1())
            self.l2.translate(self.rect().center() - self.l2.p1())
    
            painter.drawEllipse(self.e)
            painter.drawLine(self.l1)
            painter.drawLine(self.l2)
    
            fnt = painter.font() 
            fnt.setPointSize(25) 
            painter.setFont(fnt) 
            h = QtGui.QFontMetrics(painter.font()).height() 
            p = QtCore.QPoint(self.rect().center().x(), self.e.bottom() + 0.8*h)
    
            r = QtCore.QRect(QtCore.QPoint(self.e.x(), self.e.bottom()), QtCore.QSize(self.e.width(), h)) 
            painter.drawText(r, QtCore.Qt.AlignCenter, "D")
            offset = QtCore.QPoint(0, 1.5*h)
    
            self.vl.translate(self.e.bottomLeft() - self.vl.p1() + offset)
            painter.drawLine(self.vl)
            self.vl.translate(self.e.width(), 0)
            painter.drawLine(self.vl)
            self.hl.translate(self.e.bottomLeft() +  offset - QtCore.QPoint(0, 20))
            painter.drawLine(self.hl)
    

    【讨论】:

    • 非常感谢,现在它可以工作了,你是对的。但是我可以对文本使用相同的方法吗?
    • @ZarKha 使用fnt = painter.font() fnt.setPointSize(25) painter.setFont(fnt) h = QtGui.QFontMetrics(painter.font()).height() p = QtCore.QPoint(self.rect().center().x(), self.e.bottom() + h) painter.drawText(p, "D")
    • 我不这么认为,有可能在线的 p2() 处绘制箭头。箭头是Qt预定义的还是应该通过其他方式完成
    • @ZarKha 你必须创建它,它是一个简单的三角形
    • 我设法绘制了尺寸线。此代码根据self.rect().center() 用于左垂直线。 self.l3.translate(QtCore.QPoint(self.rect().center().x()-250/2 , self.e.left())) 有没有更好或更快的方法去这些坐标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    相关资源
    最近更新 更多