Tkinter: проблема фокуса при поднятии кадра - PullRequest
0 голосов
/ 05 февраля 2020

Следующий код - GUI для сенсорного экрана (без мыши, без клавиатуры). Ввод - сенсорный экран, и он реагирует как щелчок мыши. Это урезанная из более крупной программы, чтобы показать проблему. Он имеет 3 кадра, которые поднимаются по мере необходимости. В идеале, я бы хотел, чтобы фокус нигде не находился до тех пор, пока пользователь не щелкнет (указывает) на поле, а затем клавиатура вводит цифры в поле фокуса в кадрах Машина 1 или Машина 2. Это работает хорошо, но если пользователь сначала не нажимает "в поле ввода это генерирует исключение: AttributeError: у объекта 'machine1' нет атрибута 'insert'.

Я был бы рад, если бы ввод с клавиатуры go был бы" битовой корзиной "или невидимое (и неиспользуемое) поле для ввода фиктивных символов, но можно принять, что по умолчанию при поднятии кадра фокус автоматически помещается на первое поле.

После многих часов и исследований в Интернете я был не может найти решение. Спасибо, что указал мне правильное направление.

import tkinter as tk
from tkinter import font  as tkfont  

class MyApp(tk.Tk):

    def __init__(self, *args, **kwargs):

        tk.Tk.__init__(self, *args, **kwargs)

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        # the container is where we stack the frames
        # then the one we want visible is raised above the others
        container = tk.Frame(self)
        container.grid(row=0, column=0, sticky='news')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}
        self.frames["machine1"] = machine1(parent=container, controller=self)
        self.frames["machine2"] = machine2(parent=container, controller=self)
        self.frames["running"] = running(parent=container, controller=self)


        self.frames["machine1"].grid(row=0, column=0, sticky="nsew")
        self.frames["machine2"].grid(row=0, column=0, sticky="nsew")
        self.frames["running"].grid(row=0, column=0, sticky="nsew")

        self.show_frame("running")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()
        frame.focus_set() # this removed focus from the hidden window



class Keypad(tk.Frame):

    cells = [
        ['1', '2', '3', '4', '5'],
        ['6', '7', '8', '9', '0'],
        ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        for y, row in enumerate(self.cells):
            for x, item in enumerate(row):
                b = tk.Button(self, text=item, command=lambda text=item:self.append(text))
                b.grid(row=y, column=x, sticky='news')

        x = tk.Button(self, text='Backspace', command=self.backspace)
        x.grid(row=0, column=10, sticky='news')

        x = tk.Button(self, text='Clear', command=self.clear)
        x.grid(row=1, column=10, sticky='news')


    def get(self):
        widget = self.focus_get()
        return widget.get()

    def append(self, text):
    # get the widget with the focus
         widget = self.focus_get()
    # insert the value
         widget.insert("insert", text)

    def clear(self):
        widget = self.focus_get()
        widget.delete(0, 'end')

    def backspace(self):
        widget = self.focus_get()
        text = widget.get()
        text = text[:-1]
        self.clear()
        self.append(text)


class machine1(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Machine 1", font=controller.title_font)
        label.grid(row=0, column=0, sticky='news')

        e1 = tk.Entry(self, highlightthickness = 2)
        e1.grid(row=2, column=0, sticky='news')
        e1.focus_set()   # by default start with this one

        e2 = tk.Entry(self, highlightthickness = 2)
        e2.grid(row=3, column=0, sticky='news')

        kbd = Keypad(self)
        kbd.grid(row=5, column=0, columnspan=3)

        button3 = tk.Button(self, text="Run",
                            command=lambda: controller.show_frame("running"))
        button3.grid(row=6, column=2, sticky='news')        


class machine2(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Machine 2", font=controller.title_font)
        label.grid(row=0, column=0, sticky='news')

        e1 = tk.Entry(self, highlightthickness = 2)
        e1.grid(row=2, column=0, sticky='news')
        e1.focus_set()   # by default start with this one

        e2 = tk.Entry(self, highlightthickness = 2)
        e2.grid(row=3, column=0, sticky='news')

        kbd = Keypad(self)
        kbd.grid(row=5, column=0, columnspan=3)

        button3 = tk.Button(self, text="Run",
                            command=lambda: controller.show_frame("running"))

        button3.grid(row=6, column=2, sticky='news')


class running(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="Run", font=controller.title_font)
        label.grid(row=0, column=0, sticky='news')

        button1 = tk.Button(self, text="Machine 1",
                           command=lambda: controller.show_frame("machine1"))
        button2 = tk.Button(self, text="Machine 2",
                           command=lambda: controller.show_frame("machine2"))

        button1.grid(row=5, column=0, sticky='news')
        button2.grid(row=5, column=1, sticky='news')

        e1 = tk.Entry(self, highlightthickness = 2)
        e1.grid(row=1, column=1, sticky='news')


if __name__ == "__main__":

    app = MyApp()
    app.geometry("800x480")
    app.mainloop()
``b

1 Ответ

0 голосов
/ 05 февраля 2020

Что-то всегда имеет фокус, даже если это просто окно root.

Самое простое решение в вашем случае - убедиться, что фокус находится на виджете ввода, что вы можете сделать так:

def append(self, text):
     widget = self.focus_get()
     if widget.winfo_class() == "Entry":
         widget.insert("insert", text)
...