I would like to draw some lines with QPainter
, then move the start (x1,y1)
coordinates of lines to centerpoint
and some other lines which want to offset from center. Those lines should behave programmatically based on value of ellipse or other values. I have tried myself different ways to come around it but does not work.
To QRect
can utilize codes such as
moveCenter, moveTopLeft, etc...
But for Qline
there are not such methods. According to PyQt doc, a line can be drawn by this:
QLine(int x1, int y1, int x2, int y2)
QLine(const QPoint &p1, const QPoint &p2)
Maybe this line should be used in order to offset it. But no knowlegde to do it.
translated(const QPoint &offset)
On another hand would like to draw some texts and offset them in similar way as Qline
.
Look at figures below to see what is that I exactly want to do?
Visualisation
What I have achieved so far.
What I want to achieve.
The code:
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_())
The Update issue:
I have updated the code, I manage to draw what I want. But having another challenge. You could see on figure below.
When code runs and displays
When Widget minimizes or maximizes, some lines disappears?
The Update code:
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_())
I do not know why it behaves like this? any comment or help I appreciate much.
Qt does not know what size the widget will have at the beginning so self.rect()
will have any size, for example in my test self.rect()
in __init__
returns PyQt5.QtCore.QRect(0, 0, 640, 480)
but in paintEvent()
it returns PyQt5.QtCore.QRect(0, 0, 678, 578)
so that's why the calculation is incorrect.
the solution is to move the line with translate()
(do not use translated()
because this creates a new QLine and that's what I do not want)
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_())
Update:
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)