QPainterPath 沿多个路径绘制和放置项目
QPainterPath drawing and placering items along multiple paths
我从以前的代码行开发并添加了一些特殊行为。思路是在矩形和圆形内部的一定路径上绘制小圆圈,并按照预先给定的距离放置。
我想根据用户给定的距离以编程方式自动绘制。 IE。距离和数量会有所不同。
我自己看了这个练习,并试图用非常复杂的 for 循环和长代码行来解决这个问题。我害怕在这里重复相同的过程。
我想达到的效果:
在矩形的情况下,圆的大小由下式给出:
self._rebar = QtCore.QSizeF(yb, yb)
每个圆从顶部到圆心的垂直距离由下式给出:
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis = h-cb-ys-yb/2, ct+ys+yt/2
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
认为下一个输入会增加或减少钢筋的数量,从而减少或增加距离值。我将能够有条不紊地绘制它们。
输入圆形。
cb, ys, yb = 25, 8, 12
self.As = [yb, yb, yb, yb, yb, yb, yb]
self._rebar = QtCore.QSizeF(yb, yb)
如果是圆,有没有办法绘制并沿着圆形路径放置圆弧角的圆?我的意思是,我认为最简单的方法是先测量钢筋数量,然后用弧角和长度测量距离,然后再按顺序放置和组织它们,无论项目的圆数是多少!
我很欣赏任何简单而聪明的方法来解决这个问题并避免冗长的编码。
矩形解释:
据您所知,列表 self.db = [di, di, di, di+25, di+25, di+25]
将传递给来自另一个 class 的函数,后者已经计算出一层中有多少个圆圈,即。例如,self.db = [200, 200, 180, 180]
表示一层只有 2 个圆圈,另一层有 2 个圆圈。所以 beff
第一层只包含 2 个圆圈。在那种情况下需要找出如何按顺序和定期放置它们。
我更正了这行代码self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
图层
代码:
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, 800, 800))
self.button = Button()
self.paint = Createpaintwidget()
self.button.valuesChanged.connect(self.paint.set_size_squares)
self.button.valueChanged.connect(self.paint.set_size_round)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = QtGui.QRegion.Rectangle
self._factor = 1.0
self._sizeouter = QtCore.QSizeF()
self._rectouter = QtCore.QRectF()
self._sizeinner = QtCore.QSizeF()
self._rectinner = QtCore.QRectF()
self._rebar = QtCore.QSizeF()
self._rectrebar = QtCore.QRectF()
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis, ccb, cct = h-cb-ys-yb/2, ct+ys+yt/2, cb+ys+0.5*yb, ct+ys+0.5*yt
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
beff_b, beff_t = w - 2*ccb, w - 2*cct
db_d = dict(set((x,self.db.count(x)) for x in filter(lambda rec : self.db.count(rec)>1,self.db)))
db_l = [k for k in dict.values(db_d)]
dt_d = dict(set((x,self.dt.count(x)) for x in filter(lambda rec : self.dt.count(rec)>1,self.dt)))
dt_l = [k for k in dict.values(dt_d)]
xb, xt = [beff_b/(k-1) for k in db_l], [beff_t/(k-1) for k in dt_l]
self.dbx, self.dtx = [], []
start = 0
for k, b in enumerate(db_l):
sub_A = self.db[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dbx.append(ccb+i*xb[k])
start = 0
for k, b in enumerate(dt_l):
sub_A = self.dt[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dtx.append(cct+i*xt[k])
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(w, h)
self._sizeouter = QtCore.QSizeF(w-cb, h-ct)
self._sizeinner = QtCore.QSizeF(w-cb-ys, h-ct-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
cb, ys, yb = 25, 8, 12
self.As = [yb, yb, yb, yb, yb, yb, yb]
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(v, v)
self._sizeouter = QtCore.QSizeF(v-cb, v-cb)
self._sizeinner = QtCore.QSizeF(v-cb-ys, v-cb-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
S = (self._rectouter.size() + self._rectinner.size())/2
s = (self._rectouter.size() - self._rectinner.size())/2
r = QtCore.QRectF(QtCore.QPointF(), S)
r.moveCenter(self._rectouter.center())
path = QtGui.QPainterPath()
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
if self._type == QtGui.QRegion.Rectangle:
painter.drawRect(self._rect)
path.addRoundedRect(r, 10, 10)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawEllipse(self._rectrebar)
elif self._type == QtGui.QRegion.Ellipse:
painter.drawEllipse(self._rect)
path.addEllipse(r)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawEllipse(self._rectrebar)
stroker = QtGui.QPainterPathStroker()
stroker.setWidth(s.width())
stroke_path = stroker.createStroke(path)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawPath(stroke_path)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self._rectinner.translate(delta)
self._rectouter.translate(delta)
self._rectrebar.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
r = QtCore.QRectF(QtCore.QPointF(), self._size)
ro = QtCore.QRectF(QtCore.QPointF(), self._sizeouter)
ri = QtCore.QRectF(QtCore.QPointF(), self._sizeinner)
rr = QtCore.QRectF(QtCore.QPointF(), self._rebar)
r.moveCenter(QtCore.QPointF())
ro.moveCenter(QtCore.QPointF())
ri.moveCenter(QtCore.QPointF())
rr.moveCenter(QtCore.QPointF())
self._rectouter = QtCore.QRectF(ro)
self._rectinner = QtCore.QRectF(ri)
self._rect = QtCore.QRectF(r)
self._rectrebar = QtCore.QRectF(rr)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
valuesChanged = QtCore.pyqtSignal(int,int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
roundbutton = QtWidgets.QPushButton('Round')
squarebutton = QtWidgets.QPushButton('Square')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(roundbutton)
Alay.addWidget(squarebutton)
self.value = QtWidgets.QLabel()
roundbutton.clicked.connect(self.getbuttonfunc)
squarebutton.clicked.connect(self.sqaurebuttonfunc)
@QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
@QtCore.pyqtSlot()
def sqaurebuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valuesChanged.emit(number, number)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
更新码:
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis, ccb, cct = h-cb-ys-yb/2, ct+ys+yt/2, cb+ys+0.5*yb, ct+ys+0.5*yt
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
beff_b, beff_t = w - 2*ccb, w - 2*cct
db_d = dict(set((x,self.db.count(x)) for x in filter(lambda rec : self.db.count(rec)>1,self.db)))
db_l = [k for k in dict.values(db_d)]
dt_d = dict(set((x,self.dt.count(x)) for x in filter(lambda rec : self.dt.count(rec)>1,self.dt)))
dt_l = [k for k in dict.values(dt_d)]
xb, xt = [beff_b/(k-1) for k in db_l], [beff_t/(k-1) for k in dt_l]
self.dbx, self.dtx = [], []
start = 0
for k, b in enumerate(db_l):
sub_A = self.db[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dbx.append(ccb+i*xb[k])
start = 0
for k, b in enumerate(dt_l):
sub_A = self.dt[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dtx.append(cct+i*xt[k])
----------
底部圆的 y 坐标和列表中给出的相应 x 坐标:
self.dbx = [x2,x3,x1,x5,x6,x4]
self.db = [y2, y3, y1, y5, y6, y4]
顶部圆的 y 坐标和对应的 x 坐标在列表中给出:
self.dtx = [x2,x3,x1,x5,x4]
self.dt = [y2, y3, y1, y5, y4]
考虑到您提供的关于矩形左上角的位置列表,结果如下:
import math
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, 800, 800))
self.button = Button()
self.paint = Createpaintwidget()
self.button.valuesChanged.connect(self.paint.set_size_squares)
self.button.valueChanged.connect(self.paint.set_size_round)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = None
self._factor = 1.0
self._sizeouter = QtCore.QSizeF()
self._rectouter = QtCore.QRectF()
self._sizeinner = QtCore.QSizeF()
self._rectinner = QtCore.QRectF()
self._rebar = QtCore.QSizeF()
self._rectrebar = QtCore.QRectF()
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis, ccb, cct = h-cb-ys-yb/2, ct+ys+yt/2, cb+ys+0.5*yb, ct+ys+0.5*yt
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
beff_b, beff_t = w - 2*ccb, w - 2*cct
db_d = dict(set((x,self.db.count(x)) for x in filter(lambda rec : self.db.count(rec)>1,self.db)))
db_l = [k for k in dict.values(db_d)]
dt_d = dict(set((x,self.dt.count(x)) for x in filter(lambda rec : self.dt.count(rec)>1,self.dt)))
dt_l = [k for k in dict.values(dt_d)]
xb, xt = [beff_b/(k-1) for k in db_l], [beff_t/(k-1) for k in dt_l]
self.dbx, self.dtx = [], []
start = 0
for k, b in enumerate(db_l):
sub_A = self.db[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dbx.append(ccb+i*xb[k])
start = 0
for k, b in enumerate(dt_l):
sub_A = self.dt[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dtx.append(cct+i*xt[k])
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(w, h)
self._sizeouter = QtCore.QSizeF(w-cb, h-ct)
self._sizeinner = QtCore.QSizeF(w-cb-ys, h-ct-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
cb, ys, yb = 25, 8, 12
self.As = [yb, yb, yb, yb, yb, yb, yb]
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(v, v)
self._sizeouter = QtCore.QSizeF(v-cb, v-cb)
self._sizeinner = QtCore.QSizeF(v-cb-ys, v-cb-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
S = (self._rectouter.size() + self._rectinner.size())/2
s = (self._rectouter.size() - self._rectinner.size())/2
r = QtCore.QRectF(QtCore.QPointF(), S)
r.moveCenter(self._rectouter.center())
path = QtGui.QPainterPath()
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
if self._type == QtGui.QRegion.Rectangle:
painter.drawRect(self._rect)
path.addRoundedRect(r, 10, 10)
_r = QtCore.QRectF(self._rectrebar)
for x, y in zip(self.dtx + self.dbx , self.dt + self.db):
_r.moveCenter(QtCore.QPointF(x, y) + self._rect.topLeft())
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawEllipse(_r)
elif self._type == QtGui.QRegion.Ellipse:
painter.drawEllipse(self._rect)
path.addEllipse(r)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
n = 7
for i, _ in enumerate(self.As):
angle = (i*2.0/n + 1)*math.pi
radius = .5 *(r.width() - s.width() - self._rectrebar.width())
dx = radius*QtCore.QPointF(math.cos(angle), math.sin(angle))
r_ = QtCore.QRectF(self._rectrebar)
r_.translate(dx)
painter.drawEllipse(r_)
stroker = QtGui.QPainterPathStroker()
stroker.setWidth(s.width())
stroke_path = stroker.createStroke(path)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawPath(stroke_path)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self._rectinner.translate(delta)
self._rectouter.translate(delta)
self._rectrebar.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
r = QtCore.QRectF(QtCore.QPointF(), self._size)
ro = QtCore.QRectF(QtCore.QPointF(), self._sizeouter)
ri = QtCore.QRectF(QtCore.QPointF(), self._sizeinner)
rr = QtCore.QRectF(QtCore.QPointF(), self._rebar)
r.moveCenter(QtCore.QPointF())
ro.moveCenter(QtCore.QPointF())
ri.moveCenter(QtCore.QPointF())
rr.moveCenter(QtCore.QPointF())
self._rectouter = QtCore.QRectF(ro)
self._rectinner = QtCore.QRectF(ri)
self._rect = QtCore.QRectF(r)
self._rectrebar = QtCore.QRectF(rr)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
valuesChanged = QtCore.pyqtSignal(int,int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
roundbutton = QtWidgets.QPushButton('Round')
squarebutton = QtWidgets.QPushButton('Square')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(roundbutton)
Alay.addWidget(squarebutton)
self.value = QtWidgets.QLabel()
roundbutton.clicked.connect(self.getbuttonfunc)
squarebutton.clicked.connect(self.sqaurebuttonfunc)
@QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
@QtCore.pyqtSlot()
def sqaurebuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valuesChanged.emit(number, number)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
我从以前的代码行开发并添加了一些特殊行为。思路是在矩形和圆形内部的一定路径上绘制小圆圈,并按照预先给定的距离放置。 我想根据用户给定的距离以编程方式自动绘制。 IE。距离和数量会有所不同。
我自己看了这个练习,并试图用非常复杂的 for 循环和长代码行来解决这个问题。我害怕在这里重复相同的过程。
我想达到的效果:
在矩形的情况下,圆的大小由下式给出:
self._rebar = QtCore.QSizeF(yb, yb)
每个圆从顶部到圆心的垂直距离由下式给出:
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis = h-cb-ys-yb/2, ct+ys+yt/2
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
认为下一个输入会增加或减少钢筋的数量,从而减少或增加距离值。我将能够有条不紊地绘制它们。
输入圆形。
cb, ys, yb = 25, 8, 12
self.As = [yb, yb, yb, yb, yb, yb, yb]
self._rebar = QtCore.QSizeF(yb, yb)
如果是圆,有没有办法绘制并沿着圆形路径放置圆弧角的圆?我的意思是,我认为最简单的方法是先测量钢筋数量,然后用弧角和长度测量距离,然后再按顺序放置和组织它们,无论项目的圆数是多少!
我很欣赏任何简单而聪明的方法来解决这个问题并避免冗长的编码。
矩形解释:
据您所知,列表 self.db = [di, di, di, di+25, di+25, di+25]
将传递给来自另一个 class 的函数,后者已经计算出一层中有多少个圆圈,即。例如,self.db = [200, 200, 180, 180]
表示一层只有 2 个圆圈,另一层有 2 个圆圈。所以 beff
第一层只包含 2 个圆圈。在那种情况下需要找出如何按顺序和定期放置它们。
我更正了这行代码self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
图层
代码:
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, 800, 800))
self.button = Button()
self.paint = Createpaintwidget()
self.button.valuesChanged.connect(self.paint.set_size_squares)
self.button.valueChanged.connect(self.paint.set_size_round)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = QtGui.QRegion.Rectangle
self._factor = 1.0
self._sizeouter = QtCore.QSizeF()
self._rectouter = QtCore.QRectF()
self._sizeinner = QtCore.QSizeF()
self._rectinner = QtCore.QRectF()
self._rebar = QtCore.QSizeF()
self._rectrebar = QtCore.QRectF()
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis, ccb, cct = h-cb-ys-yb/2, ct+ys+yt/2, cb+ys+0.5*yb, ct+ys+0.5*yt
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
beff_b, beff_t = w - 2*ccb, w - 2*cct
db_d = dict(set((x,self.db.count(x)) for x in filter(lambda rec : self.db.count(rec)>1,self.db)))
db_l = [k for k in dict.values(db_d)]
dt_d = dict(set((x,self.dt.count(x)) for x in filter(lambda rec : self.dt.count(rec)>1,self.dt)))
dt_l = [k for k in dict.values(dt_d)]
xb, xt = [beff_b/(k-1) for k in db_l], [beff_t/(k-1) for k in dt_l]
self.dbx, self.dtx = [], []
start = 0
for k, b in enumerate(db_l):
sub_A = self.db[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dbx.append(ccb+i*xb[k])
start = 0
for k, b in enumerate(dt_l):
sub_A = self.dt[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dtx.append(cct+i*xt[k])
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(w, h)
self._sizeouter = QtCore.QSizeF(w-cb, h-ct)
self._sizeinner = QtCore.QSizeF(w-cb-ys, h-ct-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
cb, ys, yb = 25, 8, 12
self.As = [yb, yb, yb, yb, yb, yb, yb]
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(v, v)
self._sizeouter = QtCore.QSizeF(v-cb, v-cb)
self._sizeinner = QtCore.QSizeF(v-cb-ys, v-cb-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
S = (self._rectouter.size() + self._rectinner.size())/2
s = (self._rectouter.size() - self._rectinner.size())/2
r = QtCore.QRectF(QtCore.QPointF(), S)
r.moveCenter(self._rectouter.center())
path = QtGui.QPainterPath()
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
if self._type == QtGui.QRegion.Rectangle:
painter.drawRect(self._rect)
path.addRoundedRect(r, 10, 10)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawEllipse(self._rectrebar)
elif self._type == QtGui.QRegion.Ellipse:
painter.drawEllipse(self._rect)
path.addEllipse(r)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawEllipse(self._rectrebar)
stroker = QtGui.QPainterPathStroker()
stroker.setWidth(s.width())
stroke_path = stroker.createStroke(path)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawPath(stroke_path)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self._rectinner.translate(delta)
self._rectouter.translate(delta)
self._rectrebar.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
r = QtCore.QRectF(QtCore.QPointF(), self._size)
ro = QtCore.QRectF(QtCore.QPointF(), self._sizeouter)
ri = QtCore.QRectF(QtCore.QPointF(), self._sizeinner)
rr = QtCore.QRectF(QtCore.QPointF(), self._rebar)
r.moveCenter(QtCore.QPointF())
ro.moveCenter(QtCore.QPointF())
ri.moveCenter(QtCore.QPointF())
rr.moveCenter(QtCore.QPointF())
self._rectouter = QtCore.QRectF(ro)
self._rectinner = QtCore.QRectF(ri)
self._rect = QtCore.QRectF(r)
self._rectrebar = QtCore.QRectF(rr)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
valuesChanged = QtCore.pyqtSignal(int,int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
roundbutton = QtWidgets.QPushButton('Round')
squarebutton = QtWidgets.QPushButton('Square')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(roundbutton)
Alay.addWidget(squarebutton)
self.value = QtWidgets.QLabel()
roundbutton.clicked.connect(self.getbuttonfunc)
squarebutton.clicked.connect(self.sqaurebuttonfunc)
@QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
@QtCore.pyqtSlot()
def sqaurebuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valuesChanged.emit(number, number)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())
更新码:
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis, ccb, cct = h-cb-ys-yb/2, ct+ys+yt/2, cb+ys+0.5*yb, ct+ys+0.5*yt
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
beff_b, beff_t = w - 2*ccb, w - 2*cct
db_d = dict(set((x,self.db.count(x)) for x in filter(lambda rec : self.db.count(rec)>1,self.db)))
db_l = [k for k in dict.values(db_d)]
dt_d = dict(set((x,self.dt.count(x)) for x in filter(lambda rec : self.dt.count(rec)>1,self.dt)))
dt_l = [k for k in dict.values(dt_d)]
xb, xt = [beff_b/(k-1) for k in db_l], [beff_t/(k-1) for k in dt_l]
self.dbx, self.dtx = [], []
start = 0
for k, b in enumerate(db_l):
sub_A = self.db[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dbx.append(ccb+i*xb[k])
start = 0
for k, b in enumerate(dt_l):
sub_A = self.dt[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dtx.append(cct+i*xt[k])
----------
底部圆的 y 坐标和列表中给出的相应 x 坐标:
self.dbx = [x2,x3,x1,x5,x6,x4]
self.db = [y2, y3, y1, y5, y6, y4]
顶部圆的 y 坐标和对应的 x 坐标在列表中给出:
self.dtx = [x2,x3,x1,x5,x4]
self.dt = [y2, y3, y1, y5, y4]
考虑到您提供的关于矩形左上角的位置列表,结果如下:
import math
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, 800, 800))
self.button = Button()
self.paint = Createpaintwidget()
self.button.valuesChanged.connect(self.paint.set_size_squares)
self.button.valueChanged.connect(self.paint.set_size_round)
self.lay = QtWidgets.QVBoxLayout(self)
self.lay.addWidget(self.paint)
self.lay.addWidget(self.button)
class Createpaintwidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.sizeHint()
self.setBackgroundRole(QtGui.QPalette.Base)
self.setAutoFillBackground(True)
self._size = QtCore.QSizeF()
self._path = QtGui.QPainterPath()
self._rect = QtCore.QRectF()
self._type = None
self._factor = 1.0
self._sizeouter = QtCore.QSizeF()
self._rectouter = QtCore.QRectF()
self._sizeinner = QtCore.QSizeF()
self._rectinner = QtCore.QRectF()
self._rebar = QtCore.QSizeF()
self._rectrebar = QtCore.QRectF()
self._pos = QtCore.QPointF()
self._initial_flag = False
fnt = self.font()
fnt.setPointSize(20)
self.setFont(fnt)
def showEvent(self, event):
if not self._initial_flag:
self._pos = self.rect().center()
self._initial_flag = True
@QtCore.pyqtSlot(int, int)
def set_size_squares(self, w, h):
cb, ct, ys, yb, yt = 25, 25, 8, 12, 12
di, dis, ccb, cct = h-cb-ys-yb/2, ct+ys+yt/2, cb+ys+0.5*yb, ct+ys+0.5*yt
self.db, self.dt = [di, di, di, di-25, di-25, di-25], [dis, dis, dis, dis+25, dis+25]
beff_b, beff_t = w - 2*ccb, w - 2*cct
db_d = dict(set((x,self.db.count(x)) for x in filter(lambda rec : self.db.count(rec)>1,self.db)))
db_l = [k for k in dict.values(db_d)]
dt_d = dict(set((x,self.dt.count(x)) for x in filter(lambda rec : self.dt.count(rec)>1,self.dt)))
dt_l = [k for k in dict.values(dt_d)]
xb, xt = [beff_b/(k-1) for k in db_l], [beff_t/(k-1) for k in dt_l]
self.dbx, self.dtx = [], []
start = 0
for k, b in enumerate(db_l):
sub_A = self.db[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dbx.append(ccb+i*xb[k])
start = 0
for k, b in enumerate(dt_l):
sub_A = self.dt[start:start+b]
start = start+b
for i, _ in enumerate(sub_A):
self.dtx.append(cct+i*xt[k])
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(w, h)
self._sizeouter = QtCore.QSizeF(w-cb, h-ct)
self._sizeinner = QtCore.QSizeF(w-cb-ys, h-ct-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Rectangle
self.updatePath()
@QtCore.pyqtSlot(int)
def set_size_round(self, v):
cb, ys, yb = 25, 8, 12
self.As = [yb, yb, yb, yb, yb, yb, yb]
self._path = QtGui.QPainterPath()
self._size = QtCore.QSizeF(v, v)
self._sizeouter = QtCore.QSizeF(v-cb, v-cb)
self._sizeinner = QtCore.QSizeF(v-cb-ys, v-cb-ys)
self._rebar = QtCore.QSizeF(yb, yb)
self._type = QtGui.QRegion.Ellipse
self.updatePath()
def paintEvent(self, event):
pen = QtGui.QPen()
brush = QtGui.QBrush(QtCore.Qt.black)
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setPen(pen)
painter.setBrush(brush)
painter.translate(self.rect().center())
painter.scale(self._factor, self._factor)
painter.translate(-self.rect().center())
painter.translate(self._pos)
painter.drawPath(self._path)
S = (self._rectouter.size() + self._rectinner.size())/2
s = (self._rectouter.size() - self._rectinner.size())/2
r = QtCore.QRectF(QtCore.QPointF(), S)
r.moveCenter(self._rectouter.center())
path = QtGui.QPainterPath()
painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
if self._type == QtGui.QRegion.Rectangle:
painter.drawRect(self._rect)
path.addRoundedRect(r, 10, 10)
_r = QtCore.QRectF(self._rectrebar)
for x, y in zip(self.dtx + self.dbx , self.dt + self.db):
_r.moveCenter(QtCore.QPointF(x, y) + self._rect.topLeft())
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawEllipse(_r)
elif self._type == QtGui.QRegion.Ellipse:
painter.drawEllipse(self._rect)
path.addEllipse(r)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
n = 7
for i, _ in enumerate(self.As):
angle = (i*2.0/n + 1)*math.pi
radius = .5 *(r.width() - s.width() - self._rectrebar.width())
dx = radius*QtCore.QPointF(math.cos(angle), math.sin(angle))
r_ = QtCore.QRectF(self._rectrebar)
r_.translate(dx)
painter.drawEllipse(r_)
stroker = QtGui.QPainterPathStroker()
stroker.setWidth(s.width())
stroke_path = stroker.createStroke(path)
painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
painter.drawPath(stroke_path)
def mousePressEvent(self, event):
QtWidgets.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))
self._initial_pos = event.pos()
super().mousePressEvent(event)
def mouseMoveEvent(self, event):
delta = event.pos() - self._initial_pos
self._path.translate(delta)
self._rect.translate(delta)
self._rectinner.translate(delta)
self._rectouter.translate(delta)
self._rectrebar.translate(delta)
self.update()
self._initial_pos = event.pos()
super().mouseMoveEvent(event)
def mouseReleaseEvent(self, event):
QtWidgets.QApplication.restoreOverrideCursor()
super().mouseReleaseEvent(event)
def updatePath(self):
r = QtCore.QRectF(QtCore.QPointF(), self._size)
ro = QtCore.QRectF(QtCore.QPointF(), self._sizeouter)
ri = QtCore.QRectF(QtCore.QPointF(), self._sizeinner)
rr = QtCore.QRectF(QtCore.QPointF(), self._rebar)
r.moveCenter(QtCore.QPointF())
ro.moveCenter(QtCore.QPointF())
ri.moveCenter(QtCore.QPointF())
rr.moveCenter(QtCore.QPointF())
self._rectouter = QtCore.QRectF(ro)
self._rectinner = QtCore.QRectF(ri)
self._rect = QtCore.QRectF(r)
self._rectrebar = QtCore.QRectF(rr)
self.update()
def wheelEvent(self, event):
self._factor *= 1.01**(event.angleDelta().y()/15.0)
self.update()
super().wheelEvent(event)
class Button(QtWidgets.QWidget):
valueChanged = QtCore.pyqtSignal(int)
valuesChanged = QtCore.pyqtSignal(int,int)
def __init__(self, parent=None):
super(Button, self).__init__(parent)
roundbutton = QtWidgets.QPushButton('Round')
squarebutton = QtWidgets.QPushButton('Square')
Alay = QtWidgets.QVBoxLayout(self)
Alay.addWidget(roundbutton)
Alay.addWidget(squarebutton)
self.value = QtWidgets.QLabel()
roundbutton.clicked.connect(self.getbuttonfunc)
squarebutton.clicked.connect(self.sqaurebuttonfunc)
@QtCore.pyqtSlot()
def getbuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valueChanged.emit(number)
@QtCore.pyqtSlot()
def sqaurebuttonfunc(self):
number, ok = QtWidgets.QInputDialog.getInt(self, self.tr("Set Number"),
self.tr("Input:"), 1, 1)
if ok:
self.valuesChanged.emit(number, number)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = Foo()
w.show()
sys.exit(app.exec_())