Kartenmarkierungen bewegen sich weiter, nachdem sie gespeichert und erneut geöffnet wurdenPython

Python-Programme
Anonymous
 Kartenmarkierungen bewegen sich weiter, nachdem sie gespeichert und erneut geöffnet wurden

Post by Anonymous »

Code: Select all

import sys
import os
import json

from PyQt5.QtWidgets import (
QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem,
QMessageBox, QWidget, QFileDialog, QMenu, QAction, QVBoxLayout, QHBoxLayout,
QPushButton, QDialog, QFormLayout, QLineEdit, QTextEdit, QDialogButtonBox, QLabel, QSizePolicy
)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt, QUrl, QRectF, QPoint
from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5.QtCore import QPointF
from PyQt5.QtCore import Qt, QUrl, QRectF, QPoint, QPointF

def resource_path(relative_path):
""" Get absolute path to resource, works for development and PyInstaller.  """
base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
full_path = os.path.join(base_path, relative_path)
print(f"Base Path: {base_path}")
print(f"Full Path: {full_path}")
return full_path

class Marker(QGraphicsPixmapItem):
def __init__(self, x, y, icon_path, size, text="", image_link="", image_display_callback=None, parent=None):
super().__init__(parent)
self.icon_path = icon_path #  0 and self.current_zoom_level * self.zoom_factor = self.min_zoom_level:
self.scale(1 / self.zoom_factor, 1 / self.zoom_factor)
self.current_zoom_level /= self.zoom_factor

def show_context_menu(self, global_pos, scene_pos):
menu = QMenu()
icon_menu = QMenu("Add Marker with Icon", self)
for icon_path in self.custom_icon_paths:
action = QAction(os.path.basename(icon_path), self)
action.triggered.connect(lambda _, path=icon_path: self.add_marker(scene_pos.x(), scene_pos.y(), path))
icon_menu.addAction(action)

menu.addMenu(icon_menu)
menu.exec_(global_pos)

def add_marker(self, x, y, icon_path, text="", image_link=""):
resolved_icon_path = resource_path(icon_path)
print(f"Adding marker with icon path: {resolved_icon_path}")
if not os.path.exists(resolved_icon_path):
QMessageBox.critical(self, "Error", f"Icon file not found: {resolved_icon_path}")
return

marker = Marker(x, y, resolved_icon_path, self.marker_size, text, image_link, self.display_image)
self.scene.addItem(marker)
self.markers.append(marker)

def edit_marker(self, marker):
marker.hide_tooltip()
dialog = MarkerEditDialog(marker.tooltip_text, marker.tooltip_image)
if dialog.exec_() == QDialog.Accepted:
text, image_link = dialog.get_data()
marker.tooltip_text = text
marker.tooltip_image = image_link

def remove_marker(self, marker):
if marker in self.markers:
self.scene.removeItem(marker)
self.markers.remove(marker)

def display_tooltip(self, marker, mouse_position):
if marker:
global_position = self.viewport().mapToGlobal(mouse_position)
marker.tooltip_label.move(global_position + QPoint(15, 15))
marker.show_tooltip()

def display_image(self, image_link):
if image_link:
pixmap = QPixmap()
if image_link.startswith("http://") or image_link.startswith("https://"):
manager = QNetworkAccessManager()
request = QNetworkRequest(QUrl(image_link))
manager.finished.connect(lambda reply: self.handle_image_reply(reply, manager))
manager.get(request)
else:
pixmap = QPixmap(image_link)
if not pixmap.isNull():
self.image_box.setPixmap(pixmap)
self.image_box.show()
# Anchor to bottom-center of the viewport
self.image_box.move(
(self.viewport().width() - self.image_box.width()) // 2,
self.viewport().height() - self.image_box.height() - 10
)

def save_markers(self, file_path="markers.json"):
if not self.map_item:
QMessageBox.critical(None, "Error", "No map loaded to save markers.")
return

map_rect = self.map_item.boundingRect()  # Cached during load_image
markers_data = []
for marker in self.markers:
marker_pos = self.map_item.mapFromScene(marker.scenePos())
markers_data.append({
"x": (marker_pos.x() - map_rect.left()) / map_rect.width(),
"y": (marker_pos.y() - map_rect.top()) / map_rect.height(),
"icon_path": marker.icon_path,
"text": marker.tooltip_text,
"image_link": marker.tooltip_image
})

try:
with open(file_path, "w") as f:
json.dump(markers_data, f)
print(f"Markers saved to {file_path}")
except Exception as e:
QMessageBox.critical(None, "Error", f"Failed to save markers:  {e}")

def load_markers(self, file_path="markers.json"):
if not self.map_item:
QMessageBox.critical(None, "Error", "No map loaded to place markers.")
return

map_rect = self.map_item.boundingRect()  # Cached during load_image
try:
with open(file_path, "r") as f:
markers_data = json.load(f)

for marker_data in markers_data:
# Convert relative coordinates back to absolute positions
relative_x = marker_data.get("x", 0)
relative_y = marker_data.get("y", 0)
x = map_rect.left() + relative_x * map_rect.width()
y = map_rect.top() + relative_y * map_rect.height()

scene_pos = self.map_item.mapToScene(QPointF(x, y))
icon_path = resource_path(marker_data.get("icon_path", ""))
self.add_marker(scene_pos.x(), scene_pos.y(), icon_path, marker_data.get("text", ""),
marker_data.get("image_link", ""))
except FileNotFoundError:
print("No markers file found.  Starting fresh.")
except Exception as e:
QMessageBox.critical(None, "Error", f"Failed to load markers: {e}")

def hide_tooltip_and_image(self):
if self.current_hovered_marker:
self.current_hovered_marker.hide_tooltip()
self.image_box.hide()
self.current_hovered_marker = None
def zoom_in(self):
if self.current_zoom_level * self.zoom_factor = self.min_zoom_level:
self.scale(1 / self.zoom_factor, 1 / self.zoom_factor)
self.current_zoom_level /= self.zoom_factor
def handle_image_reply(self, reply, manager):
pixmap = QPixmap()
if reply.error() == 0:
data = reply.readAll()
pixmap.loadFromData(data)
self.image_box.setPixmap(pixmap)
self.image_box.show()
# Anchor to bottom-center
self.image_box.move(
(self.viewport().width() - self.image_box.width()) // 2,
self.viewport().height() - self.image_box.height() - 10
)
reply.deleteLater()
manager.deleteLater()

def load_image(self, image_path):
pixmap = QPixmap(image_path)
if pixmap.isNull():
raise FileNotFoundError(f"Could not load map image from:  {image_path}")

# Clear existing scene and markers
self.scene.clear()
self.map_item = QGraphicsPixmapItem(pixmap)
self.scene.addItem(self.map_item)

# Set scene rect to the map image dimensions
self.setSceneRect(QRectF(pixmap.rect()))
self.markers.clear()

# Center the view on the map
self.center_on_map()

# Apply a slight zoom-out for better view
self.resetTransform()  # Corrected capitalization
self.scale(0.3, 0.3)  # Adjust zoom level as needed

def center_on_map(self):
"""Center the view on the loaded map."""
if self.map_item:
# Center the view on the map's bounding rect center
self.centerOn(self.map_item.boundingRect().center())

class MarkerEditDialog(QDialog):
def __init__(self, text="", image_link=""):
super().__init__()
self.setWindowTitle("Edit Marker")
self.resize(400, 300)  # Adjusted dialog size for better usability
self.text_edit = QTextEdit()
self.text_edit.setAcceptRichText(True)
self.text_edit.setHtml(text)
self.image_edit = QLineEdit(image_link)

form_layout = QFormLayout()
form_layout.addRow("Text:", self.text_edit)
form_layout.addRow("Image Link:", self.image_edit)

button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)

layout = QVBoxLayout()
layout.addLayout(form_layout)
layout.addWidget(button_box)

self.setLayout(layout)

def get_data(self):
return self.text_edit.toHtml(), self.image_edit.text()

class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Dead Journal")
viewer_layout = QVBoxLayout()  # Added to integrate viewer
viewer_layout.setContentsMargins(0, 0, 0, 0)
self.viewer = MapViewer()
viewer_layout.addWidget(self.viewer)

# Add Zoom In and Zoom Out buttons
self.zoom_in_button = QPushButton("Zoom In", self)
self.zoom_in_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
self.zoom_in_button.setFixedHeight(30)
self.zoom_in_button.setObjectName("zoomInButton")
self.zoom_in_button.clicked.connect(self.viewer.zoom_in)

self.zoom_out_button = QPushButton("Zoom Out", self)
self.zoom_out_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
self.zoom_out_button.setFixedHeight(30)
self.zoom_out_button.setObjectName("zoomOutButton")
self.zoom_out_button.clicked.connect(self.viewer.zoom_out)

# Add Save button
self.save_button = QPushButton("Save Markers", self)
self.save_button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
self.save_button.setFixedHeight(30)
self.save_button.setObjectName("saveButton")
self.save_button.clicked.connect(self.save_markers)

self.viewer.setParent(self)

# Button layout
button_layout = QHBoxLayout()
button_layout.setContentsMargins(0, 0, 0, 0)
button_layout.addWidget(self.zoom_in_button)
button_layout.addWidget(self.zoom_out_button)
button_layout.addWidget(self.save_button)  # Add Save button to the layout

# Main layout
layout = QVBoxLayout()
layout.setContentsMargins(0, 0, 0, 0)
layout.addLayout(viewer_layout)  # Added viewer to main layout
layout.addLayout(button_layout)

container = QWidget()
container.setLayout(layout)
self.setCentralWidget(container)
self.open_image()  # Initial map load attempt
self.center_window()  # Center the window on the screen

def save_markers(self):
"""Save markers using the viewer's save function."""
try:
self.viewer.save_markers()
QMessageBox.information(self, "Success", "Markers saved successfully!")
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to save markers:  {str(e)}")

def open_image(self):
relative_path = "IGMAP_enhanced.webp"
default_image_path = resource_path(relative_path)

if os.path.exists(default_image_path):
try:
self.viewer.load_image(default_image_path)
self.viewer.load_markers()  # Load saved markers
except FileNotFoundError as e:
QMessageBox.critical(self, "Error", f"Failed to load image: {str(e)}")
else:
QMessageBox.critical(self, "Error", f"Default image not found at: {default_image_path}")

def center_window(self):
"""Center the window on the screen."""
# Ensure the window has a fixed size before centering
self.resize(1800, 1100)  # Set the desired size for the window

# Get the available screen geometry
screen = QGuiApplication.primaryScreen().availableGeometry()

# Calculate center position
x = (screen.width() - self.width()) // 2
y = (screen.height() - self.height()) // 2

# Move the window to the center
self.move(x, y)

if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())```
Beim Ausführen dieser Karte werden die Dateien in einer JSON-Datei gespeichert. Wenn die Karte geöffnet wird, werden die gespeicherten Markierungspositionen in der JSON-Datei geöffnet. Egal was ich mache. Machen Sie den Markierungspfad relativ. Gehen Sie von festen x- und y-Positionen aus und führen Sie verschiedene Konvertierungen durch, um sicherzustellen, dass keine Positionsrundungsfehler auftreten. Ich weiß nicht, was dazu führt, dass sich die Kartenmarkierungen nach dem Speichern von ihrer ursprünglichen Position verschieben. Sie bewegen sich weiter nach oben und nach links. Dadurch habe ich das Gefühl, dass jedes Mal, wenn die JSON-Datei gespeichert wird, ein Rundungsfehler auftritt und die Markierungen immer weiter gestapelt werden, obwohl sie so weit von ihrem ursprünglichen Speicherort entfernt sind, dass es keinen Sinn macht, die Markierungen zu verwenden. Irgendwelche Ideen wären super toll.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post