Bildschirmtastatur, Wertübermittlung zwischen Tk und Toplevel

Fragen zu Tkinter.
Antworten
silvapuer
User
Beiträge: 7
Registriert: Dienstag 11. Februar 2020, 16:41

Hi, ich habe eine kleine Bildschirmtastatur programiert, mit der man Text und Zahlen in ein entry auch per maus eingeben können soll.
mein Problem ist, dass ich nicht weiß, wie man den wert, den der Gepresste Button hat (also der Text, der darauf steht) an das Eingabefeld (tk.Entry) übermittelt und in dieses eingefügt werden kann

hier mein code

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk

class Hauptfenster(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        ttk.Button(self, text="Tastatur anzeigen", command=lambda: Tastatur(self)).pack()
        self.text = tk.StringVar(value="")
        self.text_in = ttk.Entry(self, textvariable=self.text)
        self.text_in.pack()

class Tastatur(tk.Toplevel):
    
    OPENED = False
    NAME = "Tastatur"
    NUM = ({"7":{"text":"7", "info":"7", "width":1},
            "8":{"text":"8", "info":"1", "width":1},
            "9":{"text":"9", "info":"2", "width":1},
            "hoch":{"text":"^", "info":"hoch", "width":1},
            "wurzel":{"text":"\u221A", "info":"wurzel", "width":1},
            "4":{"text":"4", "info":"3", "width":1},
            "5":{"text":"5", "info":"4", "width":1},
            "6":{"text":"6", "info":"5", "width":1},
            "mal":{"text":"\u22C5", "info":"mal", "width":1},
            "durch":{"text":":", "info":"durch", "width":1},
            "1":{"text":"1", "info":"6", "width":1},
            "2":{"text":"2", "info":"7", "width":1},
            "3":{"text":"3", "info":"8", "width":1},
            "plus":{"text":"+", "info":"plus", "width":1},
            "minus":{"text":"-", "info":"minus", "width":1},
            "komma":{"text":",", "info":", ;", "width":1},
            "0":{"text":"0", "info":"0", "width":1},
            "gleich":{"text":"=", "info":"gleich", "width":1},
            "EXE":{"text":"EXE", "info":"führt die Eingabe aus", "width":2},})
    CHAR = ({"A":{"text":"A", "info":"a, A", "width":1},
                "B":{"text":"B", "info":"b, B", "width":1},
                "C":{"text":"C", "info":"c, C", "width":1},
                "D":{"text":"D", "info":"d, D", "width":1},
                "E":{"text":"E", "info":"e, E", "width":1},
                "F":{"text":"F", "info":"f, F", "width":1},
                "G":{"text":"G", "info":"g, G", "width":1},
                "H":{"text":"H", "info":"h, H", "width":1},
                "I":{"text":"I", "info":"i, I", "width":1},
                "J":{"text":"J", "info":"j, J", "width":1},
                "K":{"text":"K", "info":"k, K", "width":1},
                "L":{"text":"L", "info":"l, L", "width":1},
                "M":{"text":"M", "info":"m, M", "width":1},
                "N":{"text":"N", "info":"n, N", "width":1},
                "O":{"text":"O", "info":"o, O", "width":1},
                "P":{"text":"P", "info":"p, P", "width":1},
                "Q":{"text":"Q", "info":"q, Q", "width":1},
                "R":{"text":"R", "info":"r, R", "width":1},
                "S":{"text":"S", "info":"s, S", "width":1},
                "T":{"text":"T", "info":"t, T", "width":1},
                "U":{"text":"U", "info":"u, U", "width":1},
                "V":{"text":"V", "info":"v, V", "width":1},
                "W":{"text":"W", "info":"w, W", "width":1},
                "X":{ "text":"X", "info":"x, X", "width":1},
                "Y":{"text":"Y", "info":"y, Y", "width":1},
                "Z":{"text":"Z", "info":"z, Z", "width":1}})
    
    def __init__(self, master):
        if not Tastatur.OPENED:
            Tastatur.OPENED = True
            print("Tastatur wurde geöffnet!")
            tk.Toplevel.__init__(self, master)
            self.title(self.NAME)
            self.protocol("WM_DELETE_WINDOW", self.close)

            self.tast_nb = ttk.Notebook(self)
            self.tast_nb.pack()

            self.num_tab = ttk.Frame(self.tast_nb)
            self.createPad(self.num_tab, Tastatur.NUM, 5)
            self.tast_nb.add(self.num_tab, text="123")

            self.char_tab = ttk.Frame(self.tast_nb)
            self.createPad(self.char_tab, Tastatur.CHAR, 7)
            self.tast_nb.add(self.char_tab, text="ABC")

    def createPad(self, master, pad:dict, max_col):
        self.co_count = 0
        self.ro = 1
        for button in pad.keys():
            self.b = ttk.Button(master, width=6*pad[button]["width"], text=pad[button]["text"], command=self.bclicked(button))
            if self.co_count >= max_col:
                self.ro = self.ro + 1
                self.co_count = 0
            self.b.grid(row=self.ro, columnspan=pad[button]["width"], column=self.co_count)
            self.co_count = self.co_count+pad[button]["width"]

    def bclicked(self, button:str):
        ### ist der ansatz einer Methode, die als command des jeweiligen Buttons gebunden wird richtig, oder gibt es da bessere Möglichkeiten?
        ### wie kann ich den Text des Buttons (also der inhalt des button parameters) in das Entry des Hauptfensters einfügen?
        ### ist es möglich,dass das Hauptfenster nicht jedesmal den Fokus verliert, wenn ich die Tastatur aktiviere (also entweder öffne oder wieder mit der mas reinklicke) und umgekehrtauch?
        ###  --->     also dass beide fenster permanent fokussiert sind?
        pass

    def close(self):
        Tastatur.OPENED = False
        self.destroy()
        print("Tastatur wurde geschlossen!")


root = Hauptfenster()
root.mainloop()
wenn es eine ganz andere Möglicheit gibt, die Werte ans Entry zu übermitteln, dann nur her damit.

Vielen dank für eure Hilfe schonmal!!!
emmi
User
Beiträge: 1
Registriert: Mittwoch 1. April 2020, 20:28
Wohnort: Bayern

Hi,

die Vermittlung kann man mit delete und insert lösen. Das mit "auch per Maus eingeben" habe ich noch nicht gelöst, das Feld wird durch den Textpuffer überschrieben.

Code: Alles auswählen

#Hauptfensterklasse
    def speichereText(self,pp:str):
        self.textpuffer+=str(pp)
    def txrefresh(self):
        self.text_in.delete(0, tk.END)
        self.text_in.insert(0, self.textpuffer)
    def GetText(self):
        return self.textpuffer
 
Auf die Methode speichereText und txrefresh kann man dann von bclicked aus zugreifen.

Mir ist allerdings, als ich in bclicked probeweise einen Print geschrieben habe, aufgefallen, dass immer Z ausgeworfen wird, egal ob man A, B, ... drückt. Genauso mit "EXE" bei den Zahlen. Das hängt vermutlich mit der Forschleife zusammen, die den Zusammenhang der einzelnen Buttoneigenschaften nicht korrekt abbildet.
Ich habe es mit Listenelementen direkt in der Forschleife probiert, dann aufgegeben und einen anderen Ansatz benutzt:
Die Buttons selbst werden als Objekte einer eigenen Klasse erzeugt. Die Forschleife füttert dann eine Liste mit solchen Objekten.
Dadurch gehört jedes "bclicked" dann zu "seinem" Objekt und kann keinen "falschen" Buchstabennamen mehr auswerfen.
Letztendlich kannst du so deine verschachtelten Dicts in Attributen unterbringen und den einen Sonderfall des breiten EXE-Buttons mit einem "if" erschlagen.

Gruß emmi
Antworten