簡體   English   中英

如何將 Ipyleaflet map 添加到 PyQt5 應用程序?

[英]How to add an Ipyleaflet map to a PyQt5 application?

我使用 PyQt5 創建了一個應用程序,該應用程序(除其他外)顯示 map。

對於 map 小部件,我使用了 pyqtlet ,但我開始意識到這個 package 真的很有限(我想顯示不同的層,使用可拖動的標記等),所以我想轉換到ipyleaflet .

除了我無法讓我的 map 在應用程序中顯示!

原來的代碼是這樣的:

import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QLabel
from pyqtlet import L, MapWidget


class MapWindow(QWidget):
    def __init__(self, base_coords):
        self.base_coords = base_coords
        # Setting up the widgets and layout
        super().__init__()
        self.layout = QVBoxLayout()
        self.title = QLabel("<b>This is my title</b>")
        self.layout.addWidget(self.title)
        self.mapWidget = MapWidget()
        self.layout.addWidget(self.mapWidget)
        self.setLayout(self.layout)

        # Working with the maps with pyqtlet
        self.map = L.map(self.mapWidget)
        self.map.setView(self.base_coords, zoom=10)
        L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}'
                    ).addTo(self.map)  # ArcGIS_topo layer
        self.marker = L.marker(self.base_coords)
        self.marker.bindPopup('This is my marker')
        self.map.addLayer(self.marker)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    base_coords = [45.783119, 3.123364]
    widget = MapWindow(base_coords)
    sys.exit(app.exec_())
    

然后我嘗試使用它來更改為 ipyleaflet:

import sys
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QLabel
from PyQt5 import QtWebEngineWidgets
from ipyleaflet import Map, Marker, LayersControl, basemaps
from ipywidgets import HTML


class MapWindow(QWidget):
    def __init__(self, base_coords):
        self.base_coords = base_coords
        # Setting up the widgets and layout
        super().__init__()
        self.layout = QVBoxLayout()
        self.title = QLabel("<b>This is my title</b>")
        self.layout.addWidget(self.title)

        # Working with the maps with ipyleaflet
        self.map = Map(center=self.base_coords, basemaps=basemaps.Esri.WorldTopoMap, zoom=10)
        self.layout.addWidget(self.map)

        self.marker = Marker(location=self.base_coords)
        self.marker.popup = HTML(value='This is my marker')
        self.map.add_layer(self.marker)
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    base_coords = [45.783119, 3.123364]
    widget = MapWindow(base_coords)
    sys.exit(app.exec_())

但是在布局中添加 map 不起作用,我收到以下錯誤消息:

Traceback (most recent call last):
  File "G:\venv\lib\site-packages\IPython\core\interactiveshell.py", line 3418, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-2-bd466e04ab02>", line 1, in <module>
    runfile('G:/Application/short_app - Copie.py', wdir='G:/Application')
  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_bundle\pydev_umd.py", line 197, in runfile
    pydev_imports.execfile(filename, global_vars, local_vars)  # execute the script
  File "C:\Program Files\JetBrains\PyCharm 2020.2.3\plugins\python\helpers\pydev\_pydev_imps\_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "G:/Application/short_app - Copie.py", line 29, in <module>
    widget = MapWindow(base_coords)
  File "G:/Application/short_app - Copie.py", line 19, in __init__
    self.layout.addWidget(self.map)
TypeError: addWidget(self, QWidget, stretch: int = 0, alignment: Union[Qt.Alignment, Qt.AlignmentFlag] = Qt.Alignment()): argument 1 has unexpected type 'Map'

有人知道我可以將 ipyleaflet map 添加到我的應用程序中嗎?

問題是您正在嘗試將self.map添加到布局中,但由於它不是從 QWidget 派生的,因此它不起作用,因此出現錯誤。 我可以看到你已經導入QtWebEngineWidgets但它沒有被使用。 要嵌入 Jupyter 小部件,您可以生成包含 ipyleaflet 小部件的 HTML,然后將 HTML 添加到QtWebEngineWidgets.QWebEngineView 下面是從文檔中將 Jupyter 小部件添加到 HTML 的簡單實現:

import sys
import json
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget, QLabel
from PyQt5 import QtWebEngineWidgets

from ipyleaflet import Map, Marker, LayersControl, basemaps
from ipywidgets import HTML, IntSlider
from ipywidgets.embed import embed_data


class MapWindow(QWidget):
    def __init__(self, base_coords):
        self.base_coords = base_coords
        # Setting up the widgets and layout
        super().__init__()
        self.layout = QVBoxLayout()
        self.title = QLabel("<b>This is my title</b>")
        self.layout.addWidget(self.title)

        # Create QtWebEngineView widget
        self.web = QtWebEngineWidgets.QWebEngineView(self)

        # Sliders
        s1 = IntSlider(max=200, value=100)
        s2 = IntSlider(value=40)

        # Working with the maps with ipyleaflet
        self.map = Map(center=self.base_coords, basemaps=basemaps.Esri.WorldTopoMap, zoom=10)

        self.marker = Marker(location=self.base_coords)
        self.marker.popup = HTML(value='This is my marker')
        self.map.add_layer(self.marker)

        data = embed_data(views=[s1, s2, self.map])

        html_template = """
        <html>
          <head>

            <title>Widget export</title>

            <!-- Load RequireJS, used by the IPywidgets for dependency management -->
            <script 
              src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" 
              integrity="sha256-Ae2Vz/4ePdIu6ZyI/5ZGsYnb+m0JlOmKPjt6XZ9JJkA=" 
              crossorigin="anonymous">
            </script>

            <!-- Load IPywidgets bundle for embedding. -->
            <script
              data-jupyter-widgets-cdn="https://cdn.jsdelivr.net/npm/"
              src="https://unpkg.com/@jupyter-widgets/html-manager@*/dist/embed-amd.js" 
              crossorigin="anonymous">
            </script>

            <!-- The state of all the widget models on the page -->
            <script type="application/vnd.jupyter.widget-state+json">
              {manager_state}
            </script>
          </head>

          <body>

            <h1>Widget export</h1>

            <div id="first-slider-widget">
              <!-- This script tag will be replaced by the view's DOM tree -->
              <script type="application/vnd.jupyter.widget-view+json">
                {widget_views[0]}
              </script>
            </div>

            <hrule />

            <div id="second-slider-widget">
              <!-- This script tag will be replaced by the view's DOM tree -->
              <script type="application/vnd.jupyter.widget-view+json">
                {widget_views[1]}
              </script>
            </div>
            
            <!-- The ipyleaflet map -->
            <div id="ipyleaflet-map">
                <script type="application/vnd.jupyter.widget-view+json">
                    {widget_views[2]}
                </script>
            </div>

          </body>
        </html>
        """

        manager_state = json.dumps(data['manager_state'])
        widget_views = [json.dumps(view) for view in data['view_specs']]
        rendered_template = html_template.format(manager_state=manager_state, widget_views=widget_views)

        # Set HTML
        self.web.setHtml(rendered_template)

        # Add webengine to layout and add layout to widget
        self.layout.addWidget(self.web)
        self.setLayout(self.layout)

        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    base_coords = [45.783119, 3.123364]
    widget = MapWindow(base_coords)
    widget.resize(900, 800)
    sys.exit(app.exec_())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM