Есть ли способ создать всплывающее окно, которое можно использовать для ввода текста в различные текстовые вводы? - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь создать стандартную цифровую клавиатуру, которая будет всплывать, когда пользователь касается ввода текста на экране, чтобы пользователь мог вводить числовые значения без использования мыши и клавиатуры. Я следил за этим вопросом, который допускает ввод в одно текстовое поле, но при попытке использовать его для ввода значений в несколько текстовых вводов я не мог заставить программу работать правильно. Я ограничен только использованием Python, а не языка Kivy, поэтому я могу оценить, что он немного более неудобен для кода.

Я планировал создать класс для Bubble (inputBubble), Bubble Buttons (inputBubbleButtons) и поля ввода текста (text_inputs), с виджетом text_inputs, вызывающим функцию из RHS () (одна из моих основных схем), которая должна отображать пузырь. Я не могу представить способ репликации app.root.text_input.text + = self.text из файла test.kv, поэтому моя текущая ошибка: «У объекта text_inputs нет атрибута bubblein», и я не могу думатьспособа пройти мимо этого.

import kivy
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.uix.bubble import Bubble, BubbleButton

class inputBubble(Bubble):
        def __init__(self, **kwargs):
                super(inputBubble, self).__init__(**kwargs)
                inputGrid = GridLayout(cols = 3)
                keypad_numbers = ['7', '8', '9', '4', '5', '6', '1', '2', '3', 'CLR', '0', '.']
                for x in keypad_numbers:
                        inputGrid.add_widget = inputBubbleButtons(text = x)
                self.add_widget(inputGrid)

class inputBubbleButtons(BubbleButton):
        def __init__(self, **kwargs):
                super(inputBubbleButtons, self).__init__(**kwargs)
                self.on_release = self.buttonfunctions

        def buttonfunctions(self):
                if self.text != 'CLR':
                        text_input.text += self.text
                else:
                        text_input.text = '0'

class text_inputs(TextInput):
        def __init__(self, **kwargs):
                super(text_inputs, self).__init__(**kwargs)
                self.id = 'text_input'
                self.cursor_blink = False
                self.multiline = False
                self.on_focus = RHS.show_input(self)

class RHS(BoxLayout):
        def __init__(self, **kwargs):
                super(RHS, self).__init__(**kwargs)
                nangleRow = BoxLayout(orientation = 'horizontal')
                self.add_widget(nangleRow)
                nangleRow.add_widget(Label(text = 'New Angle'))
                nangleInput = text_inputs()
                nangleRow.add_widget(nangleInput)

        def show_input(self, *l):
                if not hasattr(self, 'bubblein'):
                        bubblein = inputBubble()
                        self.bubblein.arrow_pos = "bottom_mid"
                        self.add_widget(bubblein)

class Root(GridLayout):
        def __init__(self, **kwargs):
                super(Root, self).__init__(**kwargs)
                self.cols = 1
                self.add_widget(RHS(),0)

class MainWindow(App):
        def build(self):
                return Root()

if __name__ == '__main__':
        MainWindow().run()

Я ожидаю, что это создаст пузырь, когда фокус находится на nangleInput, но вместо этого я получаю сообщение об ошибке«».

1 Ответ

1 голос
/ 06 ноября 2019

Вот версия вашего кода, которая, я думаю, делает то, что вы хотите:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.bubble import Bubble, BubbleButton

class inputBubble(Bubble):
        def __init__(self, **kwargs):
                super(inputBubble, self).__init__(**kwargs)
                inputGrid = GridLayout(cols = 3)
                keypad_numbers = ['7', '8', '9', '4', '5', '6', '1', '2', '3', 'CLR', '0', '.']
                for x in keypad_numbers:
                        inputGrid.add_widget(inputBubbleButtons(text = x))    # use add_widget to add each Button to the inputGrid
                self.add_widget(inputGrid)

class inputBubbleButtons(BubbleButton):
        def __init__(self, **kwargs):
                super(inputBubbleButtons, self).__init__(**kwargs)
                self.on_release = self.buttonfunctions

        def buttonfunctions(self):
                if self.text != 'CLR':
                        # complex path to the TextInput
                        App.get_running_app().root.RHS.nangleInput.text += self.text
                else:
                        App.get_running_app().root.RHS.nangleInput.text = '0'

class text_inputs(TextInput):
        def __init__(self, **kwargs):
                super(text_inputs, self).__init__(**kwargs)
                self.id = 'text_input'
                self.cursor_blink = False
                self.multiline = False

class RHS(BoxLayout):
        def __init__(self, **kwargs):
                super(RHS, self).__init__(**kwargs)
                nangleRow = BoxLayout(orientation = 'horizontal')
                self.add_widget(nangleRow)
                nangleRow.add_widget(Label(text = 'New Angle'))
                self.nangleInput = text_inputs()    # save a reference to text_inputs
                self.nangleInput.bind(focus=self.show_input)    # use bind to get method called when focus changes
                nangleRow.add_widget(self.nangleInput)

        def show_input(self, *l):
                if not hasattr(self, 'bubblein'):
                        self.bubblein = inputBubble()    # create attribute that is tested for in above line
                        self.bubblein.arrow_pos = "bottom_mid"
                        self.add_widget(self.bubblein)

class Root(GridLayout):
        def __init__(self, **kwargs):
                super(Root, self).__init__(**kwargs)
                self.cols = 1
                self.RHS = RHS()    # save  reference to RHS
                self.add_widget(self.RHS,0)

class MainWindow(App):
        def build(self):
                return Root()

if __name__ == '__main__':
        MainWindow().run()

Проблемы включали:

  1. inputGrid.add_widget = inputBubbleButtons(text = x) должно быть inputGrid.add_widget(inputBubbleButtons(text = x)).
  2. В вашем buttonfunctions() вы ссылаетесь на text_input, но это не было определено. Я заменил его довольно сложным путем к фактическому text_inputs.
  3. self.on_focus = RHS.show_input(self), который запускает метод show_input() и присваивает возвращаемое значение (равное None) self.on_focus. Я удалил эту строку и поместил self.nangleInput.bind(focus=self.show_input) в класс RHS, что, по моему мнению, выполняет ваши намерения.
  4. В вашем методе show_inputs() вы проверяете наличие атрибута с именем bubblein,но ваш код не создает его. Я изменил первую строку в этом блоке if на self.bubblein = inputBubble(), что создает этот атрибут. Другие изменения также для доступа к новому атрибуту.
  5. В классе Root я сохранил ссылку на созданный экземпляр RHS для использования в другом месте.

Если вы собираетесьиспользуя несколько экземпляров TextInput, вы можете отрегулировать цель клавиатуры для отправки текста на другой TextInputs. Вот еще одна версия вашего кода, которая делает это:

from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.bubble import Bubble, BubbleButton

class inputBubble(Bubble):
        def __init__(self, text_input, **kwargs):
                super(inputBubble, self).__init__(**kwargs)
                self.inputGrid = GridLayout(cols = 3)    # save a reference to the grid of inputBubbleButtons
                keypad_numbers = ['7', '8', '9', '4', '5', '6', '1', '2', '3', 'CLR', '0', '.']
                for x in keypad_numbers:
                        self.inputGrid.add_widget(inputBubbleButtons(text_input, text = x))    # use add_widget to add each Button to the inputGrid
                self.add_widget(self.inputGrid)

        # this method changes the target TextInput of the keypad
        def set_text_input(self, text_input):
                for butt in self.inputGrid.children:
                        butt.text_input = text_input

class inputBubbleButtons(BubbleButton):
        def __init__(self, text_input, **kwargs):
                self.text_input = text_input    # the target TextInput
                super(inputBubbleButtons, self).__init__(**kwargs)
                self.on_release = self.buttonfunctions

        def buttonfunctions(self):
                if self.text != 'CLR':
                        self.text_input.text += self.text
                else:
                        self.text_input.text = '0'

class text_inputs(TextInput):
        def __init__(self, **kwargs):
                super(text_inputs, self).__init__(**kwargs)
                self.id = 'text_input'
                self.cursor_blink = False
                self.multiline = False

class RHS(BoxLayout):
        def __init__(self, **kwargs):
                super(RHS, self).__init__(**kwargs)
                self.orientation = 'vertical'
                self.bubblein = None
                for i in range(5):
                        nangleRow = BoxLayout(orientation = 'horizontal')
                        self.add_widget(nangleRow)
                        nangleRow.add_widget(Label(text = 'New Angle ' + str(i)))
                        self.nangleInput = text_inputs()    # save a reference to text_inputs
                        self.nangleInput.bind(focus=self.show_input)    # use bind to get method called when focus changes
                        nangleRow.add_widget(self.nangleInput)

        def show_input(self, text_input, has_focus):
                if has_focus:
                        if self.bubblein is not None:
                                # already have a keypad, just change the target TextInput to receive the key strokes
                                self.bubblein.set_text_input(text_input)
                        else:
                                self.bubblein = inputBubble(text_input)
                                self.bubblein.arrow_pos = "bottom_mid"
                                self.add_widget(self.bubblein)

class Root(GridLayout):
        def __init__(self, **kwargs):
                super(Root, self).__init__(**kwargs)
                self.cols = 1
                self.RHS = RHS()    # save  reference to RHS
                self.add_widget(self.RHS,0)

class MainWindow(App):
        def build(self):
                return Root()

if __name__ == '__main__':
        MainWindow().run()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...