如何使用 pyinstaller 创建可独立运行的 QML 地图?

Posted

技术标签:

【中文标题】如何使用 pyinstaller 创建可独立运行的 QML 地图?【英文标题】:How to create a QML map standalone runnable with pyinstaller? 【发布时间】:2020-06-29 09:55:59 【问题描述】:

我有一个虚拟 python 程序,它创建一个 Qt 小部件应用程序,其中 QML 地图作为主要小部件 (QQuickWidget)。

如果我运行源代码 (python main.py),代码可以正常工作。当我尝试使用 pyinstaller 创建一个独立的可运行文件时,问题就来了。可运行对象已正确生成,但是当我运行它时,地图为空,并且控制台输出中出现以下消息:

1 ,  "The geoservices provider is not supported."

我认为可运行对象创建得很好,因为如果我将 view.qml 更改为更虚拟的东西(删除地图)工作正常。顺便说一句,我通过以下方式生成它:

pyinstaller --add-data "view.qml:." --onefile main.py

我的 ma​​in.spec 是:

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['main.py'],
             pathex=['/home/parias/Documentos/pyside_pruebas/wigdet-map'],
             binaries=[],
             datas=[('view.qml', '.')],
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,
          [],
          name='main',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=None,
          console=True )

我还会添加我的源文件以防我在其中出错:

ma​​in.py

from PySide2.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget
from PySide2.QtCore import Qt, Slot, QUrl
from PySide2.QtQuickWidgets import QQuickWidget

import sys
import os


class MapWidget(QWidget):
    def __init__(self, parent, *args, **kwargs):
        super(MapWidget, self).__init__(*args, **kwargs)

        self.map_widget = QQuickWidget(self)
        url = QUrl("view.qml")

        self.map_widget.setSource(url)
        self.map_widget.setResizeMode(QQuickWidget.SizeRootObjectToView)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.map_widget)

        self.setLayout(self.layout)


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.main_widget = MapWidget(self)
        self.setCentralWidget(self.main_widget)


def main():
    app = QApplication(sys.argv)

    window = MainWindow()
    window.show()

    sys.exit(app.exec_())


if __name__ == "__main__":
    main()

view.qml

import QtQuick 2.0
import QtQuick.Window 2.15
import QtLocation 5.15
import QtPositioning 5.15
import QtQuick.Controls 1.4

Item 
    width: 512
    height: 512
    visible: true

    Plugin 
        id: mapPlugin
        name: "osm"
        PluginParameter  name: "osm.useragent"; value: "Prueba" 
        PluginParameter  name: "osm.mapping.copyright"; value: "All mine" 
        PluginParameter  name: "osm.mapping.highdpi_tiles"; value: true 
    

    Map 
        id: map_map
        objectName: "map"
        anchors.fill: parent
        plugin: mapPlugin
        center: QtPositioning.coordinate(40.091675, -3.696038) // Seseña
        zoomLevel: 14
    

【问题讨论】:

【参考方案1】:

您必须复制 Map 使用的插件,为此您必须遵循以下步骤:

在控制台执行以下命令获取插件路径的路径:
python -c "from PySide2.QtCore import QLibraryInfo; print(QLibraryInfo.location(QLibraryInfo.PluginsPath))"

输出

/usr/lib/python3.6/site-packages/PySide2/Qt/plugins
将“plugins/geoservices”目录复制到可执行文件的一侧

输出:

├── geoservices
│   ├── libqtgeoservices_esri.so
│   ├── libqtgeoservices_itemsoverlay.so
│   ├── libqtgeoservices_mapboxgl.so
│   ├── libqtgeoservices_mapbox.so
│   ├── libqtgeoservices_nokia.so
│   └── libqtgeoservices_osm.so
├── main
└── view.qml
```

【讨论】:

谢谢!你太棒了!

以上是关于如何使用 pyinstaller 创建可独立运行的 QML 地图?的主要内容,如果未能解决你的问题,请参考以下文章

从 python 代码为 Windows 创建独立的可执行文件

如何使用VS 2013发布一个可以在Windows XP中独立运行的可执行文件

如何使用 JavaScript 使每一列(独立地)可过滤 HTML?

如何压缩1MB以下的独立exe项目?

如何使 Python 脚本独立可执行以在没有任何依赖项的情况下运行? [复制]

创建独立的 Lua 可执行文件