button placement.

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.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi kbr

Danke auch für deinen Tipp. Habe mein Skript wieder korrigiert:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Tkinter for Python 3.xx
import tkinter as tk

APP_TITLE = "Button placing with pack layouter"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 600
APP_HEIGHT = 200

SIDES = ['top', 'right', 'bottom', 'left']
ANCHORS = ['center', 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw']
FONT = ('Helevetica', 14, 'bold')

        
class Application(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title(APP_TITLE)
        self.build()
        
    def build(self):
        self.protocol("WM_DELETE_WINDOW", self.close_app)
        self.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
        self.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
        self.option_add("*Button.highlightThickness", 0)
        
        frame = tk.Frame(self, bg='#FFFF00')
        frame.pack(fill='both', expand=True)
        
        self.pos_var = tk.StringVar()
        self.button = tk.Button(frame, textvariable=self.pos_var, width=18,
            height=2, font=FONT)
        self.button.pack(padx=10, pady=10)

        self.place_the_button()
        
    def place_the_button(self, pos_index=0, pos_mode='side'):
        if pos_mode == 'side':    
            side = SIDES[pos_index]
            self.pack_with_side(side)
            pos_index += 1
            if pos_index >= len(SIDES):
                pos_index = 0
                pos_mode = 'anchor'
                
        elif pos_mode == 'anchor':
            anchor = ANCHORS[pos_index]
            self.pack_with_anchor(anchor)
            pos_index += 1
            if pos_index >= len(ANCHORS):
                pos_index = 0
                pos_mode = 'side'

        self.after(2000,self.place_the_button, pos_index, pos_mode)

    def pack_with_side(self, side):
        # Wichtige voreingestellte Optionen für die Anwendung von 'side' sind:
        # 'anchor' = 'center'
        # 'expand' = False
        print('Side:', self.button.pack_info())
        
        self.button.config(bg='#90EE90')
        self.pos_var.set("Position with side:\n'{}'".format(side))
        self.button.pack_configure(side=side, anchor='center', expand=False)
        
    def pack_with_anchor(self, anchor):
        # Wichtige voreingestellte Optionen für die Anwendung von 'anchor' sind:
        # 'expand' = True 
        print('Anchor:', self.button.pack_info())
        
        self.button.config(bg='#1AB7EA')
        self.pos_var.set("Position with anchor:\n'{}'".format(anchor))
        self.button.pack_configure(anchor=anchor, expand=True)
        
    def close_app(self):
        # Here do something before apps shutdown
        print("Good Bye!")
        self.destroy()


def main():        
    app = Application()
    app.mainloop()

if __name__ == '__main__':
    main()
Noch ein Frage im Zusammenhang mit dem Aufruf von 'build' in der Klasse Application. Ist es problematisch wenn sich in dieser Methode weitere 10'000 Zeilen Kode befinden?

Gruss wuf :wink:
Take it easy Mates!
Benutzeravatar
noisefloor
User
Beiträge: 3829
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ist es problematisch wenn sich in dieser Methode weitere 10'000 Zeilen Kode befinden?
Laufen tut das - nur ist eine Funktion mit 10.000 Zeilen Code nicht wartbar, darin findet du ja nichts mehr wieder... Das sollte man dann in mehr Funktionen runter brechen. Das ist aber nicht tkinter-spezifisch, dass gilt für jeglichen Code.

Gruß, noisefloor
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

@Wuf: Bei der Instanziierung eines Objektes sollte nichts weiter geschehen, als dieses Objekt in einen 'gebrauchsfähigen' Zustand zu versetzen. Wenn dafür 10000 Zeilen Code erforderlich sind, würde ich die Architektur hinterfragen. In der Praxis mag sowas zustande kommen, wenn ein Objekt sehr komplex ist und eine Vielzahl anderer Objekte als Attribute enthält (für die das ggf. auch wieder gilt). Für Python sind 10000 Zeilen Code bereits extrem viel.

Als Nachtrag noch: bei

Code: Alles auswählen

app = Application()
app.mainloop()
hast Du zudem die Möglichkeit, zwischen der Instanziierung und dem Aufruf der Mainloop, noch was einzufügen. So auch 'build', wie Du es ursprünglich getan hattest, aber dieses ist funktional der Initialisierung zuzuordnen und daher dort besser aufgehoben.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

@noisefloor & kbr: Danke für eure Antworten.

OK ich habe natürlich ein wenig übertrieben mit den 10'000 Zeilen Code. Es könnten ja viel weniger Zeilen sein aber dafür ein Zeit konsumierender Algorithmus der in der Methode 'build' abgearbeitet wird. Meine Frage ist wäre es ein Unterschied, wenn dieser Zeit konsumierend Block in der __init__ Methode ausgeführt wird oder in der Klasse 'Application' aus der _init__ Methode aufgerufenen Methode 'build' abgearbeitet würde. Wenn diese zwei Varianten keinen Unterschied ausmachen wäre es dann doch besser die folgende Variante anzuwenden?:

Code: Alles auswählen

def main():        
    app = Application()
    app.build()
    app.mainloop()

if __name__ == '__main__':
    main()
So würde doch die __init__ Methode der Klasse 'Application' sofort vor dem zeitintensiven Block in der 'build'Methode ausgeführt werden?
N.B: Hoffe mich richtig ausgedrückt zu haben.

Gruss wuf :wink:
Take it easy Mates!
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Frage ist, was das build macht. Wenn du es weg lassen kannst, und das ganze ist immer noch sinnvoll zu nutzen - dann vielleicht. Aber wenn - wie bei dir - sowieso nach Konstruktion *IMMER* build aufrufen musst, dann ist alles was du geschafft hast eine Fehlerquelle einzubauen - wehe jemand vergisst, build aufzurufen. Die Laufzeit wird aber dadurch nicht besser, wieso sollte sie? Die Menge an Anweisungen ist gleich, und damit auch die Laufzeit.

Generell ist es eine selten sinnvolle Idee, Objekte zu bauen, fuer die man erst magische Zaubesprueche in Form von diversen Methodenaufrufen in genau der richtigen Reihenfolge taetigen muss, bevor sie was tun.
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

ich mache jeden tag 2 stunden Sport, gehe zum Badminton und habe teilweise bis 4 Uhr schule. wenn ich dann um 6 oder sieben Uhr zuhause bin, habe ich tatsächlich nicht sonderlich viel Motivation mich damit tiefergehend zu beschäftigen. das buch, dass ich mir dafür gekauft habe ist absoluter quatsch und wenn ich es zwar lernen möchte aber nicht Zuviel zeit investieren kann, ist daran denke ich nichts auszusetzen. ich schade ja niemandem und wer nicht antworten will muss nicht.
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

Unglaublich. Danke für die konkrete Antwort und die Mühe. :)
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

jan.b hat geschrieben:ich mache jeden tag 2 stunden Sport, gehe zum Badminton und habe teilweise bis 4 Uhr schule. wenn ich dann um 6 oder sieben Uhr zuhause bin, habe ich tatsächlich nicht sonderlich viel Motivation mich damit tiefergehend zu beschäftigen. das buch, dass ich mir dafür gekauft habe ist absoluter quatsch und wenn ich es zwar lernen möchte aber nicht Zuviel zeit investieren kann, ist daran denke ich nichts auszusetzen. ich schade ja niemandem und wer nicht antworten will muss nicht.
Bullshit. Das markieren von Code und auswaehlen der CodeBox kostet SEKUNDEN. Die hast du, aber ganz sicher.

Und wir erzaehlen dir das hier nicht, um dich zu aergern, sondern weil diese Dinge *uns*, den Leuten, die dir kostenlos Wissen vermitteln wollen, das Leben leichter macht. Und deine Einstellung "ICH bin zu beschaeftigt mir Muehe zu geben, sollen die anderen das doch investieren" ist milde gesagt unverschaemt.

Du hast naemlich durchaus recht - niemand muss dir antworten, und es wird dann halt irgendwann nicht mehr passieren. Das wiederum ist genauso wenig unser Problem.

Und das Beispiel von wuf haettest du dir hier auch raussuchen koennen, ohne darauf einen Tag warten zu muessen. Da er so etwas oft postet. Von wegen zu wenig Zeit und so...
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

bis vor 5 Minuten war ich zu dumm, um diese bescheuerten Code boxen richtig zu setzen. dafür hat mir selbverständlich nicht die zeit gefehlt. das bezog sich nur auf den Lernprozess an sich. ich habe bei wuf nichts gefunden, dass ich auf meine frage beziehen könnte, was daran liegt, dass ich das meiste nicht verstehe. aber ich glaube, dass wir zu dem ganzen einfach unterschiedliche Meinungen haben.
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Vor nem halben Jahr konntest du das noch. viewtopic.php?t=41148

Die gleiche asoziale Attitüde hat sich allerdings auch schon in voller Pracht dargestellt....
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

kann es sein, dass du einen vollkommen falschen eindruck von mir hast? es ist nicht asozial, wenn es nicht böse gemeint ist.
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

machst du Python denn hobbymäßig oder beruflich?
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

jan.b hat geschrieben:kann es sein, dass du einen vollkommen falschen eindruck von mir hast? es ist nicht asozial, wenn es nicht böse gemeint ist.
Es kann natürlich sein, das ich dich verzerrt wahrnehme. Nur haben dir nahezu alle Leute die hier regelmäßig Posten, schon mal gesagt, dass an deinem Verhalten einiges zu wünschen übrig bleibt. Da wird die Chance, das es die Fehlwahrbehmung von mir ist, geringer ...
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi jan.b

Ein Teil deiner Frage im ersten Abschnitt dieses Threads war:
Hallo, wie kann ich diesen button umposittionieren?
Was verstehst du mit umposittionieren genau? Kannst du dein Vorhaben präziser beschreiben?

Gruss wuf :wink:
Take it easy Mates!
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

Das war nicht nett von mir.
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

Damit war das positionieren eines buttons nach ausgewählten Koordinaten innerhalb eines canvas Objektes gemeint.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

jan.b hat geschrieben:Damit war das positionieren eines buttons nach ausgewählten Koordinaten innerhalb eines canvas Objektes gemeint.
OK! Hier die Variante mit der Platzierung auf einer Canvas:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk

APP_TITLE = "Button placing on canvas"
APP_XPOS = 100
APP_YPOS = 100
APP_WIDTH = 600
APP_HEIGHT = 200

ANCHORS = ['center', 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw']
FONT = ('Helevetica', 14, 'bold')

        
class Application(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title(APP_TITLE)
        
    def build(self):
        self.protocol("WM_DELETE_WINDOW", self.close_app)
        self.geometry("+{}+{}".format(APP_XPOS, APP_YPOS))
        self.geometry("{}x{}".format(APP_WIDTH, APP_HEIGHT))
        self.option_add("*Button.highlightThickness", 0)
        
        self.canvas = tk.Canvas(self, bg='#FFFF00')
        self.canvas.pack(fill='both', expand=True)
        self.canvas.update_idletasks()
        
        self.pos_var = tk.StringVar()
        self.button = tk.Button(None, textvariable=self.pos_var, width=18,
            height=2, font=FONT)
        self.button.pack(padx=10, pady=10)
        
        self.button_width = self.button.winfo_reqwidth()
        self.button_height = self.button.winfo_reqheight()
        
        self.button_xpos = 0
        self.button_ypos = 0
        self.button_window = self.canvas.create_window(
            self.button_xpos,
            self.button_ypos,
            window=self.button, anchor='nw', tag='button')
        
        self.place_the_button()
        
    def place_the_button(self, pos_index=0):
        canvas_width = self.canvas.winfo_width()
        canvas_height = self.canvas.winfo_height()
        print(self.button_width, self.button_height, canvas_width, canvas_height)
        anchor = ANCHORS[pos_index]
        if anchor == 'center':
            xpos = (canvas_width-self.button_width) / 2
            ypos = (canvas_height-self.button_height) / 2
        elif anchor == 'n':
            xpos = (canvas_width-self.button_width) /2
            ypos = 0
        elif anchor == 'ne':
            xpos = (canvas_width-self.button_width)
            ypos = 0
        elif anchor == 'e':
            xpos = (canvas_width-self.button_width)
            ypos = (canvas_height-self.button_height) / 2
        elif anchor == 'se':
            xpos = (canvas_width-self.button_width)
            ypos = (canvas_height-self.button_height)
        elif anchor == 's':
            xpos = (canvas_width-self.button_width) / 2
            ypos = (canvas_height-self.button_height)
        elif anchor == 'sw':
            xpos = 0
            ypos = (canvas_height-self.button_height)
        elif anchor == 'w':
            xpos = 0
            ypos = (canvas_height-self.button_height) / 2
        elif anchor == 'nw':
            xpos = 0
            ypos = 0
            
        self.pos_var.set("Position:\n'{}'".format(anchor))    
        self.canvas.coords('button', xpos, ypos)
        pos_index += 1
        if pos_index == len(ANCHORS):
            pos_index = 0
            
        self.after(2000,self.place_the_button, pos_index)
        
    def close_app(self):
        # Here do something before apps shutdown
        print("Good Bye!")
        self.destroy()


def main():        
    app = Application()
    app.build()
    app.mainloop()

if __name__ == '__main__':
    main()
Gruss wuf :wink:
Take it easy Mates!
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

100 zeilen? ganz schön viel. danke für deine ausführliche hilfe. bis ich das ganz verstanden habe, muss ich wohl noch ein bisschen rum googeln, aber wenigstens die Basis habe ich jetzt. :D
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi jan.b

Hier noch eine Variante mit wesentlich weniger Zeilen:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk
 
       
class Application(tk.Tk):

    def __init__(self, title):
        tk.Tk.__init__(self)
        self.title(title)
        
        self.geometry("300x300")
        
        self.canvas = tk.Canvas(self, bg='#FFFF00')
        self.canvas.pack(fill='both', expand=True)
        self.canvas.update_idletasks()
        
        self.pos_var = tk.StringVar()
        self.button = tk.Button(None, text="Button-Widget", width=10)
        self.button.pack()
        
        # Alte Button Position        
        xpos = 0
        ypos = 0
        self.button_window = self.canvas.create_window(xpos, ypos,
            window=self.button, anchor='nw', tag='button')

        # Neue Button Position
        xpos = 150
        ypos = 150
        self.canvas.coords('button', xpos, ypos)


Application("Button placing on canvas").mainloop()
Gruss wuf :wink:
Take it easy Mates!
jan.b
User
Beiträge: 195
Registriert: Mittwoch 9. August 2017, 17:12

danke. ehrlich gesagt ist das sehr viel hilfreicher und motiviert mich dazu das ganze auch richtig durchzugehen. :D
Antworten