zooming in on an image
-
Hello,
I have been working with Pyqt5 to develop an application. I have created the design of the gui using the designer. One can execute the following code to start the application:
from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(930, 834) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) MainWindow.setSizePolicy(sizePolicy) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) self.horizontalLayout.setObjectName("horizontalLayout") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint) self.verticalLayout.setObjectName("verticalLayout") self.open_dir = QtWidgets.QPushButton(self.centralwidget) self.open_dir.setMinimumSize(QtCore.QSize(150, 75)) self.open_dir.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.open_dir.setObjectName("open_dir") self.verticalLayout.addWidget(self.open_dir) self.next = QtWidgets.QPushButton(self.centralwidget) self.next.setMinimumSize(QtCore.QSize(150, 75)) self.next.setObjectName("next") self.verticalLayout.addWidget(self.next) self.previous = QtWidgets.QPushButton(self.centralwidget) self.previous.setMinimumSize(QtCore.QSize(150, 75)) self.previous.setObjectName("previous") self.verticalLayout.addWidget(self.previous) self.load_model = QtWidgets.QPushButton(self.centralwidget) self.load_model.setMinimumSize(QtCore.QSize(150, 75)) self.load_model.setObjectName("load_model") self.verticalLayout.addWidget(self.load_model) self.predict = QtWidgets.QPushButton(self.centralwidget) self.predict.setMinimumSize(QtCore.QSize(150, 75)) self.predict.setObjectName("predict") self.verticalLayout.addWidget(self.predict) self.clear = QtWidgets.QPushButton(self.centralwidget) self.clear.setMinimumSize(QtCore.QSize(150, 75)) self.clear.setObjectName("clear") self.verticalLayout.addWidget(self.clear) self.save = QtWidgets.QPushButton(self.centralwidget) self.save.setMinimumSize(QtCore.QSize(150, 75)) self.save.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.save.setObjectName("save") self.verticalLayout.addWidget(self.save) self.horizontalLayout.addLayout(self.verticalLayout) spacerItem = QtWidgets.QSpacerItem(37, 17, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.gridLayout = QtWidgets.QGridLayout() self.gridLayout.setObjectName("gridLayout") self.image_label = QtWidgets.QLabel(self.centralwidget) self.image_label.setMinimumSize(QtCore.QSize(700, 500)) self.image_label.setMaximumSize(QtCore.QSize(16777215, 16777215)) self.image_label.setFrameShape(QtWidgets.QFrame.WinPanel) self.image_label.setFrameShadow(QtWidgets.QFrame.Sunken) self.image_label.setLineWidth(1) self.image_label.setScaledContents(True) self.image_label.setObjectName("image_label") self.gridLayout.addWidget(self.image_label, 0, 0, 1, 1) spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) self.gridLayout.addItem(spacerItem1, 1, 0, 1, 1) self.classes = QtWidgets.QLabel(self.centralwidget) self.classes.setMinimumSize(QtCore.QSize(700, 201)) self.classes.setFrameShape(QtWidgets.QFrame.WinPanel) self.classes.setFrameShadow(QtWidgets.QFrame.Plain) self.classes.setScaledContents(True) self.classes.setObjectName("classes") self.gridLayout.addWidget(self.classes, 2, 0, 1, 1) self.horizontalLayout.addLayout(self.gridLayout) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 930, 26)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.actionRecent = QtWidgets.QAction(MainWindow) self.actionRecent.setObjectName("actionRecent") self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.open_dir.setText(_translate("MainWindow", "Open Directory")) self.next.setText(_translate("MainWindow", "Next Image -->")) self.previous.setText(_translate("MainWindow", "<-- Previous Image")) self.load_model.setText(_translate("MainWindow", "Load Model")) self.predict.setText(_translate("MainWindow", "Predict")) self.clear.setText(_translate("MainWindow", "Clear")) self.save.setText(_translate("MainWindow", "Save")) self.image_label.setText(_translate("MainWindow", "ImageLabel")) self.classes.setText(_translate("MainWindow", "TextLabel")) self.actionRecent.setText(_translate("MainWindow", "Recent")) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) MainWindow = QtWidgets.QMainWindow() ui = Ui_MainWindow() ui.setupUi(MainWindow) MainWindow.show() sys.exit(app.exec_())
Now I am adding some functionalities to the image_label section of the gui i.e. zooming, panning and so on. In order to do this, I have written the following script:
# Import pyqt stuff from PyQt5 import QtCore, QtGui, QtWidgets, Qt from PyQt5.QtWidgets import QFileDialog from PyQt5.QtWidgets import QApplication # Import the python script generated by the Qt-Designer from version4 import Ui_MainWindow # Import miscellaneous import sys import os class ImageViewer(QtWidgets.QGraphicsView): factor = 2.0 def __init__(self, parent=None): super().__init__(parent) self.setRenderHints( QtGui.QPainter.Antialiasing | QtGui.QPainter.SmoothPixmapTransform ) self.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.setBackgroundRole(QtGui.QPalette.Dark) scene = QtWidgets.QGraphicsScene() self.setScene(scene) self._pixmap_item = QtWidgets.QGraphicsPixmapItem() scene.addItem(self._pixmap_item) def load_image(self, fileName): pixmap = QtGui.QPixmap(fileName) if pixmap.isNull(): return False self._pixmap_item.setPixmap(pixmap) return True def zoomIn(self): self.zoom(self.factor) def zoomOut(self): self.zoom(1 / self.factor) def zoom(self, f): self.scale(f, f) def resetZoom(self): self.resetTransform() def fitToWindow(self): self.fitInView(self.sceneRect(), QtCore.Qt.KeepAspectRatio) class mainProgram(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): # Inherit from the aforementioned class and set up the gui super(mainProgram, self).__init__(parent) self.setupUi(self) self.fileList = [] self.dirIterator = None self.scaleFactor = 1.0 self.view = ImageViewer() # Set an index to iterate through directory self.i = 0 self.create_shortcuts() self.create_actions() self.create_menus() # Statusbar self.statusBar = QtWidgets.QStatusBar(self) self.setStatusBar(self.statusBar) self.statusBar.showMessage('Welcome') def create_shortcuts(self): self.open_dir.setShortcut(QtGui.QKeySequence("O")) self.next.setShortcut(QtGui.QKeySequence("D")) self.previous.setShortcut(QtGui.QKeySequence("A")) def all_callbacks(self): self.open_dir.clicked.connect(self.open_directory_callback) self.next.clicked.connect(self.next_button_callback) self.previous.clicked.connect(self.previous_button_callback) def open_directory_callback(self): # Paths self._base_dir = os.getcwd() self._images_dir = os.path.join(self._base_dir, 'test_images') # Open a File Dialog and select the folder path dialog = QFileDialog() self._folder_path = dialog.getExistingDirectory(None, "Select Folder") # Get the list of images in the folder and read using matplotlib and print its shape self.list_of_images = os.listdir(self._folder_path) self.list_of_images = sorted(self.list_of_images) if self.list_of_images: self.statusBar.showMessage('Total Number of Images in the directory \ : {}'.format(len(self.list_of_images))) # Length of Images print('Number of Images in the selected folder: {}'.format(len(self.list_of_images))) filename = '{}\\{}'.format(self._images_dir, self.list_of_images[0]) print(filename) # Show the first Image in the same window. (self.label comes from the Ui_main_window class) pixmap = QtGui.QPixmap(filename) if filename: is_loaded = self.view.load_image(filename) self.fitToWindowAct.setEnabled(is_loaded) self.updateActions() # self.image_label.setPixmap(pixmap) # self.image_label.show() def next_button_callback(self): total_images = len(self.list_of_images) if self.list_of_images: try: self.i = (self.i + 1) % total_images self.img = self.list_of_images[self.i] pixmap = QtGui.QPixmap('{}\\{}'.format(self._images_dir, self.img)) self.image_label.setPixmap(pixmap) self.image_label.show() self.statusBar.showMessage('Current Image: {}'.format(self.list_of_images[self.i])) except ValueError as e: print('The selected folder does not contain any images') self.fitToWindowAct.setEnabled(True) self.updateActions() def previous_button_callback(self): total_images = len(self.list_of_images) if self.list_of_images: try: self.i = (self.i - 1) % total_images self.img = self.list_of_images[self.i] pixmap = QtGui.QPixmap('{}\\{}'.format(self._images_dir, self.img)) self.image_label.setPixmap(pixmap) self.image_label.show() self.statusBar.showMessage('Current Image: {}'.format(self.list_of_images[self.i])) except ValueError as e: print('The selected folder does not contain any images') self.fitToWindowAct.setEnabled(True) self.updateActions() def fitToWindow(self): if self.fitToWindowAct.isChecked(): self.view.fitToWindow() else: self.view.resetZoom() self.updateActions() def create_menus(self): # File Menu self.fileMenu = QtWidgets.QMenu("&File", self) self.fileMenu.addAction(self.exitAct) # Controls Menu self.controlsMenu = QtWidgets.QMenu("&Controls", self) self.controlsMenu.addAction(self.zoomInAct) self.controlsMenu.addAction(self.zoomOutAct) self.controlsMenu.addAction(self.normalSizeAct) self.fileMenu.addSeparator() self.controlsMenu.addAction(self.fitToWindowAct) # Add Menus self.menuBar().addMenu(self.fileMenu) self.menuBar().addMenu(self.controlsMenu) def create_actions(self): self.exitAct = QtWidgets.QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close) self.zoomInAct = QtWidgets.QAction("Zoom &In (25%)", self, shortcut="Ctrl++", enabled=False, triggered=self.view.zoomIn) self.zoomOutAct = QtWidgets.QAction("Zoom &Out (25%)", self, shortcut="Ctrl+-", enabled=False, triggered=self.view.zoomOut) self.fitToWindowAct = QtWidgets.QAction("&Fit To Window", self, shortcut="Ctrl+F", enabled=False, checkable=True, triggered=self.fitToWindow) self.normalSizeAct = QtWidgets.QAction("&Normal Size", self, shortcut="Ctrl+0", enabled=False, triggered=self.view.resetZoom) def updateActions(self): self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked()) self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked()) self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked()) def execute_pipeline(): # Make an object of the class and execute it app = QApplication(sys.argv) # Make an object and call the functions annotationGui = mainProgram() annotationGui.all_callbacks() annotationGui.show() # Exit the window sys.exit(app.exec_()) if __name__ == "__main__": execute_pipeline()
Here, the 'version4' is the code on the top.
Now, I am trying to zoom in on the image using the ImageViewer class. But when the open_directory button is pressed, the image doesn't appear in the window. But when I remove the object 'self.view' of the ImageViewer class, the image does appear but then I can't using zoomIn andf zoomOut.Therefore, I am unsure as to what is wrong. Please let me know if something else should be specified in the question.
Regards.
-
Hi and welcome to devnet,
Your view object is never shown nor added to a layout nor set as the central widget of your QMainWindow based class. Hence it stays invisible.
-
@SGaist But if I add view object to the base class like the following:
self.setCentralWidget(self.view)
then then the entire window blanks out. I just want to know how do I add the self.view to the image_label section of the gui.
Thanks for the reply!!