MVC

Fragen zu Tkinter.
Antworten
lulumagulu
User
Beiträge: 4
Registriert: Donnerstag 14. Juni 2007, 15:20

Hallo,
ich bin neu in der Community und habe auch schon gleich das erste Problem.
Wie gesagt, ich habe ein kleines Problem und drehe mich irgendwie immer im kreis. Ich möchte eine Graphische Oberfläche bauen, die mir die Primzahlen zwischen 2 bestimmten Werten ausgibt.
Ich habe eine Klasse Primzahlen die mir die Primzahlen berechnet, jedoch weiß ich nicht, wie ich sie in die Oberfläche integriere.

Vielleicht könntet ihr mir ja helfen und mir ein paar Tipps geben um meinen Programmierstil zu verbessern. Bin noch Anfänger.

Code: Alles auswählen



from Tkinter import *

class Primzahlen():
    def __init__(self,obergrenze,untergrenze):
        self.obergrenze = obergrenze
        self.untergrenze = untergrenze

    def berechne(self):
        for n in range(self.obergrenze, self.untergrenze):
            for x in range(2, n):
                if n % x == 0:
                    break
            else:
                print n
               
fenster = Tk(className="Primzahlengenerator")
frame1 = Frame(fenster)
frame2 = Frame(fenster)
label1 = Label(frame1,text="Obere Grenze")
label2 = Label(frame1, text="Untere Grenze")
scrollbar = Scrollbar(frame1)
scrollbar.pack(side=RIGHT, fill=Y)
text = Text(frame1,
            width=40, height=20,
            yscrollcommand=scrollbar.set)
entry1 = Entry(frame1)
entry2 = Entry(frame1)
button = Button(frame1, text="Berechne Primzahlen",)

        
frame1.pack()
frame2.pack()
label1.pack()
entry1.pack()
label2.pack()
entry2.pack()
button.pack()
text.pack()
fenster.mainloop()
BlackJack

Die Primzahlberechnung in eine Klasse zu stecken macht nicht viel Sinn. Das könnte eine einfache Funktion sein, die Unter- und Obergrenze als Argumente beim Aufruf bekommt.

Und sie muss natürlich das Ergebnis in irgendeiner Form, zum Beispiel in einer Liste, zurückgeben und nicht mit ``print`` ausgeben. Das sieht man ja nicht in der GUI.

Um beides zu verbinden brauchst Du eine Funtkion oder Methode, die beim `Button` als `command` angegeben wird, die Grenzen aus der GUI ausliest, die Primzahlberechnung aufruft und das Ergebnis wieder in ein GUI-Element schreibt.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

class Foo(): ist eine schlechte Idee. Entweder class Foo(object): (mit python2.2 und größer, aber kleiner als Python3 eine gute Idee) oder class Foo: (mit Python < 2.5 eine Idee, und solange du kein MI machst auch keine schlechte) oder class Foo: mit python3.

So. Jetzt hab ich jemanden verwirrt ;)

Sinn der Übung: class Foo(): geht nur mit python2.5 und höher.
TUFKAB – the user formerly known as blackbird
lulumagulu
User
Beiträge: 4
Registriert: Donnerstag 14. Juni 2007, 15:20

Hi,
danke erstmal für die Infos. Hab das jetzt so implementiert wie ihr das meintet.

Bekomme allerdings folgende Fehlermeldung:

Code: Alles auswählen


Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python25\lib\lib-tk\Tkinter.py", line 1403, in __call__
    return self.func(*args)
  File "C:\Dokumente und Einstellungen\Ismail Serin\Desktop\test.py", line 14, in berechne
    for n in range(c,d):
NameError: global name 'c' is not defined



Wie kann ich diesen Fehler beheben?
Wie kann ich Listen in einem textfeld ausgeben?

Code: Alles auswählen


# -*- coding: cp1252 -*-

from Tkinter import *



primzahlen= []
def berechne():
    for n in range(c,d):
        for x in range(2, n):
            if n % x == 0:
                break
        else:
                liste.append(n)
                print n

               
fenster = Tk(className="Primzahlengenerator")
frame1 = Frame(fenster)
frame2 = Frame(fenster)
label1 = Label(frame1,text="Obere Grenze")
label2 = Label(frame1, text="Untere Grenze")
scrollbar = Scrollbar(frame1)
scrollbar.pack(side=RIGHT, fill=Y)
text = Text(frame1,
            width=40, height=20,
            yscrollcommand=scrollbar.set)

entry1 = Entry(frame1)
entry2 = Entry(frame1)

a = entry1.get()
b = entry2.get()

if a != b:
    c = int(a)
    d = int(b)
else:
    pass

button = Button(frame1, text="Berechne Primzahlen", command=berechne)


frame1.pack()
frame2.pack()
label1.pack()
entry1.pack()
label2.pack()
entry2.pack()
button.pack()
text.pack()
fenster.mainloop()


[/code]
Zuletzt geändert von lulumagulu am Freitag 15. Juni 2007, 16:20, insgesamt 1-mal geändert.
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

lulumagulu hat geschrieben:

Code: Alles auswählen

#...
a = entry1.get()
b = entry2.get()
#...
Hi, tk.Entry.get() liefert den Inhalt des Entrys immer als str, wie auch in der Fehlermeldung zu erkennen ist.
Wandel diesen einfach mit int() um.

Code: Alles auswählen

#...
a = int(entry1.get())
b = int(entry2.get())
#...
Gruß, jj
lulumagulu
User
Beiträge: 4
Registriert: Donnerstag 14. Juni 2007, 15:20

Danke,

habe das jetzt gemacht.
Bekomme aber jetze eine neue Fehlermeldung, die ich nicht verstehe.
Siehe oben.
schlangenbeschwörer
User
Beiträge: 419
Registriert: Sonntag 3. September 2006, 15:11
Wohnort: in den weiten von NRW
Kontaktdaten:

Sind vlt. a und b gleich? Wenn du das schon während der Initialisierung testest, ist ja klar, dass der Inhlat der beiden Entrys gleich ist (beide sind ja leer). Verschiebe am Besten alles in die Funktion:

Code: Alles auswählen

def berechne(c, d):
    for n in range(c,d):
        for x in range(2, n):
            if n % x == 0:
                break
        else:
                liste.append(n)
                print n
#...
button = Button(frame1, text="Berechne Primzahlen", \
command=lambda: berechne(int(entry1.get()), int(entry2.get()))
ok, is nicht die beste lösung, aber ist ja auch nur en bsp...
_____
Außerdem solltest du deine probleme in den alten Beiträgen nicht durch neue ersetzen, das verwirrt.
lulumagulu
User
Beiträge: 4
Registriert: Donnerstag 14. Juni 2007, 15:20

Hey cool.
Dankesehr!

Muss mir jetzt nur noch anschaun, was das Lambda eigentlich genau macht.

Kann mir villeicht noch jemand bitte sagen wie ich listen in Tkinter ausgeben kann?

Muss ich vll. zuerst die Listen in Strings umwandeln?

Code: Alles auswählen



    for i in range(1,len(primzahlen)): 
        werte += str(primzahlen[i])
        print werte
        if i != len(primzahlen)-1: 
            werte += ","
        else:
            pass




EDIT:
Ich habe das Problem jetzt mit einer Listbox realisiert. Das Problem allerdings ist, dass wenn die Liste zu lang ist, dass der Zeilenumbruch fehlt?

Wie bekomme ich einen Zeilenumbruch in der Listebox hin?

Code: Alles auswählen

    

    fenster2= Tk()
    liste = Listbox(fenster2)
    liste.insert(END, primzahlen)
    liste.pack()
    fenster2.mainloop()

Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

lulumagulu hat geschrieben: Wie bekomme ich einen Zeilenumbruch in der Listebox hin?
Suchst du so etwas in der Art?

Code: Alles auswählen

liste.insert(END, '\n' + primzahlen)
[EDIT:]
Ich hab noch mal darüber nachgedacht, das löst dein Problem wohl nicht. Allerdings bin ich mir nicht so ganz sicher, wo genau dein Problem eigentlich ist, bei mir hat er am Zeilenende immer automatisch eine neue Zeile begonnen...
Zuletzt geändert von Zizibee am Montag 18. Juni 2007, 08:06, insgesamt 1-mal geändert.
BlackJack

lulumagulu hat geschrieben:

Code: Alles auswählen

    for i in range(1,len(primzahlen)): 
        werte += str(primzahlen[i])
        print werte
        if i != len(primzahlen)-1: 
            werte += ","
        else:
            pass
Diese gesamte Schleife kann man durch eine Zeile ersetzen:

Code: Alles auswählen

        werte = ','.join(map(str, primzahlen))
Benutzeravatar
Michael Schneider
User
Beiträge: 569
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Brandenburg

Hi Lulumagulu,
BlackJack hat geschrieben:Diese gesamte Schleife kann man durch eine Zeile ersetzen:

Code: Alles auswählen

        werte = ', '.join(map(str, primzahlen))
... und diesen String packst Du dann in Dein (angepasstes) Textwidget:

Code: Alles auswählen

text = Text(frame1, wrap=WORD,
            width=40, height=20,
            yscrollcommand=scrollbar.set)
text.delete("1.0", END)
text.insert("1.0", werte)
Erläuterung:
wrap=WORD -> Zeilenumbruch an Wortende
text.delete -> entfernt den Inhalt von Zeile 1, Spalte 0 (oben links) bis zum Ende
text.insert -> fügt den String werte oben links ins Textfeld ein

Grüße,
der Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Antworten