6

I am creating a standalone custom PyQGIS application and have some questions regarding canvas.

I have read the cookbook: https://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/canvas.html

They mentioned that you can open the canvas with

canvas = QgsMapCanvas()
canvas.show()

However, I have already embedded the canvas into my GUI. I wish to have the embedded canvas with all my layers in it pop up as a separate window when I click a button. I have tried this:

self.canvas = QgsMapCanvas(self.centralwidget)
self.canvas.show()

But it doesn't work.

QtDesigner test Code:

from PyQt5 import QtCore, QtGui, QtWidgets


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.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.widget = QgsMapCanvas(self.centralwidget)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        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"))
        self.pushButton.setText(_translate("MainWindow", "Fullscreen"))
from qgis.gui import QgsMapCanvas


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

Main code:

class Main(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.setupUi(self)

        self.pushbutton.clicked.connect(self.makeFullscreen)

    def makeFullscreen(self):
        self.widget.show()

The output should be a canvas in a new window after clicking the button.

4
  • Do you want to open custom map canvas in QGIS or standalone PyQt application? Recipe in the cookbook explains how to open map canvas in QGIS. Did you add layer tree widget to your GUI? Please add your script, so that we can give you more specific solution. Sep 17 '20 at 12:18
  • custom map canvas in standalone PyQt application. I'll be adding more details to the question
    – Sean Ang
    Sep 17 '20 at 12:21
  • @KadirŞahbaz I have uploaded a simplified version of my script to the question. It is a standalone PyQt application that should open the embedded canvas in a new window after the button is pressed.
    – Sean Ang
    Sep 17 '20 at 12:34
  • Do you need to maximize the actual window or open a new window include a new map canvas? Sep 17 '20 at 14:11
8

Review this script. It creates a new QMainWindow and moves the existing map canvas to that window. I've made some changes. Firstly, add a file path (to QgsVectorLayer) to be displayed in map canvas.

from PyQt5 import QtCore, QtGui, QtWidgets
from qgis.gui import QgsMapCanvas
from qgis.core import QgsVectorLayer

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        self.main_window = MainWindow
        self.main_window.setObjectName("MainWindow")
        self.main_window.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(self.main_window)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.widget = QgsMapCanvas(self.centralwidget)
        self.widget.setObjectName("widget")
        self.horizontalLayout.addWidget(self.widget)
        self.main_window.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(self.main_window)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        self.main_window.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(self.main_window)
        self.statusbar.setObjectName("statusbar")
        self.main_window.setStatusBar(self.statusbar)

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

        self.pushButton.clicked.connect(self.open_new_mapcanvas_window)
        # add a layer to map canvas
        self.layer = QgsVectorLayer("ADD/FILE/PATH", 'layer', 'ogr')
        self.widget.setExtent(self.layer.extent())
        self.widget.setLayers([self.layer])

    def open_new_mapcanvas_window(self):
        self.new_window = QtWidgets.QMainWindow()
        self.new_window.showMaximized()
        self.new_window.setCentralWidget(self.widget)
        self.new_window.show()


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


class Main(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.setupUi(self)

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

If you don't want to move existing map canvas to new window, change open_new_mapcanvas_window as below. This method creates a new window including a new map canvas object containing same layers.

def open_new_mapcanvas_window(self):
    self.new_window = QtWidgets.QMainWindow()
    self.new_window.showMaximized()
    self.new_canvas = QgsMapCanvas(self.new_window)
    self.new_canvas.setLayers(self.widget.layers())
    self.new_canvas.setExtent(self.layer.extent())
    self.new_window.setCentralWidget(self.new_canvas)
    self.new_window.show()
3
  • This doesn't work when I implement it onto my PyQt button though. It opens and instantly closes.
    – Sean Ang
    Sep 17 '20 at 12:08
  • I didn't understand what exactly you need, but review the edited answer. Sep 17 '20 at 15:02
  • I was looking for the second answer. It works with some minor adjustments. Thanks a lot! Really appreciate it!
    – Sean Ang
    Sep 17 '20 at 18:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.