如何使用 pyinstaller 创建可独立运行的 QML 映射?
How to create a QML map standalone runnable with pyinstaller?
我有一个虚拟 python 程序,它创建一个 Qt 小部件应用程序,其中 QML 映射作为主要小部件 (QQuickWidget)。
如果我 运行 源代码 (python main.py
),代码工作正常。当我尝试使用 pyinstaller 创建一个独立的 运行nable 时,问题就来了。 运行nable 生成正确,但是当我 运行 它时 map 是空的 并且以下消息出现在 控制台输出 :
1 , "The geoservices provider is not supported."
我假设 运行nable 创建得很好,因为如果我用更虚拟的东西(删除地图)更改我的 view.qml
就可以正常工作。顺便说一句,我通过以下方式生成它:
pyinstaller --add-data "view.qml:." --onefile main.py
我的main.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 )
我还添加了我的源文件以防我在其中出错:
main.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
}
}
您必须复制地图使用的插件,为此您必须遵循以下步骤:
- 在控制台执行以下命令获取插件路径的路径:
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
```
我有一个虚拟 python 程序,它创建一个 Qt 小部件应用程序,其中 QML 映射作为主要小部件 (QQuickWidget)。
如果我 运行 源代码 (python main.py
),代码工作正常。当我尝试使用 pyinstaller 创建一个独立的 运行nable 时,问题就来了。 运行nable 生成正确,但是当我 运行 它时 map 是空的 并且以下消息出现在 控制台输出 :
1 , "The geoservices provider is not supported."
我假设 运行nable 创建得很好,因为如果我用更虚拟的东西(删除地图)更改我的 view.qml
就可以正常工作。顺便说一句,我通过以下方式生成它:
pyinstaller --add-data "view.qml:." --onefile main.py
我的main.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 )
我还添加了我的源文件以防我在其中出错:
main.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
}
}
您必须复制地图使用的插件,为此您必须遵循以下步骤:
- 在控制台执行以下命令获取插件路径的路径:
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
```