Gibt es eine einfache Möglichkeit über die commandfunktion die Position des Frames zu verschieben?

Fragen zu Tkinter.
Antworten
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Das hatte apple mich gefragt.

@apple: ich weiß leider nicht, wo sich der oder die Buttons befinden sollen, die den Frame verschieben sollen. Ich habe sie mal in den Frame selber gelegt.

Aber das kann man umändern. Wenn man den Frame relativ zur augenblicklichen Position verschieben will, kann man die Koordinaten entweder durch place_info oder grid_info abfragen, oder man protokolliert die Position mit, indem man nicht grid oder place benutzt, sondern eigene Funktionen, die sich die Koordinaten merken.

Letzteres habe ich hier mal implementiert. Den Mause Cursor unsichtbar zu machen habe ich auskommentiert, weil man ohne den Mauszeiger zu sehen, schlecht Buttons drücken kann.

Ich habe eine Frameklasse MoveFrame implementiert mit Methoden, die sich die Koordinaten merken und mit Methoden zum Verschieben. Frame1, der verschoben wird, habe ich davon abgeleitet.

Code: Alles auswählen

from Tkinter import *

class MoveFrame(Frame):
    def __init__(self,master,**kwargs):
        Frame.__init__(self,master,**kwargs)

        self.x_or_column=0
        self.y_or_row=0

    def position_place(self,y,x):
        self.y_or_row = y
        self.x_or_column = x
        self.place(y=y,x=x)
        
    def position_grid(self,row,column):
        self.y_or_row = row
        self.x_or_column = column
        self.grid(row=row,column=column)

    def reposition_place(self):
        self.position_place(self.y_or_row,self.x_or_column)

    def reposition_grid(self):
        self.position_grid(self.y_or_row,self.x_or_column)

    def move_place(self,dy,dx):
        self.position_place(self.y_or_row + dy, self.x_or_column + dx)

    def move_grid(self,drow,dcolumn):
        self.position_grid(self.y_or_row + drow, self.x_or_column + dcolumn)

    def nach_oben(self):
        self.move_place(-10,0)

    def nach_unten(self):
        self.move_place(10,0)

    def nach_rechts(self):
        self.move_place(0,10)

    def nach_links(self):
        self.move_place(0,-10)


class Frame1(MoveFrame):
    def __init__(self,master,**kwargs):
        MoveFrame.__init__(self,master,**kwargs)

        Button(self,text='nach oben',command=self.nach_oben).grid(row=0,column=1)
        Button(self,text='nach links',command=self.nach_links).grid(row=1,column=0)
        Button(self,text='nach rechts',command=self.nach_rechts).grid(row=1,column=2)
        Button(self,text='nach unten',command=self.nach_unten).grid(row=2,column=1)
        
class FullScreenApp(Tk):
    def __init__(self):
        Tk.__init__(self)
       
        self.configure(background='black')
        self.geometry("480x800+0+0")
        self.attributes('-fullscreen', True)
        self.bind('<Escape>',self.toggle_geom)
        self.bind('<Delete>',self.test)
        #self.config(cursor="none")
        Frame1(self,bg='yellow').position_place(0,0)

    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-3))
    def test(self,event):
        self.geometry("200x200+0+0")

FullScreenApp().mainloop()
@apple: könntest Du vielleicht näher beschreiben, was Du genau machen willst?

An Alle: Achtung die Escape Taste Drücken, damit man die Anwendung wieder schließen kann.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: statt alle Methoden doppelt zu definieren, würde ich mir ja merken, ob das Widget per place oder per grid positioniert wurde. Der Sinn von reposition_xxx ist mir nicht ganz klar. Statt position_grid und position_place würde ich grid und place überschreiben, dann unterscheidet sich dieser Frame nicht so sehr von anderen.

Code: Alles auswählen

class MoveFrame(Frame):
    def __init__(self, master, **kwargs):
        Frame.__init__(self, master, **kwargs)
        self.positioning_method = None
        self.x_or_column = 0
        self.y_or_row = 0

    def place(self, y, x):
        self.positioning_method = self.place
        self.y_or_row = y
        self.x_or_column = x
        Frame.place(self, y=y, x=x)

    def grid(self, row, column):
        self.positioning_method = self.grid
        self.y_or_row = row
        self.x_or_column = column
        Frame.grid(self, row=row, column=column)

    def move(self, dy, dx):
        self.positioning_method(self.y_or_row + dy, self.x_or_column + dx)
PS: Sternchenimporte sind böse.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:Der Sinn von reposition_xxx ist mir nicht ganz klar.
reposition_grid ist unnötig, da bei grid_remove die layout Optionen erhalten bleiben. Bei place gibt es allerdings nur place_forget, da sind dann die layout Optionen und damit auch die Koordinaten weg. Mit reposition_place kann man nach place_forget zumindest wieder auf die vorherige Position setzen.

reposition_grid könnte man wohl besser auch so definieren:

Code: Alles auswählen

def reposition_grid(self):
    self.grid()
Nur wegen Vollständiigkeit gegenüber reposition_place
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@apple: hier die vielleicht für Dich einfachere Lösung mit place_info, die auch universeller ist, nämlich ohne Klassendefinition auf alle Gui Elemente anwendbar:

Code: Alles auswählen

from Tkinter import *

def move_place(gui_element,dy,dx):
    layout_dict = gui_element.place_info()
    y = int(layout_dict['y'])
    x = int(layout_dict['x'])
    gui_element.place(y=y+dy,x=x+dx)


class Frame1(Frame):
    def __init__(self,master,**kwargs):
        Frame.__init__(self,master,**kwargs)
 
        Button(self,text='nach oben',command = lambda me = self : move_place(me,-10,0)).grid(row=0,column=1)
        Button(self,text='nach links',command = lambda me = self : move_place(me,0,-10)).grid(row=1,column=0)
        Button(self,text='nach rechts',command = lambda me = self : move_place(me,0,10)).grid(row=1,column=2)
        Button(self,text='nach unten',command = lambda me = self : move_place(me,10,0)).grid(row=2,column=1)
 

class FullScreenApp(Tk):
    def __init__(self):
        Tk.__init__(self)
       
        self.configure(background='black')
        self.geometry("480x800+0+0")
        self.attributes('-fullscreen', True)
        self.bind('<Escape>',self.toggle_geom)
        self.bind('<Delete>',self.test)
        #self.config(cursor="none")
        Frame1(self,bg='yellow').place(y=0,x=0)
 
    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-3))
    def test(self,event):
        self.geometry("200x200+0+0")
 
FullScreenApp().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@apple: noch universeller bekommt man die Koordinaten mit winfo_rootx und winfo_rooty. Da spielt es dann keine Rolle ob das Gui Element zuerst ein grid, pack oder place layout hatte:

Code: Alles auswählen

def move_place(me,dy,dx):
    x = me.winfo_rootx()-me.master.winfo_rootx()
    y = me.winfo_rooty()-me.master.winfo_rooty()
    me.place(y=y+dy,x=x+dx)
apple
User
Beiträge: 8
Registriert: Sonntag 16. April 2017, 15:58

Um die Funktion zu beschreiben:

Ich habe zunächst den schwarzen Fullscreen, wo sich ein Button unten mittig befindet (buuton.place(x=, y=, anchor' '). Wenn ich diesen Button betätige soll ein Frame von unten (aus dem unendlichen bzw. zunächst nicht sichtbar) nach oben in eine definierte Position verschoben werden. Bei erneutem Betätigen des Buttons soll der Frame wieder nach unten ins unendliche verschoben werden.

Der Button zum verschieben soll nicht auf dem Frame selbst sein.

Später sollen noch weitere Buttons auf dem Frame platziert werden
Es soll also so ne Art Menü wie beim Smartphone sein, wo mehrere Apps in einem Ordner untergebracht sind. :D

Ich hoffe, dass die Funktion nun etwas klarer ist.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi apple

Ja es gibt eine einfache Möglichkeit ein Frame zu verschieben:

Code: Alles auswählen

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

try:
    # Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
    # Tkinter for Python 3.xx
    import tkinter as tk

APP_TITLE = "The Rising Frame"
APP_BACK_GND = 'black'

FRAME_WIDTH = 600
FRAME_HEIGHT = 400
FRAME_COLOR = 'yellow'
FRAME_YEND_POSITION = 200
LABEL_TEXT = "The Rising Frame"
LABEL_FONT = ('Helfetica', 26, 'bold')

UP = 'up'
DOWN = 'down'


class Application(object):

    def __init__(self, app_win):
        self.app_win = app_win
        
        self.screen_width = app_win.winfo_screenwidth()
        self.screen_height = app_win.winfo_screenheight()
        self.frame_xpos = (self.screen_width - FRAME_WIDTH) / 2
        self.frame_ypos = self.screen_height 
        self.move_direction = DOWN
        self.move_flag = False
        
        self.the_rising_frame = tk.Frame(self.app_win, bg=FRAME_COLOR)
        self.the_rising_frame.place(x=self.frame_xpos, y=self.frame_ypos,
            width=FRAME_WIDTH, height=FRAME_HEIGHT)
        
        tk.Label(self.the_rising_frame, text=LABEL_TEXT, font=LABEL_FONT,
            bg=self.the_rising_frame['bg']).pack(expand=True)
            
        tk.Button(app_win, text="Auferstehung", command=self.button_callback
            ).pack(side='bottom')

    def button_callback(self):
        if not self.move_flag:
            self.move_flag = True
            if self.move_direction == DOWN:
                self.move_direction = UP
            else:
                self.move_direction = DOWN
            self.move_the_frame(self.frame_ypos)
            
    def move_the_frame(self, ypos):
        if self.move_direction == UP:
            ypos -= 4
            if ypos < FRAME_YEND_POSITION:
                self.move_flag = False
                return
        else:
            ypos += 4
            if ypos > self.screen_height:
                self.move_flag = False
                return
                
        self.frame_ypos = ypos    
        self.the_rising_frame.place_configure(y=ypos)
        self.app_win.after(10, self.move_the_frame, ypos)

        
def main():
    app_win = tk.Tk()
    app_win.attributes('-zoomed', True)
    app_win.config(bg=APP_BACK_GND)
    app_win.title(APP_TITLE)
    app = Application(app_win)
    app_win.mainloop()
 
 
if __name__ == '__main__':
    main()      
Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@apple: das ist es dann wohl?

Code: Alles auswählen

from Tkinter import *

class Wish_Frame(Frame):
    def __init__(self,master,**kwargs):
        Frame.__init__(self,master,**kwargs)

        # Zum Anpassen =====
        self.rel_yup = 0.5
        self.timestep=3
        # ==================

        self.is_down = True
        self.place(rely=1,x=0,relwidth=1,relheight=1-self.rel_yup)


    def wish_start(self):
        ydown = self.master.winfo_height()
        yup = int(ydown * self.rel_yup)
        if self.is_down:
            self.is_down = False
            self._wish(ydown,yup,-1,self.timestep)
        else:
            self.is_down = True
            self._wish(yup,ydown,1,self.timestep)
 
    def _wish(self,y0, yn, step,timestep):
        def do_move(y):
            y += step
            self.place(y=y,rely=0)
            if y != yn:
                self.after(timestep, do_move,y)
            else:
                if self.is_down:
                    self.place(y=0,rely=1)
                else:
                    self.place(y=0,rely=self.rel_yup)
        do_move(y0) 


class App_Frame(Wish_Frame):
    def __init__(self,master,**kwargs):
        Wish_Frame.__init__(self,master,**kwargs)

class FullScreenApp(Tk):
    def __init__(self):
        Tk.__init__(self)
       
        self.configure(background='black')
        self.geometry("480x800+0+0")
        self.attributes('-fullscreen', True)
        self.bind('<Escape>',self.toggle_geom)
        self.bind('<Delete>',self.test)
        self.app_frame = App_Frame(self,bg='yellow')
        self.wish_button = Button(self,text = 'wish',command=self.app_frame.wish_start)
        self.wish_button.pack(side = BOTTOM)
 
    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-3))
    def test(self,event):
        self.geometry("200x200+0+0")
 
FullScreenApp().mainloop()
apple
User
Beiträge: 8
Registriert: Sonntag 16. April 2017, 15:58

@Alfons: Perfekt genau nach so einer Anwendung habe ich gesucht.

Danke :D :D
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: kannst Du die Sternchenimporte nicht durch richtige Importe ersetzen. Es gibt hier Leute, die nicht regelmäßig mitlesen, und denken, es wäre eine gute Idee, Sternchenimporte zu benutzen. Für Dich ist es kein Aufwand das zu ändern, allen Anfängern hilft es aber, besseren Code zu schreiben.

Auch hier hat das Einblenden von Frames nichts mit Wünschen zu tun. Warum übergibst Du _wish als Argument timestep, obwohl dieses ja schon als Attribut auf diesem Objekt existiert? Das ist unnötig. Die Lösung von wuf ist schöner, da wildes Clicken auf den Button nicht zu unschönen Sprüngen führt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: kannst Du die Sternchenimporte nicht durch richtige Importe ersetzen.
Wollte mich an das ursprüngliche Programm von apple halten, aber hast recht, da sollte man nicht den Sternchenimport des Codeschreibers beibehalten.
Sirius3 hat geschrieben:Auch hier hat das Einblenden von Frames nichts mit Wünschen zu tun. Warum übergibst Du _wish als Argument timestep, obwohl dieses ja schon als Attribut auf diesem Objekt existiert? Das ist unnötig.
Diese Methode _wish sollte eingentlich unabhängig vom Gebrauch als Methode einer Gui Klasse mit ganz bestimmten Attributen sein. Habe sie jetzt als Funktion ausgelagert, damit man dann damit verschiedene Gui Objekte verschieben kann, auch ohne dafür eine eigene Klasse zu haben.
Sirius3 hat geschrieben:Die Lösung von wuf ist schöner, da wildes Clicken auf den Button nicht zu unschönen Sprüngen führt.
Habe das jetzt auch mit berücksichtigt. Außerdem habe ich die Schrittweite beim Verschieben veränderlich gemacht, damit man bei einem Bildschirm mit hoher Auflösung und Fullscreen auch schnell den Frame verschieben kann.

Code: Alles auswählen

import Tkinter as tk

FRAME_REL_TOP = 0.4
FRAME_REL_BOTTOM = 1
FRAME_REL_X = 0
FRAME_REL_WIDTH = 1 - 2 * FRAME_REL_X
WISH_TIMESTEP = 3
WISH_STEP = 1


def move_object(object_to_move,y0, yn, step, timestep,clearmoving = None,rel_yn = None):
    def do_move(y):
        y += step
        object_to_move.place(y=y,rely=0)
        if step > 0 and y < yn or step < 0 and y > yn:
            object_to_move.after(timestep, do_move,y)
        else:
            if rel_yn:
                object_to_move.place(y=0,rely=rel_yn)
                
            if clearmoving:
                clearmoving()
    do_move(y0) 


class Wischen_Frame(tk.Frame):
    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)

        # Zum Anpassen =====
        self.rel_yup = FRAME_REL_TOP
        self.rel_ydown = 1
        self.timestep = WISH_TIMESTEP
        self.step = WISH_STEP
        self.place(rely=self.rel_ydown,relx=FRAME_REL_X,relwidth=FRAME_REL_WIDTH,relheight = FRAME_REL_BOTTOM - FRAME_REL_TOP)
        # ==================

        self.is_moving = False
        self.is_down = True


    def clear_moving(self):
        self.is_moving = False


    def wischen_start(self):
        if not self.is_moving:
            self.is_moving = True
            ydown = self.master.winfo_height()
            yup = int(ydown * self.rel_yup)
            if self.is_down:
                self.is_down = False
                move_object(self,ydown,yup,-self.step,self.timestep,self.clear_moving,self.rel_yup)
            else:
                self.is_down = True
                move_object(self,yup,ydown,self.step,self.timestep,self.clear_moving,self.rel_ydown)
     

class App_Frame(Wischen_Frame):
    def __init__(self,master,**kwargs):
        Wischen_Frame.__init__(self,master,**kwargs)
        

class FullScreenApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
       
        self.configure(background='black')
        self.geometry("480x800+0+0")
        self.attributes('-fullscreen', True)
        self.bind('<Escape>',self.toggle_geom)
        self.bind('<Delete>',self.test)
        self.app_frame = App_Frame(self,bg='yellow')
        self.wischen_button = tk.Button(self,text = 'Wischen',command=self.app_frame.wischen_start)
        self.wischen_button.pack(side = tk.BOTTOM)

 
    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-3))
    def test(self,event):
        self.geometry("200x200+0+0")
 
FullScreenApp().mainloop()
apple
User
Beiträge: 8
Registriert: Sonntag 16. April 2017, 15:58

@Alfons:

Ich habe nun das Programm um einen weiteren Button auf dem schwarzen Hauptscreen erweitert. Nun möchte ich, dass dieser gelöscht wird, sobald die Wischfunktion aufgerufen wird. Wenn das Wischfenster wieder in seiner Ausgangslage ist, soll der Button wieder angezeigt werden. :D

Alternativ kann auch das Frame einfach über den Button gelegt werden (Schema Vorder- und Hintergrund).. :K

Kurz um der Button soll am Ende hinter dem Frame "versteckt" sein.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

apple hat geschrieben:@Alfons:Ich habe nun das Programm um einen weiteren Button auf dem schwarzen Hauptscreen erweitert. Nun möchte ich, dass dieser gelöscht wird, sobald die Wischfunktion aufgerufen wird. Wenn das Wischfenster wieder in seiner Ausgangslage ist, soll der Button wieder angezeigt werden. :D
Nein Löschen macht man nicht, sondern nur ihn unsichtbar machen, wenn man ihn noch braucht.
apple hat geschrieben:Alternativ kann auch das Frame einfach über den Button gelegt werden (Schema Vorder- und Hintergrund).. :K
Das ist die beste Idee, weil Du hier nichts extra kodieren brauchst.[/quote]
apple hat geschrieben:Kurz um der Button soll am Ende hinter dem Frame "versteckt" sein.
Eine Lösung, die Auflösungsunabhängig ist, ist da nicht ganz simple.

Für der anderen Button habe ich einen weiteren Frame spendiert, der die Hälfte des Bildschirms breit ist. Da kann man mit pack positionieren. Der Wischen Button wird mit place positioniert und bekommt seine y Koordinate vom anderen Button. Wenn sich die Geometrie ändert, wird seine Position angepaßt

Code: Alles auswählen

import Tkinter as tk

FRAME_REL_TOP = 0.4
FRAME_REL_BOTTOM = 1
FRAME_REL_X = 0
FRAME_REL_WIDTH = 1 - 2 * FRAME_REL_X
WISH_TIMESTEP = 3
WISH_STEP = 1
BUTTON_PADX = 5

def move_object(object_to_move,y0, yn, step, timestep,clearmoving = None,rel_yn = None):
    def do_move(y):
        y += step
        object_to_move.place(y=y,rely=0)
        if step > 0 and y < yn or step < 0 and y > yn:
            object_to_move.after(timestep, do_move,y)
        else:
            if rel_yn:
                object_to_move.place(y=0,rely=rel_yn)
                
            if clearmoving:
                clearmoving()
    do_move(y0) 


class Wischen_Frame(tk.Frame):
    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)

        # Zum Anpassen =====
        self.rel_yup = FRAME_REL_TOP
        self.rel_ydown = 1
        self.timestep = WISH_TIMESTEP
        self.step = WISH_STEP
        self.place(rely=self.rel_ydown,relx=FRAME_REL_X,relwidth=FRAME_REL_WIDTH,relheight = FRAME_REL_BOTTOM - FRAME_REL_TOP)
        # ==================

        self.is_moving = False
        self.is_down = True


    def clear_moving(self):
        self.is_moving = False


    def wischen_start(self):
        if not self.is_moving:
            self.is_moving = True
            ydown = self.master.winfo_height()
            yup = int(ydown * self.rel_yup)
            if self.is_down:
                self.is_down = False
                move_object(self,ydown,yup,-self.step,self.timestep,self.clear_moving,self.rel_yup)
            else:
                self.is_down = True
                move_object(self,yup,ydown,self.step,self.timestep,self.clear_moving,self.rel_ydown)
     

class App_Frame(Wischen_Frame):
    def __init__(self,master,**kwargs):
        Wischen_Frame.__init__(self,master,**kwargs)

class Frame_Links(tk.Frame):

    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)
        self.button = tk.Button(self,text = 'Anderes')
        self.button.pack(side = tk.RIGHT, padx =  BUTTON_PADX, anchor = 's')


class FullScreenApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
       
        self.configure(background='black')
        self.geometry("480x800+0+0")
        self.attributes('-fullscreen', True)
        self.bind('<Escape>',self.toggle_geom)
        self.bind('<Delete>',self.test)

        self.frame_links = Frame_Links(self,bg='black')
        self.frame_links.place(x=0,y=0,relwidth=0.5,relheight=1)
        self.app_frame = App_Frame(self,bg='yellow')
        self.wischen_button = tk.Button(self,text = 'Wischen',command=self.app_frame.wischen_start)
        self.wischen_button.place(x=0,y=0)
        self.bind('<Configure>',self.position_wischen_button)

    def position_wischen_button(self,event):
        # wisch button nach Geometrie positionieren
        ypos = self.frame_links.button.winfo_rooty()-self.winfo_rooty()
        xpos = self.winfo_width()/2 + BUTTON_PADX
        self.wischen_button.place(x=xpos,y=ypos)

    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-3))
    def test(self,event):
        self.geometry("200x200+0+0")

 
FullScreenApp().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@apple: das Vorige war keine gute Lösung
Der zweite Frame und die Anpassung der Geometrie war unnötig. Man macht das mit place und relativen Koordinaten. Für beide Buttons die relx Position 0.5 und die rely Position 1. Damit sie nebeneinander sind, setzt man anchor entsprechend auf die untere rechte, bzw. linke Ecke. Und den Abstand bekommt man indem man zusätzlich zu relx auch noch x benutzt.

Code: Alles auswählen

import Tkinter as tk

FRAME_REL_TOP = 0.4
FRAME_REL_BOTTOM = 1
FRAME_REL_X = 0
FRAME_REL_WIDTH = 1 - 2 * FRAME_REL_X
WISH_TIMESTEP = 3
WISH_STEP = 1
BUTTON_PADX = 5

def move_object(object_to_move,y0, yn, step, timestep,clearmoving = None,rel_yn = None):
    def do_move(y):
        y += step
        object_to_move.place(y=y,rely=0)
        if step > 0 and y < yn or step < 0 and y > yn:
            object_to_move.after(timestep, do_move,y)
        else:
            if rel_yn:
                object_to_move.place(y=0,rely=rel_yn)
                
            if clearmoving:
                clearmoving()
    do_move(y0) 


class Wischen_Frame(tk.Frame):
    def __init__(self,master,**kwargs):
        tk.Frame.__init__(self,master,**kwargs)

        # Zum Anpassen =====
        self.rel_yup = FRAME_REL_TOP
        self.rel_ydown = 1
        self.timestep = WISH_TIMESTEP
        self.step = WISH_STEP
        self.place(rely=self.rel_ydown,relx=FRAME_REL_X,relwidth=FRAME_REL_WIDTH,relheight = FRAME_REL_BOTTOM - FRAME_REL_TOP)
        # ==================

        self.is_moving = False
        self.is_down = True

    def clear_moving(self):
        self.is_moving = False

    def wischen_start(self):
        if not self.is_moving:
            self.is_moving = True
            ydown = self.master.winfo_height()
            yup = int(ydown * self.rel_yup)
            if self.is_down:
                self.is_down = False
                move_object(self,ydown,yup,-self.step,self.timestep,self.clear_moving,self.rel_yup)
            else:
                self.is_down = True
                move_object(self,yup,ydown,self.step,self.timestep,self.clear_moving,self.rel_ydown)
     
class App_Frame(Wischen_Frame):
    def __init__(self,master,**kwargs):
        Wischen_Frame.__init__(self,master,**kwargs)

class FullScreenApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
       
        self.configure(background='black')
        self.geometry("480x800+0+0")
        self.attributes('-fullscreen', True)
        self.bind('<Escape>',self.toggle_geom)
        self.bind('<Delete>',self.test)

        self.anderer_button = tk.Button(self,text = 'Anders')
        self.anderer_button.place(x=-BUTTON_PADX,relx=0.5,rely=1,anchor='se')
        self.app_frame = App_Frame(self,bg='yellow')
        self.wischen_button = tk.Button(self,text = 'Wischen',command=self.app_frame.wischen_start)
        self.wischen_button.place(x=BUTTON_PADX,relx=0.5,rely=1,anchor='sw')

    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-3))
    def test(self,event):
        self.geometry("200x200+0+0")

 
FullScreenApp().mainloop()
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@apple: das mit self.winfo_screenheight() um die Größe des Hauptfensters für eine Screenfüllende Größe zu bestimmen, haut nicht gant hin, denn das Anwendungsfenster hat oben noch eine Leiste. Am Anfang hat man einen Fullscreen. Wenn man dann Escape drückt, herät das Fenster zu groß.

Für Windows gibt es ein attribut, für Linux nicht. Also muss man es in dieser Art machen. Jedoch kann man auch die Höhe der Leiste oben bestimmen, um so die genaue Höhe für das Anwendungsfenster zu berechnen.

Dazu ermittelt man mit winfo_rooty() die Y Position bei welcher der Bereich für den Inhalt des Anwendungsfensters beginnt. Wo aber das Anwendungsfenster beginnt, ermittelt man aus dem geometrie String. Und dann wird es richtig. Hier eine Ergänzung:

Code: Alles auswählen

        self.balkenhoehe = 0

    def toggle_geom(self,event):
        self.attributes('-fullscreen', False)
        if self.balkenhoehe:
            self.update_fullscreen()
        else:
            self.after(100,self.update_fullscreen)

    def test(self,event):
        self.geometry("200x200+0+0")

    def update_fullscreen(self):
        if not self.balkenhoehe:
            ygeo = int(self.geometry().split('+')[2])
            yself = self.winfo_rooty()
            self.balkenhoehe = yself-ygeo
        self.geometry("{0}x{1}+0+0".format(self.winfo_screenwidth()-3, self.winfo_screenheight()-self.balkenhoehe-3))
Antworten