Canvas

Fragen zu Tkinter.
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

Weiteres kleines Problem. ;)
wie kann ich bei einer Liste von x,y Positionen

Code: Alles auswählen

self.clef= [(38,164), (40,170), (47,165), ( 37, 131), (44, 126), (45,136),
                     (32,150), (40,161), (50,156), (47,144), ( 37,149), (40,154)]
jeweils alle y Positionen um einem bestimmten Wet verändern?
Am schluss brauche ich wieder eine Liste...

Mein Programm bisher:
bei der Funktion draw_key sollte bei jeder neuen Zeile auch der Notenschlüssel in der neuen Zeile gezeichnet werden und nicht immer in der 1. Zeile
http://www.python-forum.de/pastebin.php?mode=view&s=212
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

questlove hat geschrieben:wie kann ich bei einer Liste von x,y Positionen
jeweils alle y Positionen um einem bestimmten Wet verändern?
Am schluss brauche ich wieder eine Liste...
for, map, oder list comprehesion
Das Leben ist wie ein Tennisball.
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

danke :)
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

so..
jetzt hab ich ein etwas größeres Problemchen..
Und zwar ;):
Ich bin ja noch ein Anfänger mit Python. Und ich hab jetzt einfach mal für mein "Projekt" drauflosgeschrieben, ohne dass ich das geändert habe was mir Xynon1 geraten hat:
Xynon1 hat geschrieben:Ich werde mal mein Programm dokumentieren und dann nochmal hochladen.

Zu deinem Problem:
- Arbeite nicht mit "place"-Methoden das ist sowas von altmodisch und ohne Designer reine Folter. Nimm am besten nur "pack"-Methoden und sie mal wie weit du kommst.
- Lass niemals das Widget sich selbst auf sein Eltern-Widget packen. So kann man als Nutzer von diesem Widget nicht mehr den Geometry-Manager bestimmen.
- Man kann es nicht oft genug sagen: Halte dich an PEP8.

So könnte man es z.B. machen:

Code: Alles auswählen

#!/usr/bin/env python
import Tkinter as tk

class DarstellungsFenster(tk.Canvas):

     def __init__(self, master, cnf={}):
        # bedenke das border, relief und background so Standard sind
        # und deine Werte die du in 'cnf' übergibst eventuell überschreibst
        tk.Canvas.__init__(self, master, cnf, border=4, relief='ridge',
                           background='white')


def hauptprogramm():
    wurzel = tk.Tk()
    breite, hoehe = 800, 600
    x, y = 0, 0
    wurzel.geometry('%dx%d+%d+%d' % (breite, hoehe, x, y))
    wurzel.title('Notationsprogramm')
    darstellungsfenster = DarstellungsFenster(wurzel, dict(width=715, height=515))
    # expand sorgt dafuer das dein Widget immer genauso gross ist wie dein 
    # wurzel-Fenster
    darstellungsfenster.pack(expand=True, fill="both")

# Sonst wird der Code auch bei einem Import aufgerufen 
if __name__ == "__main__":
    hauptprogramm()
jetzt will ich statt mit Linien und Kreise in Canvas, den Notenschlüssel und die Noten durch ein gif einfach einzufügen, was wesentlich einfacher und schöner funtioniert.
Aber das eingefügte Bild per

Code: Alles auswählen

        Violinkey = tk.PhotoImage(file='vns_50.gif')
        self.create_image(130,130,image=Violinkey)
sieht man nur nur wenn ich dann noch
self.pack(dict(width=400,hight=400))
wobei self.pack() nicht ausreicht, was ich nicht verstehe.
Ich dachte es liegt nur an dem pack.

Meine Frage: Ich hab nirgens gefunden wie ich das anders einfügen kann. Was muss ich jetzt umschreiben, bzw wie? Oder gibt es eine Lösung um dem umschreiben auf die pack-Funktionen zu entkommen? ;)

(Ausschnitt aus GUI, class Darstellungsfenster,def__init__)
ich habs nur mal ins __init__ getan um zu sehen obs überhaupt geht ;)

mein code besteht aus 2 modulen:
1. Logik
2. GUI

LG
questlove
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

Bei den "create_"*-Methoden gibt es keinen Geometry-Manager (also weder pack, grid oder place), hier hast du nur die Möglichkeit mit Punkten zuarbeiten. d.h. für ein System in welchem du Bilder aneinaderreihen möchtest musst du dir selbst ein paar funktionen schreiben um das zu verwalten.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

ja das weis ich mittlerweile..danke
Auf das wollte ich aber nicht hinaus. Ich hab mich auch selber verwirrt ein bisschen. es hat garnichts mit dem pack() zu tun wie du schon sagst. Das problem ist das eingefügte Bild wird nur sichtbar wenn der code nach dem Einfügen durch einen Fehler abbricht und einen Fehler anzeigt. Wieso ist da so? W liegt da der Fehler?
BlackJack

@questlove: Das lässt sich ohne Quelltext schlecht sagen. Oder beziehst Du Dich auf den in dem Beitrag weiter oben? Da fehlt auf jeden Fall der Aufruf der Hauptschleife (`wurzel.mainloop()`).
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

ja mein post von davor.. da steht doch ganz unten dass sich mein programm aus 2 modulen aufbaut.
1. logik
2. GUI

da steht mein ganzer Quelltext..
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

und die hauptschleife ist in Logik
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@questlove
Ist jetzt aber nicht logisch, das sich die Hauptschleife der GUI in der Logik versteckt. :)

Was für eine Fehlermeldung kommt denn?
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
BlackJack

@questlove: Die GUI-Hauptschleife ist in Logik? Klingt unlogisch. ;-)

Du hast da zwei Module die sich gegenseitig importieren. Das ist im Grunde niemals eine gute Idee. Das solltest Du erst einmal ändern. Wenn sich zwei Module gegenseitig brauchen, dann sind sie so eng verbunden, dass sie im Grunde in ein einziges gehören, oder die Trennung nicht sauber gemacht ist. Zumal das oft auch gar nicht so funktioniert wie man sich das vielleicht wünscht. Man muss da nämlich sehr genau darauf achten welcher Code zu welchem Zeitpunkt ausgeführt wird, beim Importieren der Module.

Bei GUI und Logik ist es üblicherweise so, dass das GUI-Modul das Logik-Modul braucht, aber nicht umgekehrt. Denn die GUI benutzt den Logik-Teil — die Logik soll aber die GUI nicht kennen müssen. Die muss auch ohne GUI funktionieren können, beziehungsweise sollte die GUI austauschbar sein.
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

:D ich weis ;) ich hab aber nicht anders hinbekommen :/

Ja es kommt eigentlich keine, aber ich seh das bild auch nicht, das ich einfügen will.
Nur wenn ich in der zeile darunter iwas schreib (kann auch "gsbgusbutzhgzdgk" sein) dann bricht es da ab, es kommt die Fehlermeldung, dass er das wort nicht kennt, aber das bild ist sichtbar.

Mein problem also: ich will, dass es auch so sichtbar wird, ohne dass ich einen Fehler einbauen muss. Ich weis nicht an was es liegt dass sonst das bild nicht angezeigt wird.

Hoffe das ist jetzt einigermaßen verständlich ;)

@blackjack: danke für den hinweis. Ich habs auch erst in einem geschrieben jedoch musste ich es trennen, da es sonst schwieriger wird wenn ich auch noch mit mingus anfange und somit die logik "strukturiere". Ich habs anders versucht aber es ist mir iwie nicht gelungen. Was ihr meint ist, dass auch die GUI dann das modul ist, was man abspielen muss. Oder? Also sozusagen der hauptteil.
Xynon1
User
Beiträge: 1267
Registriert: Mittwoch 15. September 2010, 14:22

@questlove
Hast du eigentlich die verlinkte Seite gelesen gehabt? - Dort steht eine fettgedruckte Notiz. Les die mal bitte, dann weißt du auch warum das Bild nicht angezeigt wird.
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst.
Xynon auf GitHub
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

Und was heist das jetz auf deutsch? Ichbkann des bild nur in einem label darstellen oder wie? Aber wieso? Ich versteh die note iwie nicht. Mit abbruch funktionierts doch..
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

questlove hat geschrieben:Und was heist das jetz auf deutsch? Ichbkann des bild nur in einem label darstellen oder wie? Aber wieso? Ich versteh die note iwie nicht. Mit abbruch funktionierts doch..
Dort steht, dass du das Bild an einen Namen binden musst, welcher noch existiert während die Hauptschleife läuft. Andernfalls wird es vom Garbage-Collector aufgeräumt.
Das Leben ist wie ein Tennisball.
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

achso. Dankeschön
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

jetzt funktionierts schon, aber wenn ich die Methode

Code: Alles auswählen

    def draw_key(self):

        sypos=165 + (self.zeile*90)
        
        Violinkey = tk.PhotoImage(file='vns_50.gif')
        self.image=Violinkey
        self.create_image(42,sypos,image=Violinkey)
        #x,y Position der Notenschluesselzeilen
        cxpos=32
        cypos=150 + (self.zeile*90)
        
        # Erstellen der Notenschluesselzeilen
        for i in xrange (5):
            y=cypos + (i*7)
            self.create_line(cxpos, y, self.left(), y)
nochmal aufrufe, um das bild woanders zu erstellen, verschwindet es an dem vorherigen Punkt. :/
Kann mir jemand erklären wie ich das jetzt machen muss, dass ich das Bild einfach an verschiedenen Orten erzeugen kann? Ich brauch das nämlich noch öfter für die Bilder der Noten zum Beispiel. Anscheinend komm ich mit der Sprache noch nicht so zurecht..
BlackJack

@questlove: Wenn Du die Methode noch einmal aufrufst bindest Du ein neues Bildobjekt an `self.image`, womit natürlich das was da vorher dran gebunden wurde, nun nicht mehr von Python aus ansprechbar ist und damit der Speicher freigegeben werden kann. Wenn Du mehrere Bildobjekte erstellst, musst Du dir die *alle* irgendwo merken. Alternativ könntest Du auch mal versuchen ob es nicht günstiger wäre insgesamt nur *ein* Violinenschlüssel-Bildobjekt zu erzeugen und das wiederzuverwenden.

`image` ist vielleicht als Name auch ein wenig zu generisch. Und eigentlich sollte man es vermeiden Attribute ausserhalb der `__init__()` neu einzuführen. Da sollte man also alle Attribute zumindest zum Beispiel an `None` binden, falls man dort noch keinen anderen Wert zur Verfügung hat. In diesem Falle könnte man den Violinenschlüssel aber auch schon in der `__init__()` laden.
questlove
User
Beiträge: 65
Registriert: Dienstag 15. Februar 2011, 16:11

das zweite klingt logisch. Ich habs auch schon geändert.
Aber wie hast du das gemeint mit "wiederverwenden"? wie soll das gehen?
ich muss es einfach beliebig oft an ieinem platz einfügen können. Genau so wie später die Noten....
BlackJack

@questlove: Wiederverwenden: Halt nur *ein* `PhotoImage` aus dem GIF mit dem Violinenschlüssel erstellen und nicht jedes mal ein neues wenn ein Violinenschlüssel auf dem Canvas gesetzt werden soll.
Antworten