Настройте GraphicView в соответствии с любой геометрией изображения - PullRequest
1 голос
/ 29 марта 2019

Мой QGraphicsView должен показывать изображение большого разрешения. Размер должен соответствовать размеру окна. В настоящее время изображение просматривается так, как я хочу, но только путем предоставления некоторых скорректированных вручную значений исходной геометрии вида. Это не выглядит аккуратно. Я также попытался сослаться на решения, размещенные здесь: Графический вид и Размер Pixmap

Мое текущее окно выглядит так:

enter image description here

class ImageCheck(Ui_ImageCheck.Ui_MainWindow, QMainWindow):
    def __init__(self, parent=None):
        super(ImageCheck, self).__init__()
        self.setupUi(self)
        self.setWindowTitle("Image Analyzer")

        self.crop_ratio_w = 1
        self.crop_ratio_h = 1

        self.path = None
        self.scene = QGraphicsScene()
        self.scene.clear()
        self.image_item = QGraphicsPixmapItem()
        # This is the approximate shift in coordinates of my initial view from the window
        self.view.setGeometry(self.geometry().x()+ 10, self.geometry().y()+ 39, 
                    self.geometry().width()- 55, self.geometry().height()- 110)

        self.view.setAlignment(Qt.AlignCenter)
        self.view.setFrameShape(QFrame.NoFrame)

        def setImage(self, path):
           self.path = path
           self.crop_ratio_w = self.pixmap.width() / self.view.width()
           self.crop_ratio_h = self.pixmap.height() / self.view.height()

           pixmap = QPixmap(path)
           smaller_pixmap = pixmap.scaled(self.view.width(), self.view.height(),
                    Qt.IgnoreAspectRatio, t.FastTransformation)

           self.image_item.setPixmap(smaller_pixmap)
           self.scene.addItem(self.image_item)

           self.scene.setSceneRect(0, 0, self.view.width(), self.view.height())
           self.view.setGeometry(0, 0, self.view.width(), self.view.height())   

           self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
           self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
           self.view.setScene(self.scene)
           self.view.setSceneSize()

        def resizeEvent(self, event):
           self.view.setGeometry(self.geometry().x()+ 10, self.geometry().y()+ 39, 
                    self.geometry().width()- 55, self.geometry().height()- 110)
           self.setImage(self.path)

Мое ручное переопределение, вероятно, не было хорошей идеей, когда я пытался определить расстояния между двумя точками. Даже уменьшенное расстояние дает мне немного неправильное значение.

1 Ответ

2 голосов
/ 08 апреля 2019

Я не могу использовать ваш код, потому что есть много скрытых вещей, поэтому я предложу следующее решение, которое заключается в том, чтобы масштабировать представление на основе сцены каждый раз, когда окно меняет свой размер. Я также реализовал сигнал, который переносит информацию по щелчку на изображении на основе координат изображения.

from PyQt5 import QtCore, QtGui, QtWidgets


class ClickableGraphicsView(QtWidgets.QGraphicsView):
    clicked = QtCore.pyqtSignal(QtCore.QPoint)

    def __init__(self, parent=None):
        super(ClickableGraphicsView, self).__init__(parent)
        scene = QtWidgets.QGraphicsScene(self)
        self.setScene(scene)
        self.pixmap_item = None

    def setImage(self, path):
        pixmap = QtGui.QPixmap(path)
        self.pixmap_item = self.scene().addPixmap(pixmap)
        self.pixmap_item.setShapeMode(
            QtWidgets.QGraphicsPixmapItem.BoundingRectShape
        )

    def mousePressEvent(self, event):
        if self.pixmap_item is not None:
            if self.pixmap_item == self.itemAt(event.pos()):
                sp = self.mapToScene(event.pos())
                lp = self.pixmap_item.mapToItem(self.pixmap_item, sp)
                p = lp.toPoint()
                if self.pixmap_item.pixmap().rect().contains(p):
                    self.clicked.emit(p)
        super(ClickableGraphicsView, self).mousePressEvent(event)

    def resizeEvent(self, event):
        self.fitInView(self.sceneRect(), QtCore.Qt.IgnoreAspectRatio)
        super(ClickableGraphicsView, self).resizeEvent(event)


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setWindowTitle("Image Analyzer")
        view = ClickableGraphicsView()
        view.clicked.connect(print)
        view.setImage("image.jpg")

        label = QtWidgets.QLabel("Distance")
        display = QtWidgets.QLCDNumber()

        buttonbox = QtWidgets.QDialogButtonBox(
            QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
        )

        widget = QtWidgets.QWidget()
        self.setCentralWidget(widget)
        lay = QtWidgets.QGridLayout(widget)
        lay.addWidget(view, 0, 0, 1, 2)
        hlay = QtWidgets.QHBoxLayout()
        hlay.addWidget(label)
        hlay.addWidget(display)
        hlay.addStretch()
        lay.addLayout(hlay, 1, 0)
        lay.addWidget(buttonbox, 1, 1)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
...