QPaint画线偏移

QPaint draw lines with offset

我想用 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_())

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

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

解决方案是用 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)