@ThePaulCraft: Anmerkungen zum Quelltext:
Eingerückt wird mit vier Leerzeichen pro Ebene, nicht mit Tabs.
Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.
Dateien die man öffnet, sollte man auch wieder schliessen. Am besten verwendet man wo das möglich ist, die ``with``-Anweisung beim öffnen. Bei Textdateien sollte man explizit die Kodierung angeben.
Falls man den gesamten Dateiinhalt in eine Zeichenkette lesen möchte, hat `pathlib.Path` dafür eine Methode. Das sollte man auch anstelle vom `glob`-Modul verwenden.
Das Icon würde ich eher auf dem `QApplication`-Objekt setzen als auf individuellen Fenstern.
Vergiss das es ``global`` gibt. Funktionen und Methoden bekommen alles was sie ausser Konstanten benötigen als Argument(e) übergeben.
`QWidget.setLayout()` sollte nur einmal aufgerufen werden, das macht gar keinen Sinn das immer mit dem selben `QLayout`-Objekt aufzurufen. Und wenn man `QWidget`\s in ein `QLayout` steckt, dann übernimmt das die Elternrolle, man braucht also `win` in den Funktionen nicht.
Funktions- und Methodennamen beschreiben üblicherweise die Tätigkeit die von der Funktion oder Methode durchgeführt wird. Der Leser weiss dann was die tun und kann sie von eher passiven Werten unterscheiden.
`frame1` und `recipe_frame` sind keine Tätigkeiten. Und bei `frame1` ist auch die 1 unsinnig.
Beide Funktionen löschen als erstes alle Elemente aus dem Layout, wobei ich mir nicht sicher bin, dass das so unfallfrei funktioniert, denn es wird zwar `deleteLater()` auf den `QWidget`-Objekten aufgerufen, aber die `QLayoutItem`-Objekte werden nicht gelöscht. Damit handelt man sich eventuell Probleme/ein Speicherleck ein. Die Qt-Dokumentation zeigt zum sicheren entfernen ein Codeschnippsel in dem solange ``takeAt(0)`` auf dem `QLayout`-Objekt aufgerufen wird, bis das einen Nullpointer liefert. Und das sollte man in eine eigene Funktion auslagern.
Pfad und Dateinamen mit Zeichenkettenoperationen zu bearbeiten ist kaputt. Auch hier ist `pathlib.Path` hilfreich. Das hat ganz einfach ein Attribut für den Dateinamen ohne Dateinamenserweiterung.
Im Grunde werden die Rezeptdateien in einer zufälligen Reihenfolge aufgelistet. Denn in welcher Reihenfolge die geliefert werden ist nirgends garantiert. Das hängt vom Betriebs- und Dateisystem ab. Man sollte die also sortieren wenn man die in einer vorhersehbaren Reihenfolge anzeigen möchte.
Ein `QGridLayout` bei dem Grundsätzlich nur die erste Spalte verwendet wird, kann durch ein `QHBoxLayout` ersetzt werden.
Den Unterstrich bei `exec_()` sollte man weglassen, die Methode wird es unter diesem Namen in PyQt6 nicht mehr geben.
Zwischenstand (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python3
import sys
from functools import partial
from pathlib import Path
from PyQt5 import QtCore
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (
QApplication,
QHBoxLayout,
QLabel,
QPushButton,
QWidget,
)
RECIPES_PATH = Path("recipes")
BUTTON_STYLE_FILE_PATH = Path("style_buttons.css")
def clear_layout(layout):
while True:
item = layout.takeAt(0)
if not item:
break
item.widget().deleteLater()
def replace_content_with_recipe(layout, recipe_text):
clear_layout(layout)
layout.addWidget(
QPushButton(
"Zurück",
styleSheet=BUTTON_STYLE_FILE_PATH.read_text(encoding="utf-8"),
clicked=partial(replace_content_with_recipe_choice, layout),
)
)
layout.addWidget(QLabel(recipe_text))
def replace_content_with_recipe_choice(layout):
clear_layout(layout)
layout.addWidget(
QLabel(
"🍔Rezepte🍕",
alignment=QtCore.Qt.AlignCenter,
styleSheet="font-size: 30px;\nfont-family: Arial;",
)
)
for recipe_path in sorted(RECIPES_PATH.glob("*.txt")):
layout.addWidget(
QPushButton(
recipe_path.stem,
styleSheet=BUTTON_STYLE_FILE_PATH.read_text(encoding="utf-8"),
clicked=partial(
replace_content_with_recipe,
layout,
recipe_path.read_text(encoding="utf-8"),
),
)
)
def main():
app = QApplication(
sys.argv, applicationName="Rezepte", windowIcon=QIcon("icon.png")
)
app.setStyle("Fusion")
window = QWidget(styleSheet=Path("style.css").read_text(encoding="utf-8"))
layout = QHBoxLayout()
replace_content_with_recipe_choice(layout)
window.setLayout(layout)
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
Das mit dem austauschen des Layout-Inhalts ist total ungewöhnlich, das würde man so nicht machen. Man erstellt GUI-Elemente in der Regel am Anfang komplett und ersetzt dann nur noch die angezeigten Inhalte. Wenn in einem Elternwidget zwei unterschiedliche Inhalte angezeigt werden sollen, dann verwendet man beispielsweise ein `QStackedWidget` und schaltet dort zwischen zwei Widgets mit den Inhalten um.
Das ist so auch ineffizient immer die gleichen Rezepte wieder und wieder einzulesen.