PyQt icon indicating copy to clipboard operation
PyQt copied to clipboard

[问题] QGraphicsWidget中的图片模糊

Open richiy opened this issue 4 years ago • 5 comments

QGraphicsWidget里嵌入QWidget,且QWidget中带有图片,比如QPushButton设置了svg格式的图片,把QGraphicsWidget加入QGraphicsScene,这时候放大缩小QGraphicsview,图片会变得模糊,有什么解决方法保持图片不模糊吗

richiy avatar Jan 14 '21 02:01 richiy

这个可能是sence场景缩放类似于一个视角远近效果,可能QWidget只是被放大镜显示,svg并没有进行缩放, 可以提供下测试demo

892768447 avatar Jan 14 '21 03:01 892768447

test.zip

richiy avatar Jan 14 '21 03:01 richiy

你试试

richiy avatar Jan 14 '21 03:01 richiy

emm确实有问题。而且缩放后其实按钮的尺寸是没有改变的造成图标模糊 我只能这样测试能勉强达到效果

# -*- coding: utf-8 -*-
import math
import sys
from PyQt5.QtCore import QPointF, Qt, QRectF, QSize
from PyQt5.QtGui import QPainter, QCursor, QTransform, QIcon
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QApplication, QPushButton, QGraphicsItem


class GraphView(QGraphicsView):

    def __init__(self, parent=None):
        super(GraphView, self).__init__(parent)
        self.viewScale = 1.0
        self.scaleValue = 0

        self.viewPosInScene = QPointF(0, 0)

        self.setRenderHint(QPainter.Antialiasing, True)

    def wheelEvent(self, mouseEvent):
        if self.dragMode() == QGraphicsView.ScrollHandDrag:
            return
        angleDelta = mouseEvent.angleDelta()
        delta = angleDelta.x() + angleDelta.y()
        self.scaleValue += delta * 0.002
        self.scaleValue = max(- 2.5, min(1.5, self.scaleValue))

        oldScale = self.viewScale
        self.viewScale = math.exp(self.scaleValue)
        if self.scene():  # 通知scene
            self.scene().setScale(self.viewScale)
        scale = self.viewScale / oldScale

        mousePos = self.mapToScene(mouseEvent.pos())
        vec = self.viewPosInScene - mousePos
        self.viewPosInScene = mousePos + vec / scale
        self.resetSceneRect()

    def resetSceneRect(self):
        rect = self.rect()
        width = rect.width() / self.viewScale
        width -= max(5.0, min(100.0, 4.0 / self.viewScale))
        width = max(5.0, width)
        height = rect.height() / self.viewScale
        height -= max(5.0, min(100.0, 4.0 / self.viewScale))
        height = max(5.0, height)

        self.setSceneRect(
            QRectF(self.viewPosInScene.x() - width / 2.0, self.viewPosInScene.y() - height / 2.0, width, height))

        trans = QTransform()
        trans.scale(self.viewScale, self.viewScale)
        self.setTransform(trans)

        # 判断按钮得基础值
        if not btn.property('_baseSize'):
            # 记录基础值(很重要)
            btn.setProperty('_baseSize', btn.size())
        # 取出基础
        size = btn.property('_baseSize')
        size = QSize(size.width() * self.viewScale,
                     size.height() * self.viewScale)
        btn.resize(size)
        pixmap = CutIcon.pixmap(size.width() - 4, size.height() - 4)
        btn.setIconSize(pixmap.size())
        btn.setIcon(QIcon(pixmap))


class GraphScene(QGraphicsScene):
    def setScale(self, scale):
        for item in self.items():
            if hasattr(item, "onViewScale"):
                item.onViewScale(scale)


class PushButton(QPushButton):

    def __init__(self):
        QPushButton.__init__(self)
        self._icon = QIcon("./cut.svg")

    def resizeEvent(self, event):
        QPushButton.resizeEvent(self, event)
        size = self.size()
        pixmap = self._icon.pixmap(size.width() - 4, size.height() - 4)
        self.setIconSize(pixmap.size())
        self.setIcon(QIcon(pixmap))


if __name__ == '__main__':
    qApp = QApplication(sys.argv)

    CutIcon = QIcon("./cut.svg")

    view = GraphView()
    scene = GraphScene()
    btn = QPushButton()
    btn.setIcon(QIcon("./cut.svg"))
    bw = scene.addWidget(btn)
    bw.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)
    view.setScene(scene)
    view.show()

    b = PushButton()
    b.show()

    qApp.exec_()

892768447 avatar Jan 15 '21 05:01 892768447

好,谢谢,我试试

richiy avatar Jan 15 '21 13:01 richiy