MAC-Adessen Format Wandler

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

Hallo Leute,

Kurz zur allgemeinen Situation :)
Ich arbeite als Informatiker im Bereich der Netzwerktechnik, nun habe ich, und bestimmt auch andere, das Problem dass die meisten Programme eine MAC-Adresse nicht mit jedem Trennzeichen akzeptieren.
Zum Beispiel akzeptiert der DHCP sie nur ohne Trennzeichen und andere Programme nur mit ":" als Trennzeichen.
Nun wollte ich ein Programm welches mir die Trennzeichen entfernt bzw. hinzufügt.
Nachdem ich im Internet nichts Brauchbares gefunden habe, habe ich mich also selbst einmal darüber gemacht ein solches "Programm" zu schreiben.
Mein einziges Problem war, ich kann nicht Programmieren :D :D .
Also habe ich mich durch das Internet und sonstige Tutorials für Python gekämpft bis ich es geschafft habe das mein erstes Python Programm funktioniert und das tut was es soll.
Der Name "Format Wandler" ist zwar nicht ganz korrekt, da hier nur die Trennzeichen geändert werden aber mir ist nichts Treffenderes eingefallen.

Das "Programm" funktioniert wie folgt.
  1. Beim Starten erscheint ein Fenster in dem Man eine MAC-Adresse eingeben kann. Die Eingabe kann ohne Trennzeichen und mit ":" oder "-" als Trennzeichen erfolgen.
  2. Mit "Enter" oder einem Klick auf den Button "Show" wird dann die MAC in drei möglichen Varianten angezeigt
  1. Mac ohne Trennzeichen
  2. Mac mit Doppelpunkt als Trennzeichen
  3. Mac mit Bindestrich als Trennzeichen

So nun habe ich ein Programm welches seinen Zweck erfüllt und habe gelernt mit Python zu Programmieren.
Ich weiß aber nicht ob es gut oder schlecht Programmiert ist, ob ich zu viel sinnlosen Code eingebaut habe.
Da habe ich mir gedacht ich poste mein "Programm" einmal hier und lasse es von euch auseinandernehmen.

Ich möchte hier kein komplett überarbeitetes Programm von euch haben. Sondern lediglich konstruktive Kritik an meinem Programm.

Außerdem habe ich ein paar Fragen.
  1. In meinem Code nutze ich den Befehl

    Code: Alles auswählen

    e1.insert(10,getclip)
    Diesen Code habe ich durch goggeln gefunden. Niemand hat ihn aber erklärt bzw. habe ich nichts gefunden. Eigentlich ist er ja auch selbsterklären. Ich weiß nur nicht was die "10" bewirkt.
  2. Ich nutze TK Labels mit .Grid() nun würde ich gerne die Hinterlegte Farbe des Labels auf der ganzen breite anzeigen. Geht das?
  3. Ich kopiere mir die Zwischenablage von Windows mit

    Code: Alles auswählen

    getclip = master.clipboard_get()
    Wenn die Zwischenablage leer ist kommt ein Fehler und das Programm startet nicht.
    Wie kann ich das verhindern?

Vielen Dank an alle die sich überhaupt die Mühe machen sich das Programm anzuschauen

Gruß
T

Code: Alles auswählen

from tkinter import *
import os

def fcleanmac(finput):						#Funktion um dem String der die MAC enthält einheitlich zu machen (ohne Trennzeichen und Uppercase) finput=Eingegebene MAC
	global cleanmac							#Globale Variable für die MAC-Adresse ohne Trennzeichen
	
	
	
	finput=finput.upper()					#finput als uppcercase
	cleanmac=finput.replace(":", "")		#Entfernen aller : aus finput
	cleanmac=cleanmac.replace("-", "")		#Entfernen aller - aus finput
	
	

def fcheckmaclen():			#Funktion um die länge der eingegebenen MAC zu Prüfen und einen Fehler auszugeben
	global cleanmac			#Globale Variable für die MAC-Adresse ohne Trennzeichen
	global chklen			#Globale Variable für den Prüfwert der Längenprüfung - True=Länge der MAC "OK"
	global master			#Globale Variable für das tk.root element

	if len(cleanmac) == 12:	#If Abfrage zu Prüfung der länge
		chklen=True			#Wenn länge "OK" setze den Prüfwert auf True
		
	else:											#Wenn die Länge nicht korrekt ist
		chklen=False								#wird der Prüfwert auf False gesetzt
	

	
def fcheckallowcharmac(): 	#Funktion um die MAC auf falsche Zeichen zu prüfen - True=Keine ungültigen Zeichen enthalten
	global chkallwchar		#Globale Variable für den Prüfwert der Zeichenprüfung
	chkallwchar=True		#Prüfwert der Zeichenprüfung
	
	allwdchr=("1","2","3","4","5","6","7","8","9","0","A","B","C","D","E","F")			#Liste der Erlaubten Zeichen
	i=0				#Schleifenzähler
		
	while i < len(cleanmac):					#While Schleife zur Abfrage der erlbauten Zeichen
		if cleanmac[i] in allwdchr:				#Abfrage der Erlaubten Zeichen
			i += 1								#Zähler der Schleife um 1 erhöhen um das näcshte Zeichen abzufragen
		
		else:												#Wenn ein ungültiges Zeichen enthalten ist wird der 
			chkallwchar=False								#Prüfwert auf False gesetzt
			break											#Verlassen der Schleife

def fformatmaccolon():		#funktion um die Doppelpunkte zur "Cleanmac" hinzuzufügen
	global cleanmac			#Globale Variable für die MAC-Adresse ohne Trennzeichen		
	global colonmac			#Globale Variable für die MAC-Adresse mit Doppelpunkt als Trennzeichen
	colonmac=""				#Setzen der Variablen da sonst in der Schleife ein Fehler kommt
	i=0						#Schleifenzähler
	
	for i in range(0,12,2):								#For Schleife zum Einsetzen der Doppelpunkte
		colonmac += cleanmac[i:i+2] + ":"				#Einsetzen der Doppelpunkte
	colonmac=colonmac[:-1]								#Entfernen des letzten Zeichens da dieses ein Doppelpunkt ist

def	fformatmacdash():	#funktion um die Bindestriche zur "Cleanmac" hinzuzufügen
	global cleanmac		#Globale Variable für die MAC-Adresse ohne Trennzeichen
	global dashmac		#Globale Variable für die MAC-Adresse mit Bindestrich als Trennzeichen
	dashmac=""			#Setzen der Variablen da sonst in der Schleife ein Fehler kommt
	i=0					#Schleifenzähler
	
	
	for i in range(0,12,2):								#For Schleife zum Einsetzen der Doppelpunkte
		dashmac += cleanmac[i:i+2] + "-"			    #Einsetzen der Doppelpunkte
	dashmac=dashmac[:-1]								#Entfernen des letzten Zeichens da dieses ein Minus ist

def addToClipBoard(text):			#Funktion um einen Wert in die Zwischenablage zu kopieren
	global master					#Globale Variable master
	master.clipboard_clear()		#Leeren der Zwischenablage
	master.clipboard_append(text)	#Variable text in Zwischenablage kopieren

def fclear():				#Funktion um das Fenster auf Stadnard zu setzen
	lblank.grid_remove()	#Entfernen aller Labels damit sie beim umwandeln einer neuen MAC entfernt sind
	l1.grid_remove()
	l2.grid_remove()
	l3.grid_remove()
	l4.grid_remove()
	l5.grid_remove()
	l6.grid_remove()
	l7.grid_remove()
	l8.grid_remove()
	l9.grid_remove()
	ctc1.grid_remove()
	ctc2.grid_remove()
	ctc3.grid_remove()
	e1.delete(0,END)
	
	
def fcheckmac(checkinput):
	global chkmac
	global cleanmac		#Globale Variable für die MAC-Adresse ohne Trennzeichen
	global dashmac		#Globale Variable für die MAC-Adresse mit Bindestrich als Trennzeichen
	global colonmac		#Globale Variable für die MAC-Adresse mit Doppelpunkt als Trennzeichen
	global l1			#Globale Variable tk.label Text="Clean : "
	global l2			#Globale Variabel tk.label Text="Dash  : "
	global l3			#Globale Variabel tk.label Text="Colon : "
	global l4			#Globale Variabel tk.label Text=cleanmac
	global l5			#Globale Variabel tk.label Text=dashmac
	global l6			#Globale Variabel tk.label Text=colonmac
	
	fclear()
	e1.insert(10, checkinput)
	fcleanmac(checkinput)	#Ausführen der Funktion fcleanmac - übergabe der variablen checkinput == Wert aus Eingabefeld 
	fcheckallowcharmac()	#Ausführen der Funktion fcheckallowcharmac und die gültigen Zeichen der MAC zu prüfen
	fcheckmaclen()			#Ausführen der Funktion fcheckmaclen um die Länge der Eingabe zu prüfen


	
	lblank.grid(row=1, column=0, columnspan=3)		#Einfügen einer leerzeile
	
	if chklen == False or chkallwchar == False:		#Wenn einer der beiden Prüfungen FALSE ergibt
		l9.grid(row=2, column=0, columnspan=4)		#wird die Meldung "Eingabe prüfen" angezeigt
		
	if chklen == False:								#Wenn die länge ungültig ist
		l8.grid(row=3, column=0, columnspan=4)		#wird die Fehlermeldung "Zeichenanzahl ungültig" und
		
	if chkallwchar == False:						#Wenn ungültige Zeichen enthalten sind
		l7.grid(row=4, column=0, columnspan=4)		#wir die Fehlermeldung "Ungültiges Zeichen" und

	
	if chklen and chkallwchar == True:				#Wenn beide Prüfungen TRUE ergeben
		fformatmaccolon()							#Funktion fformatmaccolon ausführen um die MAC mit Doppelpunkt als Trennzeichen zu erhalten
		fformatmacdash()							#Funktion fformatmaccolon ausführen um die MAC mit Bindestrich als Trennzeichen zu erhalten
		
		l4.configure(text = cleanmac)
		l5.configure(text = dashmac)
		l6.configure(text = colonmac)
		
		l1.grid(row=3, column=0)					#tk.label Text = "Clean : "
		l2.grid(row=4, column=0)					#tk.label Text = "Colon : "
		l3.grid(row=5, column=0)					#tk.label Text = "Dash  : "
		l4.grid(row=3, column=1)					#tk.label Text = cleanmac					
		l5.grid(row=4, column=1)					#tk.label Text = dashmac	
		l6.grid(row=5, column=1)					#tk.label Text = colonmac	
		ctc1.grid(row=3, column=2)					#tk.button um den Wert der Variablen cleanmac in die Zwischenablage zu kopieren
		ctc2.grid(row=4, column=2)					#tk.button um den Wert der Variablen dashmac in die Zwischenablage zu kopieren
		ctc3.grid(row=5, column=2)					#tk.button um den Wert der Variablen colonmac in die Zwischenablage zu kopieren


	
master = Tk()									#Festlegen des root Fenster für tk
master.title("MAC Zauberer")					#Titel des Fensters
master.resizable (width=NO, height=NO)			#Fenster kann nicht vergrößert oder verkleinert werden





Label(master, font= "Verdana 10 bold", text="Eingabe: ", width=20).grid(row=0, column=0) #tk.label Text=Eingabe

master.bind("<Return>",lambda eff:fcheckmac(e1.get()))	#Commando für das drücken der Enter Taste - Führe Funktion fcheckmac aus und übergebe den Wert aus dem Eingabefeld

#
#Konfiguration der Labels und Buttons die oben Verwendet werden
#

ctc1 = Button(master, font= "Verdana 10 " , text='ctc')
ctc2 = Button(master, font= "Verdana 10 " , text='ctc') 
ctc3 = Button(master, font= "Verdana 10 " , text='ctc')
ctc1.configure(command=lambda: addToClipBoard(cleanmac))
ctc2.configure(command=lambda: addToClipBoard(dashmac))
ctc3.configure(command=lambda: addToClipBoard(colonmac))

l1 = Label(master, font= "Verdana 10 bold")
l2 = Label(master, font= "Verdana 10 bold")
l3 = Label(master, font= "Verdana 10 bold")


l4 = Label(master, font= "Verdana 10 ")
l5 = Label(master, font= "Verdana 10 ")
l6 = Label(master, font= "Verdana 10 ")

l7 = Label(master, justify=CENTER, bg = "red", font= "Verdana 10 bold")
l8 = Label(master, justify=CENTER, bg = "red", font= "Verdana 10 bold")
l9 = Label(master, justify=CENTER, bg = "red", font= "Verdana 10 bold")


l7.configure(text="Ungültiges Zeichen")
l8.configure(text="Zeichenanzahl ungültig")
l9.configure(text="Eingabe prüfen")

lblank = Label(master, justify=CENTER, text="")

e1 = Entry(master,font= "Verdana 10 ", justify=CENTER, width=20)	#tk.entry - Eingabefeld für MAC-Adresse
e1.grid(row=0, column=1)

getclip=""
getclip = master.clipboard_get() 	#Kopieren der Zwischenablage in Variable

if len(getclip) < 20:			#wenn die Zwischenablage weniger als 20 Zeichen hat						
	e1.insert(10,getclip)		#wird diese in das Entry Feld eingetragen

b1=Button(master, width=10, font= "Verdana 10", text='Start', command=lambda: fcheckmac(e1.get())) 	#tk.Button = commando führt Funktion fcheckmac und übergibt den Wert aus dem Eingabefeld
b1.grid(row=0, column=3, padx=15)

clre1=Button(master, width=10, font= "Verdana 10", text='Clear', command=fclear)
clre1.grid(row=0 ,column=2, padx=5)



	
		
mainloop()
Zuletzt geändert von Anonymous am Mittwoch 18. Januar 2017, 17:13, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DerT: Sternchenimporte sind böse, weil man nicht kontrollieren kann, welche Namen da in den Namensraum geladen werden. Tkinter wird üblicherweise als "import tkinter as tk" importiert und per "tk." referenziert. Vergiss dass es global gibt, das hat in einem sauberen Programm nichts verloren. Funktionen erhalten Parameter als Argumente und geben Ergebnisse als Rückgabewert zurück, z.B:

Code: Alles auswählen

def fcheckmaclen(cleanmac):
    """ Funktion um die länge der eingegebenen MAC zu Prüfen und einen Fehler auszugeben"""
    return len(cleanmac) == 12
Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 3. Alles ab Zeile 138 gehört auch in eine Funktion, die üblicherweise main genannt wird und zum Schluß per "if __name__ == '__main__': main()" aufgerufen wird. Fängt man an Variablennamen durchzunummerieren, will man eigentlich eine Liste und Schleifen benutzen. Variablennamen sollten aussagekräftig sein, dann braucht man auch keine Kommentare, die die Namen erklären, also Statt "e1 # Eingabefeld für MAC-Adresse" einfach mac_input_field verwenden.
BlackJack

@DerT: Was Einrückung und Namensschreibweisen angeht gibt es einen Style Guide for Python Code.

Warum fangen alle Funktionsnamen mit einem `f` an? Das etwas eine Funktion ist, erkannt man üblicherweise daran, dass Funktionen (und Methoden) nach Tätigkeiten benannt sind. Damit man weiss was sie tun und um sie von eher passiven Werten unterscheiden zu können. Das `f` als Präfix nicht funktioniert sieht man an `finput`, was *keine* Funktion ist.

Das ganze ist ziemlich excessiv kommentiert, teilweise wegen der schlecht gewählten Namen und der vielen ``global``-Anweisungen, teilweise steht in den Kommentaren nichts kommentierenswertes. Ein Kommentar sollte nicht erklären was der Code macht, denn das kann man ja schon am Code ablesen, sondern warum er das so macht. Aber auch nur soweit das nicht sowieso ersichtlich ist. Wobei hier als Adressat jemand angenommen werden sollte, der die Sprache kennt, und die Dokumentation der verwendeten Bibliotheken lesen kann.

Der Kommentar der beschreibt was eine Funktion tut, als Argumente erwartet, und als Ergebnis liefert, sollte nicht als Kommentar, sondern als Docstring geschrieben werden. So kann er von anderen Werkzeugen, beispielsweise zur Dokumentation oder von IDEs, sinnvoll verwendet werden.

Kommentare am Zeilenende sprengen sehr schnell die 80 Zeichen pro Zeile und sollten deshalb nur für sehr kurze Anmerkungen verwendet werden. Längere Kommentare stehen bei Python Quelltext normalerweise in der/den Zeile(n) vor dem kommentierten Code.

Die ``while``-Schleife in `fcheckallowcharmac()` sollte eigentlich eine ``for``-Schleife direkt über die Zeichen sein. So etwas wie `allwdchr` gibt es (fast) im `string`-Modul:

Code: Alles auswählen

from string import hexdigits

# ...

def has_only_allowed_characters(mac):
    """Prüfe MAC auf ungültige Zeichen."""
    return all(digit in hexdigits for digit in mac)
`fformatmaccolon()` und `fformatmacdash()` enthalten nahezu identischen Code, das sind also eigentlich keine zwei Funktionen, sondern eine, der man das Trennzeichen als Argument übergeben sollte.

Die Laufvariable `i` direkt vor der Schleife an einen Wert zu binden macht nur Sinn wenn man a) erwartet das die Schleife eventuell nicht durchlaufen wird (weil das iterierbare Objekt nach ``in`` ”leer” ist) und b) der Wert von der Laufvariablen nach der Schleife noch für irgendetwas verwendet wird. Denn nur dann kann der Wert, der vor der Schleife zugewiesen wird, überhaupt irgendwann einmal verwendet werden. Die Zuweisung einer leeren Zeichenkette an `getclip` macht auch keinen Sinn wenn man gleich in der nächsten Zeile einen anderen Wert an den Namen bindet. `getclip` wäre auch eher ein Funktionsname und sollte eher `clipboard_content` oder etwas in der Richtung heissen.

Vergleiche von `bool`-Werten mit literalen `True` und `False` machen keinen Sinn. Bei dem Vergleich kommt ja doch nur wieder ein `bool`-Wert heraus, das heisst man kann entweder gleich den Wert verwenden, den man sowieso schon vor dem Vergleich hatte, oder dessen Negation mit ``not``, je nach dem was man braucht.

Das ein- und ausblenden von Anzeigeelementen über `grid()` und `grid_forget()` ist eher ungewöhnlich. Üblicherweise erstellt man die GUI am Anfang und ändert dann nur noch die Inhalte der Anzeigeelemente. Zumindest würde man aber die ganzen Sachen nicht einzeln ein- und ausblenden sondern was zusammen ein- und ausgeblendet wird zum Beispiel in `Frame`\s zusammenfassen und *die* dann ein- und ausblenden.

Ob der Text 'ctc' von normalen Benutzern als Kopieren in die Zwischenablage verstanden wird, wage ich zu bezweifeln. Das würde ich über das übliche Icon für diese Aktion (”Klemmbrett”) visuell lösen, wenn es platzsparend sein soll, oder über den Text 'Copy'.

Zu den Fragen:

Ad 1.: Die `tkinter`-Dokumentation in der Python-Dokumentation ist nicht besonders umfangreich. Hat am Anfang aber Links zu anderen Quellen. Zwei davon sind die Online-Ausgabe vom Buch von Effbot und die Tkinter Reference von der New Mexico Tech, die beide beschreiben was das erste Argument von `Entry.insert()` bedeutet:
http://effbot.org/tkinterbook/entry.htm
http://infohost.nmt.edu/tcc/help/pubs/t ... entry.html

Ad 2.: Ja das geht. :-)

Ad 3.: Was für ein Fehler kommt? Eine Ausnahme? Welche? Die sollte man mit der Ausnahmebehandlung von Python behandeln können. → Errors and Exceptions.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Prüfung auf ungültige Zeichen in der MAC-Adresse könnte man sogar noch etwas effizienter gestalten:

Code: Alles auswählen

from string import hexdigits

def has_invalid_characters(mac, allowed=set(hexdigits + ':')):
    return any(char not in allowed for char in mac)
Hier wird ein Set verwendet, damit die erlaubten Zeichen nicht jedes Mal sequentiell durchlaufen werden müssen.
BlackJack

@snafu: Der Doppelpunkt braucht hier nicht mit enthalten sein, beziehungsweise müsstest Du dann auch das '-' mit aufnehmen.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

BlackJack hat geschrieben:@snafu: Der Doppelpunkt braucht hier nicht mit enthalten sein,
Geht es nicht um die komplette MAC-Adresse?
BlackJack hat geschrieben:beziehungsweise müsstest Du dann auch das '-' mit aufnehmen.
Lässt sich ja leicht hinzufügen.
BlackJack

@snafu: Das ist doch gerade der Punkt von dem Programm, das es nicht *die* Schreibweise von MAC-Adressen gibt, weil einige Programme Doppelpunkte erwarten, andere Bindestriche, und wieder andere gar keine Trennzeichen erlauben. Die Prüffunktion wird jedenfalls mit einer Zeichenkette aufgerufen bei der Doppelpunkte und Bindestriche vorher entfernt wurden.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Manchmal hilft es auch, den ersten Beitrag aufmerksam zu lesen... :)
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

Hallo Leute,

vielen Dank für die Antworten.
Ich bin gerade dabei den Code neu zu schreiben und versuche dabei alle Hinweise zu beachten.
Nun habe ich aber noch ein paar Fragen zu euren Antworten :)
BlackJack hat geschrieben:Das ein- und ausblenden von Anzeigeelementen über `grid()` und `grid_forget()` ist eher ungewöhnlich. Üblicherweise erstellt man die GUI am Anfang und ändert dann nur noch die Inhalte der Anzeigeelemente. Zumindest würde man aber die ganzen Sachen nicht einzeln ein- und ausblenden sondern was zusammen ein- und ausgeblendet wird zum Beispiel in `Frame`\s zusammenfassen und *die* dann ein- und ausblenden.
Kannst du mir das genauer erklären? Bzw. hast du einen Link der das Thema Frames genauer Beschreibt?
Ich versuche es gerade mit Frames nachzubauen.

BlackJack hat geschrieben: Ad 1.: Die `tkinter`-Dokumentation in der Python-Dokumentation ist nicht besonders umfangreich. Hat am Anfang aber Links zu anderen Quellen. Zwei davon sind die Online-Ausgabe vom Buch von Effbot und die Tkinter Reference von der New Mexico Tech, die beide beschreiben was das erste Argument von `Entry.insert()` bedeutet:
http://effbot.org/tkinterbook/entry.htm
http://infohost.nmt.edu/tcc/help/pubs/t ... entry.html
Das Heißt also der Text wird an der Stelle eines vorhandenen Strings eingesetzt?
Das Heißt das ich dort eine "10" stehen habe ist Schwachsinn? :lol:

BlackJack hat geschrieben: Ad 2.: Ja das geht. :-)
Okay, ich hätte auch Fragen sollen wie :)
Wie geht das denn?

BlackJack hat geschrieben: Ad 3.: Was für ein Fehler kommt? Eine Ausnahme? Welche? Die sollte man mit der Ausnahmebehandlung von Python behandeln können. → Errors and Exceptions.
Falls der Fehler beim neuen Code auch auftritt werde ich versuchen Ihn mit dem Link zu beheben, ansonsten Poste ich ihn mal :)


Eine Letzte Frage noch.
Ist es möglich die Standardschriftart und Größe für alle widgets festzulegen?
Wenn ja wie? :D

Gruß
T
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

BlackJack hat geschrieben: Vergleiche von `bool`-Werten mit literalen `True` und `False` machen keinen Sinn. Bei dem Vergleich kommt ja doch nur wieder ein `bool`-Wert heraus, das heisst man kann entweder gleich den Wert verwenden, den man sowieso schon vor dem Vergleich hatte, oder dessen Negation mit ``not``, je nach dem was man braucht.
Wie meinst du das?
Ich muss doch ein "if" benutzen wenn ich den Wert abfragen will.
Gibt es eine andere, einfachere Methode einen 'bool'-Wert abzufragen?
Tut mir leid falls die Frage dämlich ist :)
Ich versuch nur was zu lernen.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DerT: Du schreibst

Code: Alles auswählen

if chklen == False or chkallwchar == False:
besser wäre

Code: Alles auswählen

if not chklen or not chkallwchar:
BlackJack

Oder mit einer Operation weniger:

Code: Alles auswählen

if not (chklen and chkallwchar):
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

Hallo Leute,

ich bräcuhte nochmal eure Hilfe.

Ich habe foglenden Code um mir die Fehler anzeigen zu lassen.

Code: Alles auswählen

def check_and_format_mac(inputmac, tkroot):
	
	error_frame = tk.Frame(tkroot, height=50,width=400)
	error_frame.propagate(0)

	
	
	if not 	check_mac_lenght(cleanmac(inputmac)) or not check_allowed_characters(cleanmac(inputmac)):
		print("Eingabe Falsch")
		tk.Label(error_frame, text="Eingabe Prüfen").grid(row=0)
		if not check_mac_lenght(cleanmac(inputmac)):
			print("Zeichenanzahl ungültig")
			tk.Label(error_frame, text="Zeichenanzahl ungültig").grid(row=1)
		if not check_allowed_characters(cleanmac(inputmac)):
			print("Ungültiges Zeichen")
			tk.Label(error_frame, text="Ungültiges Zeichen enthalten").grid(row=2)
		error_frame.grid(row=1)
Funktioniert auch.
Aber wie entferne ich die widgets wieder aus dem Frame?
Wenn ich so mein Programm öfter nutze (ohne es zu schließen) legt er mir immer neue labels über die alten.

Gruß T

ps. wie fomratiere ich den Code im Forum als Python-Code?
Zuletzt geändert von Anonymous am Montag 23. Januar 2017, 12:24, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DerT: wie BlackJack schon geschrieben hat, wäre es am besten, alle Ergebnisse in *einem* Frame darzustellen, den solltest Du Dir merken und vor dem Erstellen eines neuen Ergebnisses einfach löschen.

Die Funktion enthält zu viele Leerzeilen; Funktionen werden unnötigerweise viel zu oft aufgerufen; eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 3.

Code: Alles auswählen

def check_and_format_mac(inputmac, parent):
    results_frame = tk.Frame(parent)
    errors = []
    inputmac = cleanmac(inputmac)
    if not check_mac_length(inputmac):
        errors.append("Zeichenanzahl ungültig")
    if not check_allowed_characters(inputmac):
        errors.append("Ungültiges Zeichen")

    if errors:
        errors.insert(0, "Eingabe Prüfen")
        for row, line in enumerate(errors):
            tk.Label(results_frame, text=line).grid(row=row)
    else:
        [...]
    return results_frame
PS: über dem Editfeld gibt es ein Dropdown "Code auswählen", wo Du "PY (Python)" auswählen kannst.
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

Hallo :),

auch auf die Gefahr hin das ích euch nerve und mir keiner mehr antwortet, stelle ich weiter dumme Fragen :D

Ich habe es nun nocheinmal überarbeitet. (Bzw. den Code von Sirius3 ausgebaut)

Code: Alles auswählen

def check_and_format_mac(inputmac, parent):
    results_frame = tk.Frame(parent)
    errors = []
    mac = []
    delimeter = [":", "-"]
    clean = cleanmac(inputmac)
    if not check_mac_length(clean):
    	errors.append("Zeichenanzahl ungültig")
    if not check_allowed_characters(clean):
        errors.append("Ungültiges Zeichen")
    if errors:
        errors.insert(0, "Eingabe Prüfen")
        for row, line in enumerate(errors):
            tk.Label(results_frame, text=line).grid(row=row)
    else:
        mac.append(clean)
        for i in delimeter:
            mac.append(format_mac(clean, i))
        for row, line in enumerate(mac):
            tk.Label(results_frame, text=line).grid(row=row, column=0)
            
        tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(mac[0], parent)).grid(row=0, column=1) 
        tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(mac[1], parent)).grid(row=1, column=1)
        tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(mac[2], parent)).grid(row=2, column=1)
           
    return results_frame
Ich habe auserdem versucht diesen Code:

Code: Alles auswählen

        tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(mac[0], parent)).grid(row=0, column=1) 
        tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(mac[1], parent)).grid(row=1, column=1)
        tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(mac[2], parent)).grid(row=2, column=1)
Hiermit zu ersetzen.
Was leider nur teilweise funktioniert hat.

Code: Alles auswählen

        for row, line in enumerate(mac):
            tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(str(line), parent)).grid(row=row, column=2) 
Es werden zwar 3 Buttons erstellt jedoch kopieren alle drei den gleichen Wert in die Zwischenablage.
Sirius3 hat geschrieben:@DerT: wie BlackJack schon geschrieben hat, wäre es am besten, alle Ergebnisse in *einem* Frame darzustellen, den solltest Du Dir merken und vor dem Erstellen eines neuen Ergebnisses einfach löschen.
Ja, aber ich muss ja den Frame bei jedem aufruf der Funktion "check_and_format_mac" löschen.
Leider finde ich keinen code mit dem ich ein Frame "leeren" kann.
und destroy() kommt ja nicht in Frage da ich es wiederverwenden will.
Sirius3 hat geschrieben: eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 3
Bei mir ist es mit 4 Leerzeilen eingerückt.


Gruß
T
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DerT: in der ersten Zeile der Funktion erzeugst Du einen neuen Frame. Der alte kann also komplett gelöscht werden.
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

Hallo,
Sirius3 hat geschrieben:@DerT: in der ersten Zeile der Funktion erzeugst Du einen neuen Frame. Der alte kann also komplett gelöscht werden.
Ja aber wenn ich den Frame mit destroy() zerstöre bekomme ich beim ersten durchlauf einen "NameError:" da der Frame ja noch nicht definiert ist.


Dieses Problem könnte/konnte ich lösen mit einem.

Code: Alles auswählen

    try:
        results_frame.destroy()
    except NameError:
        [...]
Aber ich möchte ebenfalls einen Clear Burron einbauen. Welchen command muss ich diesem geben?



Anbei mal mein "neues" Programm. (Ohne "frame.destroy()" ) Ich habe versucht alle Tipps zu berückstichtigen.

Code: Alles auswählen

import os
import tkinter as tk
from string import hexdigits

def cleanmac(inputmac):
    cleanmac=inputmac.upper()
    clean=[":", " ", "-"]
    for i in clean:
        cleanmac=cleanmac.replace(i, "")
    return cleanmac
	
def check_mac_length(inputmac):
    return len(inputmac) == 12

def check_allowed_characters(inputmac): 	
    return all(digit in hexdigits for digit in inputmac)					

def format_mac(inputmac, inputcharacter):
    formatmac=""
    for i in range(0,12,2):
        formatmac += inputmac[i:i+2] + inputcharacter
    formatmac=formatmac[:-1]
    return formatmac
	
def add_to_clipboard(text, parent):					
    parent.clipboard_clear()	
    return parent.clipboard_append(text)

def getclipboard(parent):
    getclip = ""
    getclip = parent.clipboard_get()
    if len(getclip) < 20:
        return getclip
    else:
        return ""
    
def check_and_format_mac(inputmac, parent):
    results_frame = tk.Frame(parent, width=430, height=90)
    errors = []
    mac = []
    delimeter = [":", "-"]
    clean = cleanmac(inputmac)
    from_above = 10
    if not check_mac_length(clean):
    	errors.append("Zeichenanzahl ungültig")
    if not check_allowed_characters(clean):
        errors.append("Ungültiges Zeichen")

    if errors:
        errors.insert(0, "Eingabe Prüfen")
        for line in errors:
            tk.Label(results_frame, font= "Verdana 10 bold", text=line, justify=tk.CENTER, width=20).place(x=120, y=from_above, width=170, height=20)
            from_above += 20
        
    else:
        print(inputmac)
        mac.append(clean)
        for i in delimeter:
            mac.append(format_mac(clean, i))
        for row, line in enumerate(mac):
            tk.Label(results_frame,  font= "Verdana 10 ", text=line, justify=tk.CENTER).place(x=120, y=from_above, width=170, height=20)
            from_above += 25
            
        tk.Button(results_frame, font= "Verdana 10 ", text="copy", command=lambda: add_to_clipboard(mac[0], parent), width=10).place(x=320, y=10, width=100, height=20) 
        tk.Button(results_frame, font= "Verdana 10 ", text="copy", command=lambda: add_to_clipboard(mac[1], parent), width=10).place(x=320, y=35, width=100, height=20)
        tk.Button(results_frame, font= "Verdana 10 ", text="copy", command=lambda: add_to_clipboard(mac[2], parent), width=10).place(x=320, y=60, width=100, height=20)

        #for row, line in enumerate(mac):
            #tk.Button(results_frame, text="copy", command=lambda: add_to_clipboard(str(line), parent)).place(x=120, y=from_above, width=170, height=20)
            #from_above += 25

    return results_frame

def main():
    master = tk.Tk()
    master.title = "MAC Zauberer"
    master.resizable(width=0, height=0)
    master.bind("<Return>",lambda eff:check_and_format_mac(eingabefeld.get(), master).grid(row=1, column=0))

    entry_frame = tk.Frame(master, width=430, height=70)
    entry_frame.grid(row=0)
    
    eingabe_label = tk.Label(entry_frame, font= "Verdana 10 bold", text="Eingabe:")
    eingabe_label.place(x=30, y=40, width=60, height=20)

    eingabefeld  = tk.Entry(entry_frame, justify=tk.CENTER, font= "Verdana 10 ")
    eingabefeld.place(x=120, y=40, width=170, height=20)
    eingabefeld.insert(0,getclipboard(master))

    clear_button = tk.Button(entry_frame, font= "Verdana 10 ", text= "Clear",)
    clear_button.place(x=320, y=10, width=100, height=20)

    start_button = tk.Button(entry_frame,  font= "Verdana 10 ", width=10, text= "Start", command= lambda: check_and_format_mac(eingabefeld.get(), master).grid(row=1, column=0))
    start_button.place(x=320, y=40, width=100, height=20)
	
	
if __name__ == "__main__": main()
BlackJack

@DerT: `NameError` sollte man nicht behandeln. Das ist ein Programmierfehler der zur Laufzeit gar nicht auftreten sollte. Falls er Auftritt sollte man das Programm so ändern das er nicht auftreten kann.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DerT: "format_mac" könnte man mit .join schreiben

Code: Alles auswählen

def format_mac(inputmac, inputcharacter=":"):
    return inputcharacter.join(inputmac[i:i+2] for i in range(0,12,2))
Der Rückgabewert von add_to_clipboard ist wenig sinnvoll. getclip wird unnötigerweise an eine leere Zeichenkette gebunden. mac und delimiter werden definiert, lange bevor sie verwendet werden. place sollte man nicht verwenden. Die Copy-Buttons kann man innerhalb der Schleife erzeugen, wenn man partial statt lambda verwendet.

Solange kein results_frame existiert weist man ihm den Wert None zu, so dass eine einfache Abfrage "result_frame is not None" statt des NameErrors ausreicht. Dann brauchst Du aber eine Klasse, um diesen Wert irgendwo speichern zu können.
DerT
User
Beiträge: 8
Registriert: Dienstag 10. Januar 2017, 15:58

Hallo,

versuche mich gerade daran eine Klasse zu erstellen.
Keine Ahnung ob es so überhaupt Sinn macht.
Ich wollte eine Klasse "gui" erstellen die z.B. die methoden "create_frame" und "destroy_frame" hat.
Funktioniert auch soweit. Nur "destroy_frame" zerstört den Frame nicht.

Code: Alles auswählen

class gui:

    def __init__ (self, master):
        self.master = master
        master.title("Das ist ein GUI")


    def create_frame(self):
        self.frame = tk.Frame(self.master)
        self.label = tk.Label(self.master, text="Hallo aus create_frame") 
        self.frame.pack()
        self.label.pack()
        
    
    def destroy_frame(self):
        self.frame.destroy()
        print("destroy_frame")
Nerv ich euch langsam? :?: :lol: :D

Gruß
T
Antworten