ich komme momentan nicht weiter.
Habe zwei Bücher zur Fehlersuche, sowie mehrere Stunden Internet zu rate gezogen und finde keine Lösung.
Fehlerbeschreibung:
Das "Programm" erledigt die bis zum jetzigen Punkt geschriebenen Sachen.
Perfekt programmiert ist es aber wohl kaum.
Es sind zwei Fehler die ich nicht lösen kann.
1. Wenn im GUI die Schaltflächen "Statistik anzeigen", sowie "Bestellung anzeigen" gedrückt werden,
wird jeweils ein neues Fenster erzeugt. In diesen neuen Fenstern wird aber links oben ein Knopf angezeigt
der hier nichts verloren hat.
2. Das ist jetzt mein schwerwiegenderes Problem. Über die beiden Schaltflächen "Statistik anzeigen" und "Bestellung anzeigen"
wird jeweils ein neues Fenster geöffnet, welches ein Kind von Mainwidow ist. Da der Aritkelbestand sich aber in der Elternklasse
befindet, weiß ich nicht wie ich diesen auch von den Kindern aufrufbar/bearbeitbar machen kann.
Der Interpreter meldet mir beim aufruf der Funktion "Statistik anzeigen", dass er im __init__ zwei "Argumente" übergeben haben möchte.
Dies ist zwar verständlich warum, aber woher soll ich die nehmen?
Code: Alles auswählen
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
import csv
import re
import ast
import json
import datetime
from collections import OrderedDict
from PyQt5 import QtCore
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, \
QHBoxLayout, QLineEdit, QPushButton, QTextEdit, \
QCompleter, QTableWidget, QTableWidgetItem, \
QInputDialog, QMessageBox, QAbstractItemView, \
QTreeView, QComboBox, QFormLayout
class Lager():
def __init__(self):
self.artikelbestand = OrderedDict()
# Beinhaltet alle eingelesen Artikel aus der Csv Datei im Format
# OrderedDict(Artikelnummer : {"Artikelbezeichnung": "str",
# "Menge": "int", "Einheit": "str", "VPE": "int",
# "E.-Pr.Ne": "float", "Steuersatz" : "float", "E.-Pr. Br." : "float",
# "Geb.-Pr. Ne." : "float", "Geb.-Pr. Br" : "float",
# "Lieferant" : "str", "Artikelnummer" : "int",
# "Bestellstatus" : "bool", "Bestellmenge" : "int" }
self.feldnamen = [] # Benötigt zur Erstellung der Feldnamen der Tabelle
def artikel_aus_csv_laden(self, csvdatei):
# Einlesen von Dateien aus der übergeben CSV Datei
with open(csvdatei, "r", encoding="utf-8", newline="") as csvfile:
reader = csv.DictReader(csvfile, delimiter=";")
self.feldnamen = reader.fieldnames
# Es werden die Feldnamen der CSV Datei in die Instanzvariable
# self.feldnamen übergeben. Diese werden später in der Funktion
# tabelle_erzeugen gebraucht, um die Header Labels des Tabellenwid -
# gets zu beschriften.
reader = sorted(reader, key=lambda d: d["Artikelbezeichnung"])
# Die einzelnen Zeilen des readerobjects werden nach ihren Namen
# sortiert, damit immer eine Alphabetische Reihenfolge unabhängig
# von der Eintragung in die CSV Datei vorliegt. Die Artikelnummern
# Können daher durcheinander sein.
vortlaufendenummer = 1
# Zähler der die Artikelnummer des einzelnen Artikels festlegt und
# die Maximale Anzahl aller Dateien in der CSV Datei erfasst.
meldung_auf_konsole_ausgeben("folgende Artikel wurden aus der CSV "\
"Datei eingelesen")
for zeile in reader:
zeile = {k:v if v != "" else "0" for (k,v) in zeile.items()}
# Es wird jede Zeile geprüft, ob sich darin leere Zellen befin -
# den und diese dann mit einer 0 im Stringformat aufgefüllt.
# Das Stringformat ist wichtig, da wenn er in einer Zelle einge-
# fügt wird auf die später die int() funktion angewandt wird
# erscheint eine Fehlermeldung.
zeile["Menge"] = float(zeile["Menge"].replace(",","."))
zeile["VPE"] = int(zeile["VPE"])
zeile["E.-Pr. Ne."] = float(zeile["E.-Pr. Ne."]\
.replace(",","."))
zeile["Steuersatz"] = float(zeile["Steuersatz"]\
.replace(",","."))
zeile["E.-Pr. Br."] = float(zeile["E.-Pr. Br."]\
.replace(",","."))
zeile["Geb.-Pr. Ne."] = float(zeile["Geb.-Pr. Ne."]\
.replace(",","."))
zeile["Geb.-Pr. Br."] = float(zeile["Geb.-Pr. Br."]\
.replace(",","."))
zeile["Artikelnummer"] = int(zeile["Artikelnummer"])
zeile["Bestellstatus"] = ast.literal_eval(zeile\
["Bestellstatus"])
zeile["Bestellmenge"] = int(zeile["Bestellmenge"])
# Es werden die jeweiligen Zellen in bestimmte Formate forma -
# tiert umd diese später besser bearbeiten zu können.
self.artikelbestand[vortlaufendenummer] = OrderedDict(zeile)
# Dem OrderedDict wird ein Schlüssel/Wert - Paar hinzugefügt.
# Format -> Vortlaufendenummer : {}
# Die Vortlaufendenummer dient als interne Artikelnummer.
# Die Artikelnummern dienen nur zur einzigartigen Durchnum -
# merierung, sie werden nicht zur Artikelsuche benötigt.
print(self.artikelbestand[vortlaufendenummer])
# Nur zum Debuggen
vortlaufendenummer += 1
def artikel_in_csv_schreiben(self, tabelle, csvdatei, feldnamen):
# Speichern der Werte aus der übergebenen Tabelle in die angegebene CSV -
# Datei. Es werden alle Zeilen der Tabelle neu gschrieben, nicht nur die
# die sich geändert haben.
with open(csvdatei, "w", newline="", encoding="utf-8") as csvfile:
writer = csv.writer(csvfile, delimiter=";")
writer.writerow(feldnamen)
# Als erste Zeile werden die Feldnamen in die CSV-Datei geschrieben
for zeile in tabelle:
writer.writerow(tabelle[zeile].values())
class Zulieferer():
def __init__(self):
self.lieferanten = OrderedDict()
# Beinhaltet alle Angaben zu den Lieferanten aus der in die CSV Datei
# erhaltenen Werte im Format:
# OrderedDict(Vortlaufendenummer : {'Name': 'str',
# 'Strasse': 'str', 'Hausnummer': 'str', 'PLZ': 'int',
# 'Ort': 'str', 'Telefonnummer': 'int', 'Email': 'str',
# 'Kundennummer': 'int'})
self.feldnamen = []
# self.feldnamen enthalten die Feldnamen aus der eingelesenen CSV Datei
def zulieferer_aus_csv_laden(self, csvdatei):
# Einlesen von Dateien aus der übergeben Csv Datei
with open(csvdatei, "r", encoding="utf-8", newline="") as datei:
reader = csv.DictReader(datei, delimiter=";")
self.feldnamen = reader.fieldnames
# Es werden die Feldnamen der CSV Datei in die Instanzvariable
# self.feldnamen übergeben. Diese werden später in der Funktion
# tabelle_erzeugen gebraucht, um die Header Labels des Tabellenwid -
# gets zu beschriften.
reader = sorted(reader, key=lambda d: d["Name"])
# Die einzelnen Zeilen des readerobjects werden nach dem Namen des
#Lieferanten sortiert, damit immer eine Alphabetische Reihenfolge
# unabhängig von der Eintragung in die CSV Datei vorliegt. Die Namen
# Können daher durcheinander sein.
vortlaufendenummer = 1
meldung_auf_konsole_ausgeben("folgende Lieferanten wurden aus der "\
"CSV Datei eingelesen")
for zeile in reader:
self.lieferanten[vortlaufendenummer] = zeile
# Dem OrderedDict wird ein Schlüssel/Wert - Paar hinzugefügt.
# Format -> Vortlaufendenummer : {}
# Die Vortlaufendenummer dient als interne Lieferantennummer.
# Die Lieferantennummern dienen nur zur einzigartigen Durchnum -
# merierung, sie werden nicht zur Lieferantensuche benötigt.
print(self.lieferanten[vortlaufendenummer])
# Nur zum Debuggen
vortlaufendenummer += 1
def zulieferer_in_csv_schreiben(csvdatei):
pass
class Mainwindow(QWidget):
def __init__(self, lager, zulieferer):
super().__init__()
self.lager = lager
self.zulieferer = zulieferer
self.fenstereinstellungen()
self.erzeugeWidgets()
self.erzeugeLayout()
self.autovervollstaendigung()
self.show()
def fenstereinstellungen(self):
self.resize(1500, 600)
self.setWindowTitle("Bestellung V 1.0")
def erzeugeWidgets(self):
self.label1 = QLabel()
self.tablewidget = QTableWidget()
self.tablewidget.setEditTriggers(QTreeView.NoEditTriggers)
self.tablewidget.setSelectionBehavior(QAbstractItemView.SelectRows)
self.tablewidget.setSelectionMode(QAbstractItemView.SingleSelection)
self.suchleiste = QLineEdit(self)
self.suchleiste.returnPressed.connect(lambda: self.artikel_suchen_und_anzeigen("Artikelbezeichnung"))
self.suchleiste.setToolTip("Artikelbezeichnung, oder Artikelnummer "\
"eingeben")
self.sf_suche = QPushButton("Suchen", self)
self.sf_suche.clicked.connect(lambda: self.artikel_suchen_und_anzeigen("Artikelbezeichnung"))
self.sf_bestellen = QPushButton("Artikel bestellen", self)
self.sf_bestellen.clicked.connect(self.artikel_bestellen)
self.sf_bestellung = QPushButton("Bestellung anzeigen", self)
self.sf_bestellung.clicked.connect(self.bestellung_fenster_oeffnen)
self.sf_statistik = QPushButton("Statistik anzeigen", self)
self.sf_statistik.clicked.connect(self.statistik_fenster_oeffnen)
self.sf_ende = QPushButton("Beenden", self)
self.sf_ende.clicked.connect(self.fenster_schliessen)
def erzeugeLayout(self):
vbox1 = QVBoxLayout()
vbox1.addWidget(self.label1)
vbox1.addWidget(self.tablewidget)
hbox1 = QHBoxLayout()
hbox1.addWidget(self.suchleiste)
hbox1.addWidget(self.sf_suche)
hbox2 = QHBoxLayout()
hbox2.addWidget(self.sf_bestellen)
hbox2.addWidget(self.sf_bestellung)
hbox2.addWidget(self.sf_statistik)
hbox2.addWidget(self.sf_ende)
masterbox = QVBoxLayout()
masterbox.addLayout(hbox1)
masterbox.addLayout(vbox1)
masterbox.addLayout(hbox2)
self.setLayout(masterbox)
def tabelle_erzeugen(self, artikelnummernliste):
self.tablewidget.setColumnCount(len(self.lager.feldnamen))
self.tablewidget.setHorizontalHeaderLabels(self.lager.feldnamen)
self.tablewidget.setRowCount(len(artikelnummernliste))
zeile = -1
meldung_auf_konsole_ausgeben("folgende Artikel wurden in die Tabelle" \
" geschrieben")
for artikelnummer in artikelnummernliste:
zeile += 1
spalte = 0
print(self.lager.artikelbestand[artikelnummer])
# Nur zur Fehlersuche, gibt alle gefundenden Einträge aus dem
# OrderedDict auf der Konsole aus.
for schluessel in self.lager.artikelbestand[artikelnummer]:
self.tablewidget.setItem(zeile, spalte, \
QTableWidgetItem(str(self.lager.\
artikelbestand[artikelnummer]\
[schluessel])))
spalte += 1
self.label1.setText("Es wurden " + str(len(artikelnummernliste)) + \
" Artikel gefunden")
def artikel_suchen_und_anzeigen(self, feldfilter):
# Es wird in der Instanz der Klasse "Lager" nach den eingegebenen Text-
# teilen in den angegebenen Feldnamen hier genannt "feldfilter" gesucht
# und gibt diese dann durch aufruf der tabelle_erzeugen funktion aus.
durchlaufzaehler = 0
suchbegriff = "".join(["[" + str(zeichen).upper() +\
str(zeichen).lower() + "]"\
for zeichen in self.suchleiste.text()])
# Formatieren der eingegebenen Zeichenkette von Brot -> [Bb[Rr][Oo][Tt]
meldung_auf_konsole_ausgeben("Die Suche nach der Zeichenkette" \
" ergab folgende Nummern")
print("Gesuchte Zeichenkette: " + suchbegriff)
gefundene_artikelnummern = []
# Behälter für alle Artikelnummern bei denen die gesuchte Zeichenfolge
# passt.
for artikelnummer in self.lager.artikelbestand:
if re.findall(suchbegriff, self.lager.artikelbestand\
[artikelnummer][feldfilter]):
gefundene_artikelnummern.append(artikelnummer)
# Durchsuchen aller Artikelbezeichnungen, ob der Suchbegriff darin
# vorkommt. Passt der Suchbegriff, wird dessen Artikelnummer in die
# Liste gefundene_Artiklnummern geschrieben um damit die entsprech-
# ende Tabelle zu füllen
durchlaufzaehler += 1
print("Artikelnummern in denen die gesuchte Zeichenkette vorkommt: " +
str(gefundene_artikelnummern))
# Ausgabe zur möglichen Fehlersuche
self.tabelle_erzeugen(gefundene_artikelnummern)
def artikel_bestellen(self):
#
# Auswahl der zu bestellenden Menge die dem Artikel hinterlegt werden soll
artikelauswahl = self.tablewidget.selectedItems()
if artikelauswahl != []:
# Prüfung ob aus der Tabelle eine Zeile angewählt wurde
bestellmenge, check = QInputDialog.getInt(self, "Bestellmenge",
"Zu bestellenden Menge eingeben:",
value=1, min=0)
# Aufruf einer Dialogbox, bei der die gewünschte Bestellmenge ausge-
# wählt werden kann und der Variable "bestellmenge" übergeben wird
if check:
# Abfrage ob "Ok" im Abfragefeld ausgewählt wurde
for artikelnummer in self.lager.artikelbestand:
# Es werden alle Artikelnummern die sich im Container
# self.warenbestand.lager nacheinander aufgerufen.
if self.lager.artikelbestand[artikelnummer]\
["Artikelbezeichnung"] == artikelauswahl[0].text():
# Wird der Artikelname gefunden, der zur Auswahl
# passt wird die alte Bestellmenge auf die neu eingegebene
# gesetzt und der Bestellstatus auf True gesetzt.
self.lager.artikelbestand[artikelnummer]\
["Bestellmenge"] = bestellmenge
if bestellmenge != 0:
# Es wird geprüft, ob die eingebenen Zahl den Wert
# ungleich 0 aufweist, dann wird der Bestellstatus auf
# "Wahr" gesetzt. Andernfalls, ist die Bestellmenge 0,
# so wird der Bestellstatus auf "Falsch" gesetzt, da ja
# Auch keine Menge des Artikels mehr benötigt wird.
self.lager.artikelbestand[artikelnummer]\
["Bestellstatus"] = True
else:
self.lager.artikelbestand[artikelnummer]\
["Bestellstatus"] = False
meldung_auf_konsole_ausgeben("Es wurde die "\
"Bestellmenge " + str(bestellmenge) + \
" zum Artikel \"" + self.lager.artikelbestand\
[artikelnummer]["Artikelbezeichnung"] +
"\" hinzugefügt")
# Ausgabe auf der Konsole, nur zur Fehlersuche
self.tabelle_erzeugen(list(range(1,len(\
self.lager.artikelbestand)\
+1)))
self.lager.artikel_in_csv_schreiben(
self.lager.artikelbestand,\
"./Listen/Artikelliste.csv",\
self.lager.feldnamen)
break
else:
print("es wurde KEIN Artikel ausgewählt!")
QMessageBox.information(self, "Auswahl", "Um eine Bestellmenge"\
" hinzufügen zu können bitte erst"\
" einen Artikel aus der Tabelle"\
"auswählen!")
def autovervollstaendigung(self):
autocomplete = QCompleter([self.lager.artikelbestand[nummer]["Artikelbezeichnung"] for nummer in self.lager.artikelbestand])
self.suchleiste.setCompleter(autocomplete)
def bestellung_fenster_oeffnen(self):
self.bestellfenster = Bestellwindow()
def statistik_fenster_oeffnen(self):
self.statistikfenster = Statistikwindow()
def fenster_schliessen(self):
reply = QMessageBox.question(self, "Achtung", "Möchten Sie die "\
"Anwendung wirklich beenden?", \
QMessageBox.Yes | QMessageBox.No, \
QMessageBox.No)
if reply == QMessageBox.Yes:
QCoreApplication.quit()
class Bestellwindow(Mainwindow):
def __init__(self):
Mainwindow.__init__(self)
def fenstereinstellungen(self):
self.setWindowTitle("Bestellung nach Lieferant")
self.resize(500, 600)
def erzeugeWidgets(self):
Mainwindow.erzeugeWidgets(self)
self.label1.setText("Lieferant auswählen:")
self.cb_lieferanten = QComboBox()
self.sf_senden = QPushButton("Bestellung senden", self)
#self.sf_senden.click.connect(self.bestellung_an_lieferanten_senden)
def erzeugeLayout(self):
hbox1 = QHBoxLayout()
hbox1.addWidget(self.label1)
hbox1.addWidget(self.cb_lieferanten)
hbox2 = QHBoxLayout()
hbox2.addWidget(self.sf_senden)
hbox2.addWidget(self.sf_ende)
masterbox = QVBoxLayout()
masterbox.addLayout(hbox1)
masterbox.addWidget(self.tablewidget)
masterbox.addLayout(hbox2)
self.setLayout(masterbox)
def bestellung_an_lieferanten_senden(self):
pass
def fenster_schliessen(self):
self.close()
class Statistikwindow(Mainwindow):
def __init__(self):
super().__init__()
def fenstereinstellungen(self):
self.setWindowTitle("Bestellstatistiken")
self.resize(800, 600)
def erzeugeWidgets(self):
super().erzeugeWidgets()
self.label_artikelname = QLabel()
self.label1.setText("Statistik zum Artikel:")
def erzeugeLayout(self):
hbox1 = QHBoxLayout()
hbox1.addWidget(self.suchleiste)
hbox1.addWidget(self.sf_suche)
hbox2 = QHBoxLayout()
hbox2.addWidget(self.label1)
hbox2.addWidget(self.label_artikelname)
masterbox = QVBoxLayout()
masterbox.addLayout(hbox1)
masterbox.addLayout(hbox2)
masterbox.addWidget(self.tablewidget)
masterbox.addWidget(self.sf_ende)
self.setLayout(masterbox)
def fenster_schliessen(self):
self.close()
def meldung_auf_konsole_ausgeben(text):
print("-" * (len(text)+4))
print("| " + text + " |")
print("-" * (len(text)+4))
def main():
lager = Lager()
lager.artikel_aus_csv_laden("./Listen/Artikelliste.csv")
zulieferer = Zulieferer()
zulieferer.zulieferer_aus_csv_laden("./Listen/Lieferantenliste.csv")
app = QApplication(sys.argv)
mw = Mainwindow(lager, zulieferer)
mw.tabelle_erzeugen(tuple(mw.lager.artikelbestand.keys()))
sys.exit(app.exec_())
if __name__ == "__main__":
main()