Problem mit klassen und objekten ^^

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

hallo , ich habe das problem das ich für nen spiel ( dieses uralte tennis spiel mit den weißen schlägern ^^ und immer bei berührung bub...bub^^) naja das hab ich nach programmiert und wollte jetzt ne "anzeigetafel" machen , mein problem es funkt nicht ganz ... also die funktion --->eins<---- wird nicht durchgeführt .... weiß nicht obb das daran liegt das ich das mainloop vom fenster verschiebenmüsste :?
für ne hilfe oder tipp wäre ich dankbar :D

Code: Alles auswählen

import Tkinter

import Canvas

from Tkconstants import *


class Punkte ():
    def __init__(self):
#hier werden fenster, mittellinie usw. gemacht 
        self.fenster2 = Tkinter.Tk()
        self.flaeche2 = Tkinter.Canvas (self.fenster2, relief = SUNKEN, width = 400, height = 150, bg = "black")
        self.flaeche2.pack()
        self.mittellinie = Canvas.Rectangle(self.flaeche2,  (200,0),  (200,150), outline ="white", fill ="white")
   
# hier soll eine 8 erzeugt werden , damit dann je nach aufruf einer methode bestimmte elemente geloescht werden     
        self.rechtsoben = Canvas.Rectangle(self.flaeche2, (175,20), (180,70), outline = "white",fill= "white")
        self.rechtsunten = Canvas.Rectangle(self.flaeche2, (175,75), (180,125), outline = "white",fill = "white")
        self.linksoben = Canvas.Rectangle(self.flaeche2, (140,20), (145,70), outline = "white",fill = "white")
        self.linksunten = Canvas.Rectangle(self.flaeche2, (140,75), (145,125), outline = "white",fill = "white")
        self.ganzoben = Canvas.Rectangle(self.flaeche2, (145,15), (175,20), outline = "white",fill = "white")
        self.mitte = Canvas.Rectangle(self.flaeche2, (145,70), (175,75), outline = "white",fill = "white")
        self.ganzunten = Canvas.Rectangle(self.flaeche2, (145,125), (175,130), outline = "white",fill = "white")
      

#hier sollen alle elemente bis auf 2 geloescht werden somit nur eine 1 stehn bleibt ( wie bei einer anzeigetafel)
    def display_one(self) :
        self.linksoben.delete()
        self.linksunten.delete()
        self.ganzoben.delete()
        self.mitte.delete()
        self.ganzunten.delete()

#so ?       
Punkte.fenster2.mainloop()
    

if __name__ == "__main__":
    test=Punkte()
    test()
    test.eins()
Zuletzt geändert von Dorfl am Dienstag 16. Dezember 2008, 22:34, insgesamt 9-mal geändert.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Wenn in init irgendwelche Seiteneffekte hat, hast du Mist gebraucht und wenn die Instanz einer Klasse mehrere einzelne Dinge representiert ist dass noch viel schlimmer.

Sollte eine Klasse eine Methode "eins" heissen und du kannst dir nicht denken was die macht ist der Name unbrauchbar, dass gleiche gilt im Allgemeinen für Objekte mit Namen wie ro, ru, lo usw. und wie du gerade gelesen hast es heisst Methode wenn die Funktion im Namespace eine Klasse zu finden ist.

Desweiteren solltest du die wahrscheinlich mal PEP 8 anschauen, auf beiden Seiten eines Operators sollte ein Leerzeichen stehen, außer bei Keywords in Aufrufen.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

und was meinst du mit der methode eins ??
ich weiß was die macht aber ich scheine sie falsch aufzurufen
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Mal abgesehen davon dass der Code ziemlicher Mist ist - Variablen die man mit einem Kommentar erklären muss, sollten einem zu denken geben, ebenso komplett falsch benannte Methoden - verstehe ich nicht was das `test()' soll.

Deine Klasse implementiert __call__ nicht, darum solltest du auch einen AttributeError bekommen. Das dürfte deine Methode aber nicht beeinflussen.

Ich denke da hast du in deiner Methode mist gebaut, aber mit Tk kenne ich mich nicht aus.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

ja das programm ist ja auch eigentlich nur für mich gewesen und ich hatte nicht vor es nach dem allgemeinen schreibstil zu machen....
und das test ()
ich hatte es so im unterricht gezeigt bekommen und daher is das bei ir noch so drinn , es ist ja nur nen teil programm und wie der name test schon sagt , hatte ich das auch nur für test zwecke....
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dorfl hat geschrieben:ja das programm ist ja auch eigentlich nur für mich gewesen und ich hatte nicht vor es nach dem allgemeinen schreibstil zu machen....
Dann behalt das Programm doch einfach für dich, und erwarte nicht von anderen, dass sie sich in "deinen schreibstil" einarbeiten, wenn du es nicht für nötig hältst, dich an gute Konventionen zu halten, damit andere (und du selbst) deinen Code lesen können.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

war ja auch nur , weil frag um hilfe und statt diese zu bekommen werde ich erst ma zugeflamt , wegen stil und was mit klassen usw...
statt einfach zu schreiben , das ich das nochma nach der norm schreiben sollte...
und bitte auf die frage eingehen , ich möchte nur wissen ob mir jemand sagen kann wo der fehler ist
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dorfl hat geschrieben:war ja auch nur , weil frag um hilfe und statt diese zu bekommen werde ich erst ma zugeflamt , wegen stil und was mit klassen usw...
statt einfach zu schreiben , das ich das nochma nach der norm schreiben sollte...
und bitte auf die frage eingehen , ich möchte nur wissen ob mir jemand sagen kann wo der fehler ist
Das hat mit flame nichts zu tun. Du möchtest immerhin, dass andere sich mit deinem Code beschäftigen. Ohne einen Blick darauf zu werfen, wird man den Fehler (wenn es denn nur mal Singular ist :) ) ja nicht finden. Wenn du aber nicht bereit bist, hilfreiche Verbesserungsvorschläge anzunehmen, und darauf insistierst, es schlecht machen zu wollen, aber andere mögen doch bitte dabei helfen, dass zwar immer noch schlecht ist, aber irgendwie läuft, dann führt das eben nicht zu positiven Reaktionen. Vielleicht findet sich ja noch jemand, den das nicht stört und der dir trotzdem hilft ...
BlackJack

@Dorfl: Der Aufruf von `mainloop()` kehrt nicht zurück, bzw. erst wenn das Fenster geschlossen wurde. *Dann* willst Du die Methode aber sehr wahrscheinlich nicht mehr aufrufen, denn das Fenster mit der Grafik ist dann ja schon weg.

GUI-Programmierung bedeutet ereignisbasierte Programmierung, d.h. man programmiert nicht mehr rein linear, sondern legt fest welche Funktionen oder Methoden bei welchem Ereignis aufgerufen werden sollen und übergibt die Kontrolle dann der Hauptschleife der verwendeten GUI-Bibliothek.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

ah, danke . Also wenn ich richtig verstanden hab , fehlt sozusagen das mainloop() wenn ich die Methode "eins" aufrufe ?

2. was soll denn an meinem text noch so falsch sein? der name "eins" zur methode ist , weil da eine 1 sozusagen erzeugt werden soll durch 2 rechtecke.
und mit den variablen , wenn ich ncohma ne frage hier haben sollte und den text hier posten werd ich es berücksichtigen , aber kanns halt erstmal nur so machen wie ich es bisher gelernt habe
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dorfl hat geschrieben:ah, danke . Also wenn ich richtig verstanden hab , fehlt sozusagen das mainloop() wenn ich die Methode "eins" aufrufe ?
Nein.
Dorfl hat geschrieben:wenn ich ncohma ne frage hier haben sollte und den text hier posten werd ich es berücksichtigen , aber kanns halt erstmal nur so machen wie ich es bisher gelernt habe
Sicher. Aber du hast ja in diesem Thread (von anderen) schon Hinweise zur Verbesserung bekommen. Als Zeichen des guten Willens könntest du diese ja umsetzen und den verbesserten Code zeigen. Das erhöht bei anderen vermutlich die Bereitschaft, sich weiter damit auseinanderzusetzen und dir weiterzuhelfen.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

so? siehe oben
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Jein, zumindest sind die Variablennamen nun verständlich.
Deine Eins-Methode solltest du vielleicht generischer gestalten - wobei ich zugeben muss, dass mir da bei LED-Ziffern nichts einfallen würde, evtl sind normale Ziffern eine Alternative?

Was du dir aber auf jeden Fall anschauen solltest: [wiki=PEP_8_(Übersetzung)]PEP8 deutsch[/wiki] bzw PEP8 orginal

Dein Problem ist aber immernoch nicht gelöst. Den Mainloop musst du ausserhalb der Klasse setzen, wie BJ schon angedeutet hat, und Events zum Aufruf der Methoden definieren.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

cofi hat geschrieben: Deine Eins-Methode solltest du vielleicht generischer gestalten
Wie wäre es mit display_one()? Oder display_digit_one() ... so in der Art.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

okay ich schätze das mainloop ist immernoch falsch .. also von dem schreibweise ...
und sry aber was ist mit events gemeint, kenne mich noch nicht wirklich gut aus :wink:
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ich dachte jetzt eher an den Code nicht an den Namen ;)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Es sieht doch immer deutlicher danach aus, als fehlten dir momentan noch die Voraussetzungen, um das Problem überhaupt vernünftig lösen zu können. Was ich allerdings nicht verstehe: Du hast in einem Post geschrieben, dass du irgendetwas im Unterricht so gezeigt bekommen hast. Wenn ihr in diesem Unterricht Tkinter behandelt habt, dann verstehe ich nicht, dass du mit mainloop() nicht klarkommst.

Für eine anständige Lösung deiner Anzeigetafel würde man IMHO ganz anders herangehen. Nicht für jede Ziffer eine eigene Funktion schreiben, nicht mit rectangle arbeiten, nicht mit absoluten Koordinaten usw.

Ein ordentlicher Ansatz könnte der sein, dass man sich zunächst einmal die übliche Bezeichnung einer Siebensegmentanzeige ansieht und dann eine brauchbare Datenstruktur entwirft. Das könnte dann z.B. so aussehen:

Code: Alles auswählen

import Tkinter as tk

class Segment7(tk.Canvas):

    def __init__(self, master, breite=200,
                 hintergrund="black", ziffernfarbe="white"):
        tk.Canvas.__init__(self, master)
        d = self.dicke = breite // 8
        l = breite - 3*d
        self.hintergrund, self.ziffernfarbe = hintergrund, ziffernfarbe
        self.config(width=breite, height=2*l+5*d, bg=hintergrund)
        self.segmente = {"a":(2*d,d,d+l,d),
                         "b":(d+d+l,d+d,d+d+l,d+d+l),
                         "c":(d+d+l,3*d+l,d+d+l,3*d+l+l),
                         "d":(2*d,4*d+l+l,d+l,4*d+l+l),
                         "e":(d,3*d+l,d,3*d+l+l),
                         "f":(d,d+d,d,d+d+l),
                         "g":(2*d,2.5*d+l,d+l,2.5*d+l)}
        self.ziffern = ["abcdef","bc","abged","abgcd","fgbc","afgcd","afedcg",
                       "abc","abcdefg","abcdfg"]

    def loesche(self):
        for segment in self.ziffern[8]:
            self.create_line(self.segmente[segment],
                        fill=self.hintergrund, width=self.dicke)

    def zeige(self,char):
        try:
            ziffer = int(char)
        except ValueError:
            return
        self.loesche()
        for segment in self.ziffern[ziffer]:
            self.create_line(self.segmente[segment],
                        fill=self.ziffernfarbe, width=self.dicke)

if __name__ == "__main__":
    root = tk.Tk()
    anzeige = Segment7(root, breite=300)
    anzeige.pack()
    anzeige.bind_all("<KeyPress>",lambda e:anzeige.zeige(e.char))
    root.mainloop()
Bedienung: Beim Drücken einer Zifferntaste erfolgt die entsprechende Anzeige.

Das ein oder andere könnte man auch anders lösen, z.B. auf die loesche()-Methode verzichten und die benötigte Funktionalität mit in zeige() implementieren. Dann ggf. auch statt alle Segmente immer zu löschen, bei der Anzeige einer Ziffer alle Segmente durchlaufen und im Fall, dass das entsprechende Segment zur Ziffer gehört, in Ziffernfarbe darstellen und ansonsten in Hintergrundfarbe. Das verbesserte etwas die Performance.

Man könnte auch noch eine weitere Farbe mit einbeziehen, so dass die nicht angezeigten Segmente nicht ganz verschwinden, sondern blass erkennbar sind usw. usw.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

so... erstmal grooooßes Danke , sowohl für die erklärung als auch dafür das du dir die arbeit gemacht hast und nen beispielprogramm geschrieben hast.
verstehe jetzt auch wo das mainloop hingehört^^
und das mit dem unterricht... wir hatten nur nen beispiel code bekommen und sollten uns so alles zusammen reimen und bei fragen halt durften wir fragen...
daher wusste ich nicht genau zu 100% was , wo wie mainloop zu satzen ist :roll:
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dorfl hat geschrieben:so... erstmal grooooßes Danke , sowohl für die erklärung als auch dafür das du dir die arbeit gemacht hast und nen beispielprogramm geschrieben hast.
Sinnvoller als den Code jetzt für dein Programm einfach zu übernehmen (falls du das tust) ist es in jedem Fall, wenn du versuchst, den Code zu verstehen, und damit meine ich wirklich *VERSTEHEN*, d.h. z.B. jemand anderem Zeile für Zeile zu erklären, was da passiert und warum die Zeile so ist wie sie ist. Das ist mit Arbeit verbunden (weil auch Elemente enthalten sind, die man nicht unbedingt am Anfang eines Programmierkurses lernt), aber eine lohnende Arbeit.

Eine Hilfe beim Verstehen des Codes kann es auch sein, wenn du gezielt an einzelnen Stellen kleine Änderungen vornimmst, dir ansiehst, wie sich das auf das Ergebnis auswirkt und das dann analysierst.
Dorfl
User
Beiträge: 17
Registriert: Sonntag 23. November 2008, 17:18

^^ jo hab das auch gemacht und gesehn wo man sich einiges erleichtern kann :) es gibt zwar noch einige dinge die ich noch nicht ganz nachvollziehen kann aber arbeite drann :)
Antworten