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.
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()
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())
# 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)}")
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_())``` [/code] 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.
Ich stehe vor dem folgenden Problem:
Wenn ich bei normaler Nutzung der App auf der Root-Route (/) die Zurück-Taste drücke, wird die App geschlossen. Bisher ist dieses Verhalten in Ordnung und...
Wenn ich meine Python -Datei ausführe, funktioniert alles zum ersten Mal gut. Aber am Ende braucht es Benutzereingaben, und wenn der Benutzer den Code wiedergeben möchte, wird der Abrufstunde nicht...
Vor kurzem verwende ich Laravel, um meine Buchungsdienstanwendungen zu entwickeln. Ich habe die Route und die Methode bereits richtig gesetzt, aber das Problem beginnt, wenn ich auf die Schaltfläche...
Bitte sagen Sie mir, wie ich das Albumcover-Bild eines mp3 -Songs extrahieren kann, das mit einem HTML5--Element verknüpft ist, sobald die Metadaten geladen werden, ohne dass dies erforderlich ist...