QPaint рисует линии со смещением - PullRequest
0 голосов
/ 30 октября 2018

Я хотел бы нарисовать несколько линий с помощью 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.

Посмотрите на цифры ниже, чтобы понять, что именно я хочу сделать?

Визуализация

Чего я достиг к настоящему моменту.

enter image description here

Чего я хочу достичь.

enter image description here

Код:

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_())

Обновление вопроса:

Я обновил код, мне удалось нарисовать то, что я хочу. Но с другой проблемой. Вы можете видеть на рисунке ниже.

Когда код запускается и отображает

enter image description here

Когда Widget сворачивается или разворачивается, некоторые строки исчезают?

enter image description here

Код обновления:

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_())

Не знаю, почему так себя ведет? Любой комментарий или помощь, я ценю много.

1 Ответ

0 голосов
/ 30 октября 2018

Qt не знает, какой размер будет иметь виджет в начале, поэтому self.rect() будет иметь любой размер, например, в моем тесте self.rect() в __init__ возвращает PyQt5.QtCore.QRect(0, 0, 640, 480), но в paintEvent() он возвращает 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_())

enter image description here

Обновление:

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)

enter image description here

...