Kivy keyboard_on_key_down 工作不转换其中一个输入的文本

Kivy keyboard_on_key_down working doesn't convert text on one of inputs

我的代码有点问题 - 我有 5 个 TextInputs,我想在按下按钮时写字母我移到另一个 window,它按原样工作正常。 每当我尝试在不打开大写锁定的情况下进行书写时,问题就出现了,前 4 个字母将通过 self.text=text.upper() 函数转换,但是最后一个字母似乎不起作用 - 它读取字母两次 - 第一个来自函数,然后一个字母作为小写字母,但我不知道它来自哪里以及如何防止我的代码使用它。

import kivy
import sys
kivy.require('1.11.1')
from kivy.app import App
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.app import App
from kivy.clock import Clock
from random import choice
import math
from kivy.properties import StringProperty
import string 
from functools import partial
letters= string.ascii_lowercase
Builder.load_file("GuessWord.kv")

def set_color(letter, color):
    COLORS_DICT  = {"W" : "ffffff", "Y" : "ffff00", "G" : "00ff00"}
    c = COLORS_DICT.get(color, "W")
    return f"[color={c}]{letter}[/color]"

class MyTextInput(TextInput):   
    focused = 'id1'

    def change_focus(self, *args):
        app = App.get_running_app()
        if app.root is not None:
            # Now access the container.
            layout = app.root.ids["layout"]
            # Access the required widget and set its focus.
            print("Changefocus", MyTextInput.focused)
            layout.ids[MyTextInput.focused].focus = True

    def keyboard_on_key_down(self, window, keycode, text, modifiers):
        print(keycode,text)
        focusedid = int(MyTextInput.focused[2])


        if keycode[1] == "backspace":
            if self.text=="":
                if int(MyTextInput.focused[2]) > 1:
                    self.text = ""
                    focusedid -= 1
                    MyTextInput.focused = "id" + str(focusedid)
            else:
                self.text = self.text[:-1]
        if keycode[1] == "right":
            if int(MyTextInput.focused[2]) < 5:
                focusedid += 1
                MyTextInput.focused = "id" + str(focusedid)
            elif int(MyTextInput.focused[2]) == 5:
                MyTextInput.focused = "id" + str(1)
                
        elif keycode[1] == "left":
            if int(MyTextInput.focused[2]) > 1:
                focusedid -= 1
                MyTextInput.focused = "id" + str(focusedid)
            elif int(MyTextInput.focused[2]) == 1:
                MyTextInput.focused = "id" + str(5)
        
        elif keycode[1] in letters:
            if int(MyTextInput.focused[2]) <= 5:
                self.text=text.upper()
                if int(MyTextInput.focused[2]) <5 :               
                    focusedid += 1
                    MyTextInput.focused = "id" + str(focusedid)
                
            
        self.change_focus()
        print("After changing", MyTextInput.focused)
        return True
class MainScreen(Widget):
    pass                 
class TestingappApp(App):
    def build(self):
        return MainScreen()
    
TestingappApp().run()

.kv 文件

#:import Clock kivy.clock.Clock
#:import threading threading
#:import partial functools.partial



<MainScreen>:
    BoxLayout:
        size: root.size
        orientation: "vertical"             
        CustomBox:
            size_hint: 1,0.5
            id: layout
            cols:5

<CustomBox@BoxLayout>:
    MyTextInput:
        id: id1
        font_size: 120
        halign: "center"
        focus: True
        focused: "id1"
        multiline: False
    MyTextInput:
        id: id2
        font_size: 120
        halign: "center"
        focused: "id2"
        multiline: False
    MyTextInput:
        id: id3
        font_size: 120
        halign: "center"
        focused: "id3"
        multiline: False
    MyTextInput:
        id: id4
        font_size: 120
        halign: "center"
        focused: "id4"
        multiline: False
    MyTextInput:
        id: id5
        font_size: 120
        halign: "center"
        focused: "id5"
        multiline: False

问题是代码比较复杂:

  • 首先是 运行s keyboard_on_key_down() 用于在小部件中添加文本,
  • 接下来它检查焦点,如果焦点相同,则它 运行s input_text() 这是小部件中 put/add 文本的正确功能,它添加第二个字符,
  • 接下来还可能运行 on_text()self.text改变时执行,
  • 最后 运行s keyboard_on_key_up()

所以最后一个小部件不会改变焦点,所以它 运行s insert_text() 添加了第二个字符。但是您可以创建空函数 insert_text() 来停止它。它也会停止数字等

    def insert_text(self, substring, from_undo=False):
        pass

但也许所有代码都应该在 insert_text() 中 运行 而不是 `keyboard_on_key_down()


请参阅文本输入文档:


完整代码(.kv相同):

import kivy
import sys
kivy.require('1.11.1')
from kivy.app import App
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.lang import Builder
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.textinput import TextInput
from kivy.uix.label import Label
from kivy.app import App
from kivy.clock import Clock
from random import choice
import math
from kivy.properties import StringProperty
import string 
from functools import partial

letters = string.ascii_lowercase
Builder.load_file("GuessWord.kv")

def set_color(letter, color):
    COLORS_DICT  = {"W" : "ffffff", "Y" : "ffff00", "G" : "00ff00"}
    c = COLORS_DICT.get(color, "W")
    return f"[color={c}]{letter}[/color]"

class MyTextInput(TextInput):   
    focused = 'id1'

    def change_focus(self, *args):
        app = App.get_running_app()
        if app.root is not None:
            # Now access the container.
            layout = app.root.ids["layout"]
            # Access the required widget and set its focus.
            print("Changefocus", MyTextInput.focused)
            layout.ids[MyTextInput.focused].focus = True

    def insert_text(self, substring, from_undo=False):
        print('[insert_text] substring:', substring)
        print('[insert_text] self.text:', self.text)
        #substring = substring.upper()
        #return super().insert_text(substring, from_undo=from_undo)        

    def on_text(self, instance, value):
        print('[on_text]', instance, 'have:', value)

    def keyboard_on_key_up(self, window, keycode):
        print('[keyboard_on_key_up] keycode:', keycode)
        print('[keyboard_on_key_up] self.text:', self.text)
        print('---')

    def keyboard_on_key_down(self, window, keycode, text, modifiers):
    
        print('[keyboard_on_key_down] keycode:', keycode)
        print('[keyboard_on_key_down] text:', text)
        print('[keyboard_on_key_down] self.text:', self.text)
        
        focusedid = int(MyTextInput.focused[2])

        if keycode[1] == "backspace":
            if self.text == "":
                if focusedid > 1:
                    self.text = ""
                    focusedid -= 1
                    MyTextInput.focused = "id" + str(focusedid)
            else:
                self.text = self.text[:-1]
                
        if keycode[1] == "right":
            if focusedid < 5:
                focusedid += 1
                MyTextInput.focused = "id" + str(focusedid)
            elif focusedid == 5:
                MyTextInput.focused = "id" + str(1)
                
        elif keycode[1] == "left":
            if focusedid > 1:
                focusedid -= 1
                MyTextInput.focused = "id" + str(focusedid)
            elif int(MyTextInput.focused[2]) == 1:
                MyTextInput.focused = "id" + str(5)
        
        elif keycode[1] in letters:
            if focusedid <= 5:
                self.text = text.upper()
                if focusedid < 5 :               
                    focusedid += 1
                    MyTextInput.focused = "id" + str(focusedid)
            
        self.change_focus()
        print("[keyboard_on_key_down] after changing focus:", MyTextInput.focused)
        return True
        
class MainScreen(Widget):
    pass        
         
class TestingappApp(App):
    def build(self):
        return MainScreen()
    
TestingappApp().run()