如何在缩放时支持qgraphicsproxywidget中的高分辨率像素映射

时间:2016-02-09 04:31:57

标签: qt pyqt qwidget qgraphicsview qpixmap

我有一个qgraphicsview,其中包含一个包含qgraphicsproxywidget的场景。小部件当前通过QPixmap在大约25x25的正方形中显示一些高分辨率图像。我正在寻找适当的方法来支持放大图像而不会如此恶化其分辨率。我发现可以通过覆盖paint方法(即从QPixmap派生然后覆盖paint方法),或者使用QImage或一些配置选项(我在QGraphicsView上尝试过setSmoothRendering,但这只能帮助一点)提示,但是当图像在图形视图中的小部件中时,这些技术是否适用尚不清楚。

我写了下面的程序(实际上,我的同事Colin做了,我简化了发布),显示了我使用的技术。保存附加图像并运行程序后,将鼠标放在像素图上,然后按+几次放大:注意像素图是如何像素化的,而文本是完美的。

from PyQt5.QtCore import Qt
from PyQt5.Qt import QPixmap
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import (QApplication, QGraphicsScene, QWidget,
        QGraphicsView, QGraphicsProxyWidget, QLabel, QVBoxLayout, QHBoxLayout)


class TestGraphicsWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

    def setupUi(self, TEST):
        TEST.resize(400, 300)
        self.verticalLayout = QVBoxLayout(TEST)
        self.widget = QWidget(TEST)
        self.horizontalLayout = QHBoxLayout(self.widget)
        self.image_label = QLabel(self.widget)
        self.image_label.setStyleSheet("border: 2px solid red;")
        self.horizontalLayout.addWidget(self.image_label)
        self.text_label1 = QLabel(self.widget)
        self.text_label1.setStyleSheet("border: 2px solid red;")
        self.horizontalLayout.addWidget(self.text_label1)
        self.verticalLayout.addWidget(self.widget)
        self.text_label2 = QLabel(TEST)
        self.text_label2.setStyleSheet("border: 2px solid red;")
        self.verticalLayout.addWidget(self.text_label2)

        TEST.setWindowTitle("Form")
        self.text_label1.setText("TEXT LABEL 1")
        self.text_label2.setText("TEXT LABEL 2")


class TestView(QGraphicsView):

    def __init__(self):
        super().__init__()
        scene = QGraphicsScene(self)
        scene.setItemIndexMethod(QGraphicsScene.NoIndex)
        scene.setSceneRect(-400, -400, 800, 800)
        self.setScene(scene)
        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setViewportUpdateMode(QGraphicsView.BoundingRectViewportUpdate)
        self.setRenderHint(QPainter.Antialiasing)
        self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse)
        self.setResizeAnchor(QGraphicsView.AnchorViewCenter)

        test_widget = TestGraphicsWidget()
        test_widget.image_label.setFixedSize(25, 25)
        test_widget.image_label.setScaledContents(True)
        test_widget.image_label.setPixmap(QPixmap(r"chicken.jpg"))

        proxy = QGraphicsProxyWidget()
        proxy.setWidget(test_widget)
        proxy.setPos(-100, -100)
        scene.addItem(proxy)

        self.scale(0.8, 0.8)
        self.setMinimumSize(400, 400)

    def keyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_Plus:
            self.scaleView(1.2)
        elif key == Qt.Key_Minus:
            self.scaleView(1 / 1.2)
        else:
            super().keyPressEvent(event)

    def scaleView(self, scaleFactor):
        self.scale(scaleFactor, scaleFactor)


if __name__ == '__main__':
    import sys
    app = QApplication([])
    widget = TestView()
    widget.show()
    sys.exit(app.exec_())

虽然这并不是那么令人惊讶,因为像素图被缩减为25x25平方像素,然后按视图放大,如果有一种特定于qt的技术我不会感到惊讶,就像某些东西一样这可以通过覆盖QPixmap的绘制来完成,以考虑视图的当前比例。我没有选择使用QGraphicsView或在QGraphicsProxyWidget中嵌入图像,但我可以自由使用图像格式,视图配置或用于将图像加载到qt中的类等等。

任何帮助都会非常感激。

enter image description here

1 个答案:

答案 0 :(得分:2)

您似乎在问:如何在没有像素化的情况下将600x600 jpg缩小到25x25?答案显然是:你做不到。

如果你在一个图形视图中放置一个蹩脚的小25x25 jpg图像并将刻度尺放入和取出,就像站得更近或更远。图像根本不会改变:只有你的视图才能改变。而你越接近它,就会发现其内在的懦弱。

所以一个解决方案似乎是:从一个更大的主题开始。将窗口小部件的大小调整为原始大小的四倍(同样是图像标签),然后缩小图形视图以返回窗口小部件的原始起始大小。