Modularise things a little

This commit is contained in:
2026-03-09 14:03:31 +11:00
parent 825ceedb0d
commit 25cd36d417
8 changed files with 173 additions and 94 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
src/__pycache__

View File

@@ -9,5 +9,5 @@ pip install -r requirements.txt
Run with: Run with:
``` ```
python app.py python src/app.py
``` ```

93
app.py
View File

@@ -1,93 +0,0 @@
from PySide6.QtCore import QSize
from PySide6.QtWidgets import QApplication, QLabel, QPushButton, QMainWindow, QWidget, QBoxLayout
from PySide6.QtGui import QPixmap
from typing import final
import sys
app = QApplication(sys.argv)
@final
class Movie:
def __init__(self, name: str, price: float, image: QWidget):
self.name = name
self.price = price
self.image = image
def createImage(filename: str) -> QWidget:
label = QLabel()
pixmap = QPixmap(filename)
label.setPixmap(pixmap.scaled(300, 300))
return label
movies = {
"spiderman": Movie("Spider-Man: Very far from home", 39.95, createImage("resources/spiderman.png")),
"cars2": Movie("Cars 2", 79.95, createImage("resources/cars2.png")),
"leo": Movie("The Nerd Movie", -189.95, createImage("resources/leo.png"))
}
class MovieView(QWidget):
def __init__(self, movie: Movie):
super().__init__()
layout = QBoxLayout(QBoxLayout.Direction.TopToBottom)
self.setWindowTitle("Movie viewer")
label1 = QLabel(f"Buying a ticket for {movie.name}")
label2 = QLabel(f"For cost ${movie.price}")
label3 = movie.image
layout.addWidget(label1)
layout.addWidget(label2)
layout.addWidget(label3)
self.setLayout(layout)
# Main Window
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.takers: list[MovieView] = []
self.setWindowTitle("Cinema Tickets");
layout = QBoxLayout(QBoxLayout.Direction.LeftToRight)
self.spiderman: QPushButton = QPushButton("Buy tickets for spider man");
self.spiderman.setCheckable(True)
_ = self.spiderman.clicked.connect(self.buySpiderman)
layout.addWidget(self.spiderman)
self.cars: QPushButton = QPushButton("Buy tickets for cars 2");
self.cars.setCheckable(True)
_ = self.cars.clicked.connect(self.buyCars)
layout.addWidget(self.cars)
self.leo: QPushButton = QPushButton("Buy tickets for the nerd movie");
self.leo.setCheckable(True)
_ = self.leo.clicked.connect(self.buyLeo)
layout.addWidget(self.leo)
centralWidget = QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
def buySpiderman(self):
self.setCentralWidget(MovieView(movies["spiderman"]))
def buyLeo(self):
self.setCentralWidget(MovieView(movies["leo"]))
def buyCars(self):
self.setCentralWidget(MovieView(movies["cars2"]))
window = MainWindow()
window.show()
exit(app.exec())

BIN
resources/hairypotty.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

37
src/Movie.py Normal file
View File

@@ -0,0 +1,37 @@
from PySide6.QtWidgets import QWidget, QLabel
from PySide6.QtGui import QPixmap
from typing import final
@final
class Movie:
"""
Describes a movie which will be displayed in the GUI.
Usage:
Movie("Movie name", <Movie price>, "Path to movie cover image")
"""
def __init__(self, name: str, price: float, image_path: str, description: str):
self.name = name
self.price = price
self.image_path = image_path
self.description = description
def createImage(filename: str) -> QLabel:
"""
Creates an image (in form of a QLabel) from a provided filename.
The filename must be a path to the image file.
It does not have to be an absolute path.
"""
label = QLabel()
pixmap = QPixmap(filename)
label.setPixmap(pixmap.scaled(300, 450))
return label
"""
Dictionary mapping strings (movie ID's) to Movie() objects.
"""
movies = {
"spiderman": Movie("Spider-Man: Very far from home", 39.95, "resources/spiderman.png", "spiderman, spiderman, he's a spider, and he's a man"),
"cars2": Movie("Cars 2", 79.95, "resources/cars2.png", "I am speed"),
"leo": Movie("The Nerd Movie", -189.95, "resources/leo.png", "Did you know that the quadratic formula is negative b plus or minus square root of b squared minus 4 a c all divided by 2 a"),
"hairypotty": Movie("Harry Potter and the Deathly Weapons", 447.95, "resources/hairypotty.png", "Dobby's got a glock")
}

30
src/MovieButton.py Normal file
View File

@@ -0,0 +1,30 @@
from typing import Callable
from PySide6.QtGui import QMouseEvent
from PySide6.QtWidgets import QVBoxLayout, QWidget, QLabel
from PySide6.QtCore import QTimer
from Movie import Movie, createImage
class MovieButton(QWidget):
"""
Buttons for selecting the movie on the main screen.
Usage:
MovieButton(Movie(...), self.show<Movie>)
"""
def __init__(self, movie: Movie, callback: Callable[[], None]):
super().__init__()
layout = QVBoxLayout()
self.movie: Movie = movie
layout.addWidget(createImage(movie.image_path))
layout.addWidget(QLabel(movie.name))
self.setLayout(layout)
self.callback: Callable[[], None] = callback
def mousePressEvent(self, event: QMouseEvent):
QTimer.singleShot(0, self.callback)

40
src/MovieView.py Normal file
View File

@@ -0,0 +1,40 @@
from PySide6.QtGui import Qt
from Movie import Movie, createImage
from PySide6.QtWidgets import QHBoxLayout, QPushButton, QWidget, QGridLayout, QLabel
class MovieView(QWidget):
"""
A QWidget which shows details about a given movie.
Shows cover image, title, price, description.
Also provided a button for buying tickets to the movie.
"""
def __init__(self, movie: Movie):
super().__init__()
self.setMaximumWidth(800)
self.setMaximumHeight(600)
# Create layouts
bodylayout = QHBoxLayout()
contentlayout = QGridLayout()
# Create labels and buttons
label1 = QLabel(f"Buying a ticket for {movie.name}\nFor cost ${movie.price}")
label1.setWordWrap(True)
label2 = QLabel(movie.description)
label2.setWordWrap(True)
label3 = createImage(movie.image_path)
button1 = QPushButton("Buy")
button1.setMaximumWidth(100)
contentlayout.addWidget(label1, 0, 0, alignment=Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)
contentlayout.addWidget(label2, 1, 0, alignment=Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)
contentlayout.addWidget(button1, 1, 0, alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignLeft)
bodylayout.addWidget(label3)
bodylayout.addLayout(contentlayout)
self.setLayout(bodylayout)

64
src/app.py Normal file
View File

@@ -0,0 +1,64 @@
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QHBoxLayout
from typing import final
import sys
from Movie import movies
from MovieView import MovieView
from MovieButton import MovieButton
# Main Window
@final
class MainWindow(QMainWindow):
"""
The main window for Max's movie tickets application.
Usage:
window = MainWindow()
window.show()
"""
currentMovie: MovieView | None = None
def __init__(self):
super().__init__()
self.setWindowTitle("Cinema Tickets")
# Create the layout for all the movies
layout = QHBoxLayout()
# Create the buttons for each movie
self.spiderman = MovieButton(movies["spiderman"], self.buySpiderman)
layout.addWidget(self.spiderman)
self.cars = MovieButton(movies["cars2"], self.buyCars)
layout.addWidget(self.cars)
self.leo = MovieButton(movies["leo"], self.buyLeo)
layout.addWidget(self.leo)
self.hairypotty = MovieButton(movies["hairypotty"], self.buyHairyPotty)
layout.addWidget(self.hairypotty)
centralWidget = QWidget()
centralWidget.setLayout(layout)
self.setCentralWidget(centralWidget)
# Callback functions to set the movie
def buySpiderman(self):
self.currentMovie = MovieView(movies["spiderman"])
self.currentMovie.show()
def buyLeo(self):
self.currentMovie = MovieView(movies["leo"])
self.currentMovie.show()
def buyCars(self):
self.currentMovie = MovieView(movies["cars2"])
self.currentMovie.show()
def buyHairyPotty(self):
self.currentMovie = MovieView(movies["hairypotty"])
self.currentMovie.show()
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())