【问题标题】:QGraphicsEllipseItem paint event being clippedQGraphicsEllipseItem 绘制事件被裁剪
【发布时间】:2018-10-02 16:35:44
【问题描述】:

我有两个问题。

  1. 当我绘制椭圆时,在悬停事件期间,椭圆的边缘似乎没有被绘制成白色。当点是常规大小和悬停在上面时,我该如何解决这个问题?
  2. 当用户将鼠标悬停在点上时,我希望点的半径增加 2,但是当我这样做时,它当前不会从点的中心缩放。如何根据点的中心点进行调整以增加其大小?

import sys
from PySide.QtGui import *
from PySide.QtCore import *
import random


class MyGraphicsView(QGraphicsView):
    def __init__(self):
        super(MyGraphicsView, self).__init__()
        self.setDragMode(QGraphicsView.RubberBandDrag)
        self._isPanning = False
        self._mousePressed = False
        # self.setBackgroundBrush(QImage("C:/Users/jmartini/Desktop/Temp/images/flag_0140.jpg"))
        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff )
        self.setVerticalScrollBarPolicy( Qt.ScrollBarAlwaysOff )


    def mousePressEvent(self,  event):
        if event.button() == Qt.LeftButton:
            self._mousePressed = True
            if self._isPanning:
                self.setCursor(Qt.ClosedHandCursor)
                self._dragPos = event.pos()
                event.accept()
            else:
                super(MyGraphicsView, self).mousePressEvent(event)
        elif event.button() == Qt.MiddleButton:
            self._mousePressed = True
            self._isPanning = True
            self.setCursor(Qt.ClosedHandCursor)
            self._dragPos = event.pos()
            event.accept()


    def mouseMoveEvent(self, event):
        if self._mousePressed and self._isPanning:
            newPos = event.pos()
            diff = newPos - self._dragPos
            self._dragPos = newPos
            self.horizontalScrollBar().setValue(self.horizontalScrollBar().value() - diff.x())
            self.verticalScrollBar().setValue(self.verticalScrollBar().value() - diff.y())
            event.accept()
        else:
            super(MyGraphicsView, self).mouseMoveEvent(event)


    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            if self._isPanning:
                self.setCursor(Qt.OpenHandCursor)
            else:
                self._isPanning = False
                self.setCursor(Qt.ArrowCursor)
            self._mousePressed = False
        elif event.button() == Qt.MiddleButton:
            self._isPanning = False
            self.setCursor(Qt.ArrowCursor)
            self._mousePressed = False
        super(MyGraphicsView, self).mouseReleaseEvent(event)


    def mouseDoubleClickEvent(self, event): 
        self.fitInView(self.sceneRect(), Qt.KeepAspectRatio)
        pass


    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Space and not self._mousePressed:
            self._isPanning = True
            self.setCursor(Qt.OpenHandCursor)
        else:
            super(MyGraphicsView, self).keyPressEvent(event)


    def keyReleaseEvent(self, event):
        if event.key() == Qt.Key_Space:
            if not self._mousePressed:
                self._isPanning = False
                self.setCursor(Qt.ArrowCursor)
        else:
            super(MyGraphicsView, self).keyPressEvent(event)


    def wheelEvent(self,  event):
        # zoom factor
        factor = 1.25

        # Set Anchors
        self.setTransformationAnchor(QGraphicsView.NoAnchor)
        self.setResizeAnchor(QGraphicsView.NoAnchor)

        # Save the scene pos
        oldPos = self.mapToScene(event.pos())

        # Zoom
        if event.delta() < 0:
            factor = 1.0 / factor
        self.scale(factor, factor)

        # Get the new position
        newPos = self.mapToScene(event.pos())

        # Move scene to old position
        delta = newPos - oldPos
        self.translate(delta.x(), delta.y())


class MyGraphicsScene(QGraphicsScene):
    def __init__(self,  parent):
        super(MyGraphicsScene,  self).__init__()
        self.setBackgroundBrush(QBrush(QColor(50,50,50)))


class EllipseItem(QGraphicsEllipseItem):
    def __init__(self):
        super(EllipseItem,  self).__init__()
        self.setAcceptHoverEvents(True)
        self.hover = False

    def paint(self, painter, option, widget):
        painter.setRenderHints( QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing, True )
        painter.setBrush(QBrush(QColor(170,170,170,255)))

        if self.isSelected():
            painter.setPen(QPen(QColor(255,255,255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        else:
            painter.setPen(QPen(QColor(30,30,30), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))

        self.setRect(-16, -16, 16, 16)

        if self.hover:
            painter.setPen(QPen(QColor(255,255,255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            self.setRect(-18, -18, 18, 18)

        painter.drawEllipse(self.rect())


    def hoverEnterEvent(self, event):
        self.hover = True
        self.update()
        super(self.__class__, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        self.hover = False
        self.update()
        super(self.__class__, self).hoverEnterEvent(event)


class MyMainWindow(QMainWindow):
    def __init__(self):
        super(MyMainWindow, self).__init__()
        self.setWindowTitle("Test")
        self.resize(800,600)

        self.gv = MyGraphicsView()
        self.gv.setScene(MyGraphicsScene(self))

        lay_main = QVBoxLayout()
        lay_main.addWidget(self.gv)
        widget_main = QWidget()
        widget_main.setLayout(lay_main)
        self.setCentralWidget(widget_main)

        self.populate()


    def populate(self):
        scene = self.gv.scene()
        item = EllipseItem()
        item.setFlag( QGraphicsItem.ItemIsSelectable )
        scene.addItem(item)


def main():
    app = QApplication(sys.argv)
    ex = MyMainWindow()
    ex.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

【问题讨论】:

    标签: python pyside


    【解决方案1】:

    我不太确定您到底想要什么(也许是我的英语)。通过运行您的代码,我看到在悬停时,边缘会从盒子中剪掉,并且两个圆圈的中心不在同一点上。

    嗯,居中问题是由于在 EllipseItem 类的 paint 重载上使用了 setRect 方法。对于悬停的情况(我忽略了代码的选定项逻辑),您正在设置实际上具有不同中心的矩形。要解决此问题,您可以使用QPainter.drawEllipse(center, rx, ry)docs

    可以修复边缘问题,注意在 setRect 设置的矩形上不考虑绘制边缘,如发布 here。老实说,我不太清楚为什么较小的椭圆适合矩形而较大的椭圆不适合。

    无论如何,你可以尝试做这样的事情:

    def paint(self, painter, option, widget):
        painter.setRenderHints( QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform | QPainter.HighQualityAntialiasing, True )
        painter.setBrush(QBrush(QColor(170,170,170,255)))
    
        # if self.isSelected():
        #     painter.setPen(QPen(QColor(255,255,255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        # else:
        #     painter.setPen(QPen(QColor(30,30,30), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
    
        #self.setRect(-16, -16, 16, 16)
        center = QPointF(0,0)
        if self.hover:
            painter.setPen(QPen(QColor(255,255,255), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            # self.setRect(-10,-10, 20, 20) # this one wont fit the ellipse
            self.setRect(-11, -11, 22, 22)
            # plus 2 
            painter.drawEllipse(center, 10, 10)
        else:
            painter.setPen(QPen(QColor(30,30,30), 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))  
            self.setRect(-8, -8, 16, 16)  # but this one does
            painter.drawEllipse(center, 8, 8)
    

    显然,您可以通过多种方式将椭圆居中,上面的代码只是其中一种方式。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 2015-06-21
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      相关资源
      最近更新 更多