Reputation: 220
I am attempting to create a field in a QWizardPage that the user can either click on and a popup window opens up (this would be a window with a map on that allows the user to pick 2 coordinates) or allows the user to input the coordinates themselves. Think along the lines of a file picker line where the user can either open the popup file browser or manually type in the file path.
The original command is QLineEdit.
Upvotes: 0
Views: 101
Reputation: 243955
You have to create a custom widget that for example shows a QDoubleSpinBox for latitude and another for longitude, in addition to a button that allows to display a map (for example using QML). And then the widget is added to QWizardPage like any other widget.
import os
import sys
from pathlib import Path
from PySide2.QtCore import Property, Signal, Slot, Qt, QUrl
from PySide2.QtWidgets import (
QApplication,
QDialog,
QDialogButtonBox,
QDoubleSpinBox,
QHBoxLayout,
QLabel,
QToolButton,
QVBoxLayout,
QWidget,
QWizard,
QWizardPage,
)
from PyQt5.QtPositioning import QGeoCoordinate
from PyQt5.QtQuickWidgets import QQuickWidget
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class MapDialog(QDialog):
def __init__(self, geo_widget):
super().__init__(geo_widget)
self.setWindowTitle("Map")
self.map_widget = QQuickWidget(resizeMode=QQuickWidget.SizeRootObjectToView)
self.map_widget.rootContext().setContextProperty("controller", geo_widget)
filename = os.fspath(CURRENT_DIRECTORY / "main.qml")
url = QUrl.fromLocalFile(filename)
self.map_widget.setSource(url)
button_box = QDialogButtonBox()
button_box.setOrientation(Qt.Horizontal)
button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
lay = QVBoxLayout(self)
lay.addWidget(self.map_widget)
lay.addWidget(button_box)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
class GeoWidget(QWidget):
coordinate_changed = Signal(name="coordinateChanged")
def __init__(self, parent=None):
super().__init__(parent)
self._coordinate = QGeoCoordinate(0, 0)
self._lat_spinbox = QDoubleSpinBox(
minimum=-90.0, maximum=90.0, valueChanged=self.handle_value_changed
)
self._lng_spinbox = QDoubleSpinBox(
minimum=-180.0, maximum=180.0, valueChanged=self.handle_value_changed
)
self.btn = QToolButton(text="map", clicked=self.handle_clicked)
self.map_view = MapDialog(self)
lay = QHBoxLayout(self)
lay.addWidget(QLabel("Latitude:"))
lay.addWidget(self._lat_spinbox)
lay.addWidget(QLabel("Longitude:"))
lay.addWidget(self._lng_spinbox)
lay.addWidget(self.btn)
@Property(QGeoCoordinate, notify=coordinate_changed)
def coordinate(self):
return self._coordinate
@coordinate.setter
def coordinate(self, coordinate):
if self.coordinate == coordinate:
return
self._coordinate = coordinate
self.coordinate_changed.emit()
def handle_value_changed(self):
coordinate = QGeoCoordinate(
self._lat_spinbox.value(), self._lng_spinbox.value()
)
self.coordinate = coordinate
@Slot(QGeoCoordinate)
def update_from_map(self, coordinate):
self.coordinate = coordinate
self._lat_spinbox.setValue(self.coordinate.latitude())
self._lng_spinbox.setValue(self.coordinate.longitude())
def handle_clicked(self):
self.map_view.exec_()
class WizardPage(QWizardPage):
def __init__(self, parent=None):
super().__init__(parent)
self.geo_widget1 = GeoWidget()
self.geo_widget2 = GeoWidget()
self.registerField("coordinate1", self.geo_widget1, b"coordinate")
self.registerField("coordinate2", self.geo_widget2, b"coordinate")
lay = QVBoxLayout(self)
lay.addWidget(self.geo_widget1)
lay.addWidget(self.geo_widget2)
def main():
app = QApplication(sys.argv)
w = QWizard()
page = WizardPage()
w.addPage(page)
w.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
import QtLocation 5.15
import QtQuick 2.15
Item {
width: 400
height: 400
Map {
id: map
anchors.fill: parent
zoomLevel: 14
MouseArea {
id: mouse
anchors.fill: parent
onClicked: controller.update_from_map(map.toCoordinate(Qt.point(mouse.x, mouse.y)))
}
plugin: Plugin {
name: "osm"
}
}
}
Upvotes: 1