pythonpython-3.xpyqtpyqt5qtsvg

How can I stop a QSvgWidget from spawning it's own window


I have just worked out how to show an svg image in pyqt5 using QSvgWidget and have tried to transplant it into a blank gui created with the qt designer. The svg image displays but in it's own window instead of in a container or boarder.

I have tried to read through the QSvgWidget docs to see what I am doing wrong but I have a feeling this is a problem with how I am using PyQT5 rather than QSvgWidget.

from PyQt5 import QtCore, QtGui, QtWidgets, QtSvg
import sys

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.viewer = QtSvg.QSvgWidget()
        self.viewer.load('C:/Windows/Temp/tubesheetsvgpreview.svg')
        self.viewer.setGeometry(QtCore.QRect(0,0,600,600))
        self.viewer.show()

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))




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_())

The results look like this:

enter image description here

whereas I would just like the svg to appear in a boarder within the main window and scaled to the boarder or window size


Solution

  • For a widget to be part of a window it must be a child of the window or child of a child from a window, in the case of QMainWindow it must be from the centralWidget, for this there are 2 methods:

    1. Pass to the window as a parent.
    # ...
    # pass self.centralwidget as parent
    self.viewer = QtSvg.QSvgWidget(self.centralwidget) 
    self.viewer.load('C:/Windows/Temp/tubesheetsvgpreview.svg')
    self.viewer.setGeometry(QtCore.QRect(0,0,600,600))
    # ...
    
    1. Set the widget through a layout.
    # ...
    self.centralwidget.setObjectName("centralwidget")
    
    self.viewer = QtSvg.QSvgWidget()
    self.viewer.load('C:/Windows/Temp/tubesheetsvgpreview.svg')
    self.viewer.setGeometry(QtCore.QRect(0,0,600,600))
    
    # set the layout to centralWidget
    lay = QtWidgets.QVBoxLayout(self.centralwidget)
    # add the viewer to the layout
    lay.addWidget(self.viewer)
    
    MainWindow.setCentralWidget(self.centralwidget)
    # ...
    

    Update:

    If you want to center the widget, it is best to use the second method and establish an alignment:

    # ...
    lay = QtWidgets.QVBoxLayout(self.centralwidget)
    lay.addWidget(self.viewer, alignment=QtCore.Qt.AlignCenter) # <---
    # ... 
    

    In the case of the first method, move the official widget (and in essence it is what the layout does in the other method) but you would have to do the same every time the widget changes in size.

    So the simplest method is to use the layout.