绘画师在另一个矩形内绘制圆角矩形

2024-04-20 15:06:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我想解释一下我想达到的目标是什么,还有什么可能不起作用。当用户绘制矩形或圆形时,要绘制圆形内的环和矩形内边为圆形的矩形环。到目前为止,我已经实现了我的代码。。。如下所示

enter image description here

enter image description here

如上图所示,应该从外矩形中减去内矩形。边缘应该是圆的。你知道吗

我想要达到的和圆形形状相似

enter image description here

enter image description here

代码:

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._pos = QtCore.QPointF()
        self._initial_flag = False
        fnt = self.font() 
        fnt.setPointSize(20) 
        self.setFont(fnt) 

        print(self._size, self._rect, self._type, self._pos)

    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, yb = 25, 25, 8
        self._path = QtGui.QPainterPath()
        self._size = QtCore.QSizeF(w, h)
        self._sizeouter = QtCore.QSizeF(w-cb, h-ct)
        self._sizeinner = QtCore.QSizeF(w-cb-yb, h-ct-yb)
        self._type = QtGui.QRegion.Rectangle
        self.updatePath()

        print(self._size, self._rect, self._type, self._pos)

    @QtCore.pyqtSlot(int)
    def set_size_round(self, v):
        cb, yb = 25, 8
        self._path = QtGui.QPainterPath()
        self._size = QtCore.QSizeF(v, v)
        self._sizeouter = QtCore.QSizeF(v-cb, v-cb)
        self._sizeinner = QtCore.QSizeF(v-cb-yb, v-cb-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)
        if self._type == QtGui.QRegion.Rectangle:
            painter.fillRect(self._rectouter, QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
            painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
            painter.drawRect(self._rectouter)
            painter.fillRect(self._rect, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
            painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
            painter.drawRect(self._rect)
            painter.fillRect(self._rectinner, QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
            painter.setBrush(QtGui.QBrush(QtCore.Qt.NoBrush))
            painter.drawRect(self._rectinner)
        elif self._type == QtGui.QRegion.Ellipse:
            painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
            painter.drawEllipse(self._rect)
            painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.SolidPattern))
            painter.drawEllipse(self._rectouter)
            painter.setBrush(QtGui.QBrush(QtCore.Qt.gray, QtCore.Qt.Dense7Pattern))
            painter.drawEllipse(self._rectinner)

    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.update()
        self._initial_pos = event.pos()
        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        QtWidgets.QApplication.restoreOverrideCursor()
        super().mouseReleaseEvent(event)

    def updatePath(self):
        fm = QtGui.QFontMetrics(self.font())
        r = QtCore.QRectF(QtCore.QPointF(), self._size)
        ro = QtCore.QRectF(QtCore.QPointF(), self._sizeouter)
        ri = QtCore.QRectF(QtCore.QPointF(), self._sizeinner)
        r.moveCenter(QtCore.QPointF())
        ro.moveCenter(QtCore.QPointF())
        ri.moveCenter(QtCore.QPointF())
        r.moveCenter(QtCore.QPointF())

        self._rectouter = QtCore.QRectF(ro)
        self._rectinner = QtCore.QRectF(ri)
        self._rect = QtCore.QRectF(r)
        self._path.moveTo(QtCore.QPointF())
        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_())

Tags: posrectselfeventsizedefqtpainter
1条回答
网友
1楼 · 发布于 2024-04-20 15:06:54

对于这些情况,最好使用QPainterPathStroker并传递给它一个QPainterPath,我有一个带addRoundedRect()的圆形矩形:

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, 20, 20)

    elif self._type == QtGui.QRegion.Ellipse:
        painter.drawEllipse(self._rect)
        path.addEllipse(r)

    stroker = QtGui.QPainterPathStroker()
    stroker.setWidth(s.width())
    stroke_path = stroker.createStroke(path)
    # painter.setPen(QtCore.Qt.NoPen)
    painter.setBrush(QtGui.QBrush(QtCore.Qt.cyan, QtCore.Qt.SolidPattern))
    painter.drawPath(stroke_path)

enter image description here

enter image description here

相关问题 更多 >