CRM Projekt

Fragen zu Tkinter.
Antworten
d.christopher
User
Beiträge: 5
Registriert: Samstag 25. Juli 2020, 11:03

Moin alle zusammen,
ich habe ein neues Projekt (mein erstes Tkinter & GUI Projekt ) ich bin dabei ein lokales "customer relationship management" System mit sqlite3 als Datenbank bauen, die Ein- und Ausgabe soll dabei über die Tkinter GUI erfolgen.
Aktuell habe ich die Elementaren Funktionen zum Nutzen er Datenbank implementiert (Erstellen der Datenbank mit Table, Scheiben von Daten, Bearbeiten von Daten, Löschen von Daten) im nächsten Schritt habe ich mir über die Strukturierung der GUI gedanken gemacht.

Ich möchte das ganze nicht zu Kompliziert machen und alles auf einer Seite/Fenster Platzieren, dazu sollte am Rand eine Art Navbar mit Aktionsbuttons sein, in der Mitter der Seite sollte dann jeweils die ausgewählte Aktion nach dem Anklicken erscheinen.

Code: Alles auswählen

from tkinter import *

def mainBtn(site):
	btnLbl = ["Aktion_1", "Aktion_2",  "Aktion_3", "Aktion_4"]
	btn = [ ]
	
	for i in range(0,len(btnLbl)):
		btn.append(Button(site, text=btnLbl[i], command = lambda i=i: open_this(i, site))
		btn[i].grid( column=i+1, row = 1 )

def open_this(myNum, site):
	if myNum == 0:
		action_1(site)
	elif myNum == 1:
		action_2(site)
		
def action_1(site):
	L = Label(site, text="Aktion 1")
	L.grid( column=1, row = 2)
	
	E = Entry ( site)
	E.grid(  column=1, row = 3)
	
	B = Button(site, text = "Speichern", command = save) 
	
def action_2(site):
	L = Label(site, text="Aktion 2")
	L.grid( column=1, row = 2)
	
	E = Entry ( site)
	E.grid(  column=1, row = 3)
	
	B = Button(site, text = "Speichern", command = save) 

main = Tk()
main.title("Main Screen")
buttom(main)

main.mainloop()

Dies ist aktuell mein Beispielhafter Code, leider funktioniert dieser nicht so wie ich es mir vorstelle und nach längerer Recherche habe ich leider keine Lösung für mein Problem gefunden.

Meine Frage ist kann man überhaupt Buttons Labels und Entrys duch klicken auf einen Button (also mittels Funktion) auf der seilben Fenster ein und ausblenden.

Ich hatte auch einen anderen Ansatz mit mehreren Fenstern, das fang ich aber nicht so schön und etwas unübersichtlich.

Ich freu mich über alle Anmerkungen, Anregungen und hilfreiche Tipps.
Benutzeravatar
peterpy
User
Beiträge: 188
Registriert: Donnerstag 7. März 2013, 11:35

Hallo d.christopher,

ich weiss nicht woher dein Code stammt, bei mir funktioniert er gar nicht.
- Vergiss die Sternchenimporte!
- Eingerückt wird mit vier Leerzeichen.
- Innerhalb von Klammerausdrücken sind keine Leerzeichen erwünscht, ausser nach Kommas.
- Variablen Namen werden klein geschrieben, also nicht E, L, B
- Die Abkürzungen verwirren nur, warum schreibst Du nicht button, entry, label...

Es ist möglich Widgeets zu verstecken oder zu deaktivieren was Du möchtest.
Dann schau doch mal hier:https://anzeljg.github.io/rin2/book2/24 ... index.html
Versuch doch zuerst die Gui ganz klassisch aufzubauen, erstellst die Frames, Label, Entrys und Buttons, dann siehst Du was in deinem Code alles falsch läuft.

Gruss
Peter
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@d.christopher: Anmerkungen zum Quelltext:

Da fehlt eine Klammer damit das am Compiler vorbei kommt. Und dann gibt es die Funktion `buttom()` nirgends.

Sternchen-Importe sind Böse™. Da holt man sich gerade bei `tkinter` fast 200 Namen ins Modul von denen nur ein kleiner Bruchteil verwendet wird. Auch Namen die gar nicht in `tkinter` definiert werden, sondern ihrerseits von woanders importiert werden. Das macht Programme unnötig unübersichtlicher und fehleranfälliger und es besteht die Gefahr von Namenskollisionen.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst. Wenn man eine Funktion mit dem Namen `main()` hat, sollte man das Hauptfenster anders nennen. Das ist sonst verwirrend.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Namen sollten keine kryptischen Abkürzungen enthalten und schon gar nicht nur aus einer kryptischen Abkürzung bestehen. Wenn man `button` meint, sollte man nicht nur `btn` schreiben. `btnLbl`? Konsonanten kosten nix extra. Die darf man einfach so verwenden. Ist ja nicht Glücksrad hier. 😉

Funktionen und Methoden werden üblicherweise nach der Tätigkeit benannt die sie ausführen. `mainBtn()` ist keine Tätigkeit.

`site` ist ein ungewöhnlicher Name für Tk-Containerwidgets. Die laufen in Tk unter dem Namen `master`.

``for i in range(0, len(sequence)):`` ist in Python ein „anti pattern“. Man kann direkt über die Elemente von `sequence` iterieren, ohne den Umweg über einen Index. Falls man *zusätzlich* eine laufende Zahl benötigt, gibt es die `enumerate()`-Funktion.

In `mainBtn()` wird `btn` als Liste definiert, Objekte werden hineingesteckt, aber dann wird die Liste nirgends verwendet.

Statt des Schlüsselword-Tricks bei ``lambda`` um ein Argument zur Definitionszeit zu binden, würde ich `functools.partial()` verwenden. Das wurde extra für solche Fälle eingeführt.

Die indirektion über das komisch benannte `open_this` und magische Zahlen sollte man sich sparen.

Die Vorsilbe `my` macht bei Namen keinen Sinn. Es sei denn es gibt auch ein `ourNum` oder `theirNum` um das voneinander abzugrenzen.

In den Aktionsfunktionen sind `L`, `E`, und `B` schlechte Namen, die aber auch gar nicht wirklich gebraucht werden.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
import tkinter as tk
from functools import partial


def action_a(master):
    tk.Label(master, text="Aktion 1").grid(column=1, row=2)
    tk.Entry(master).grid(column=1, row=3)
    tk.Button(master, text="Speichern").grid(column=1, row=4)


def action_b(master):
    tk.Label(master, text="Aktion 2").grid(column=1, row=2)
    tk.Entry(master).grid(column=1, row=3)
    tk.Button(master, text="Speichern").grid(column=1, row=4)


def create_buttons(master):
    button_data = [
        ("Aktion 1", action_a),
        ("Aktion 2", action_b),
        ("Aktion 3", lambda master: None),  # TODO
        ("Aktion 4", lambda master: None),  # TODO
    ]
    for column, (button_text, action_function) in enumerate(button_data, 1):
        tk.Button(
            master, text=button_text, command=partial(action_function, master),
        ).grid(column=column, row=1)


def main():
    root = tk.Tk()
    root.title("Main Screen")
    create_buttons(root)

    root.mainloop()


if __name__ == "__main__":
    main()
Das ”funktioniert” bedingt, ist aber keine gute Idee jedes mal neue Elemente zu erzeugen die über die bereits vorhandenen Elemente in die gleichen Zellen gesetzt werden.

Was Du hier suchst ist ein `tkinter.ttk.Notebook`.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

@d.christopher: Was heißt denn "lokales CRM"? Ist das so lokal, dass nur du selbst das nutzen möchtest? An einem einzigen Arbeitsplatz? Falls nicht solltest du zumindest in Erwägung ziehen das ganze als Webprogramm umzusetzen. Nur weil es in einem Browser läuft, muss es ja nicht zwangsläufig irgendwo im Internet sein. Es funktioniert ja auch ein lokaler Webserver bzw. ein Webserver im Intranet.

Für eine wirklich aufwändige GUI würde ich dir eine andere Oberfläche als Tk empfehlen. Spätestens wenn du so etwas wie Tabellen brauchst, wirst du schnell an die Grenzen stoßen. Recht weit verbreitet, gut dokumentiert und gut an Python angebunden ist Qt. Das kannst du mit pyQt oder pyside anbinden.
Antworten