flandre/draft/pyqt_avif.py

132 lines
4.0 KiB
Python
Raw Normal View History

2025-06-11 20:13:53 +08:00
import io
import sys
from pathlib import Path
from PIL import Image
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QImage, QPixmap
from PyQt6.QtWidgets import (
QApplication,
QGraphicsPixmapItem,
QGraphicsScene,
QGraphicsView,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
# For PyQt5 users, change the imports above to this:
# from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QVBoxLayout, QWidget, QPushButton, QFileDialog
# from PyQt5.QtGui import QPixmap
# from PyQt5.QtCore import Qt
class ZoomableView(QGraphicsView):
"""
A custom QGraphicsView that provides zoom functionality with the mouse wheel.
"""
def __init__(self, scene):
super().__init__(scene)
# Set anchor points for zooming and resizing
self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
self.setResizeAnchor(QGraphicsView.ViewportAnchor.AnchorViewCenter)
def wheelEvent(self, event):
"""
Handles mouse wheel events to zoom in or out.
"""
# Get the amount of scroll
angle = event.angleDelta().y()
if angle > 0:
# Zoom in
factor = 1.25
else:
# Zoom out
factor = 0.8
self.scale(factor, factor)
class ImageViewer(QMainWindow):
"""
Main application window for viewing an image.
Includes loading, zooming, and panning functionality.
"""
def __init__(self):
super().__init__()
self.setWindowTitle("PyQt Image Viewer (Load, Zoom, Pan)")
self.setGeometry(100, 100, 800, 700)
# Main widget and layout
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
# 1. Create the QGraphicsScene
# The scene is the container for all 2D graphical items
self.scene = QGraphicsScene()
# 2. Create the custom QGraphicsView
# This is our custom view with zoom capabilities
self.view = ZoomableView(self.scene)
# 3. Enable panning (drag the scene with the mouse)
# The hand cursor will appear when you click and drag.
self.view.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
# Add a button to load an image
self.load_button = QPushButton("Load Image")
self.load_button.clicked.connect(self.load_image)
# Add widgets to the layout
layout.addWidget(self.load_button)
layout.addWidget(self.view)
# A variable to hold the currently displayed image item
self.pixmap_item = None
def load_image(self):
file_path = Path(
"/home/lambda/Downloads/f546ed6d35ee05338b8403d57dda10103ac3b1b8.jpg@672w_378h_1c_!web-home-common-cover.avif"
)
image_data = file_path.read_bytes()
im = Image.open(io.BytesIO(image_data))
pixmap = QPixmap.fromImage(
QImage(im.tobytes(), im.size[0], im.size[1], QImage.Format.Format_RGB888)
)
if pixmap.isNull():
print(f"Error: Failed to load image from {file_path}")
return
# If an image is already loaded, remove the old one first
if self.pixmap_item:
self.scene.removeItem(self.pixmap_item)
# 5. Create a QGraphicsPixmapItem to hold the image
self.pixmap_item = QGraphicsPixmapItem(pixmap)
# 6. Add the item to the scene
self.scene.addItem(self.pixmap_item)
# --- Optional: Improve the viewing experience ---
# Reset any previous transformations (like zoom/pan)
self.view.resetTransform()
# Fit the entire image within the view, maintaining aspect ratio
self.view.fitInView(self.pixmap_item, Qt.AspectRatioMode.KeepAspectRatio)
if __name__ == "__main__":
# Create the application instance
app = QApplication(sys.argv)
# Create and show the main window
viewer = ImageViewer()
viewer.show()
# Start the application's event loop
sys.exit(app.exec())