Структура вызова всплывающего окна Kivy и привязки не имеют смысла - PullRequest
0 голосов
/ 26 августа 2018

Ниже приведен пример рабочего кода программы, которая предоставляет пользователю всплывающие меню для ввода информации.

Проблема заключается в правильной работе привязок увольнения. Программа в данный момент:

  • объявить контент с обратным вызовом
  • Загрузка содержимого во всплывающий объект
  • вызвать всплывающее окно
  • __init__ вызывается и устанавливает что-то вроде _keyboard привязки
  • Пользователь вводит данные и нажимает клавишу подтверждения
  • Вызван обратный вызов, всплывающее окно больше не требуется, поэтому мы вызываем popup.dismiss()
  • всплывающее окно закрывается и оно

Проблема в том, что если я сделаю _keyboard привязку в __init__, то, когда всплывающее окно закроется, я ДОЛЖЕН вызвать метод unbind, иначе ввод с клавиатуры все еще вызывает старые функции всплывающих окон!

Еще одна вещь, которая мне не нравится, это обратный вызов, который нужно вызвать self._popup.dismiss(). Я думаю, что будет намного чище, если всплывающее окно будет полностью автономным и полностью повторно используемым. Это всплывающее окно ввода с цифровой клавиатуры, оно должно связывать клавиатуру и отсоединять ее самостоятельно. Обратный вызов получает моментальный снимок экземпляра всплывающего окна, поэтому легко получить доступ к возвращаемым данным. Само всплывающее окно должно закрывать само собой, поскольку оно точно знает, что конечной целью была returnCB().

Хотя я понятия не имею, как это реализовать. Связывание on_dismiss внутри __init__ ничего не делает, так как TouchGoToInput_dismiss никогда не вызывается. Я также не могу понять, как заставить TouchGoToInput закрыться.

Другая проблема заключается в том, что при нажатии ESC всплывающее окно закрывается и снова переплетается привязка клавиатуры.

Может кто-нибудь помочь мне разобраться в структуре дел вызова?

from kivy.app import App
from kivy.lang import Builder
from kivy.factory import Factory
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.core.window import Window
from kivy.uix.popup import Popup


Builder.load_string('''
<TouchGoToInput>:
    textInput:textInput
    cols: 1
    size: root.size
    pos: root.pos
    GridLayout:
        cols: 1
        size_hint_y:.25
        TextInput:
            size_hint_x:1.0
            font_size: self.height - 15
            padding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
            id:textInput
            disabled: True
    GridLayout:
        cols: 3
        Button:
            text: "1"
            on_release: root.addText("1")
        Button:
            text: "2"
            on_release: root.addText("2")
        Button:
            text: "3"
            on_release: root.addText("3")
        Button:
            text: "4"
            on_release: root.addText("4")
        Button:
            text: "5"
            on_release: root.addText("5")
        Button:
            text: "6"
            on_release: root.addText("6")
        Button:
            text: "7"
            on_release: root.addText("7")
        Button:
            text: "8"
            on_release: root.addText("8")
        Button:
            text: "9"
            on_release: root.addText("9")
        Button:
            text: "."
            on_release: root.addText(".")
        Button:
            text: "0"
            on_release: root.addText("0")
        Button:
            text: "Done"
            on_release: root.accept()
''')


class TouchGoToInput(GridLayout):

    returnCB = ObjectProperty(None)

    def __init__(self, **kwargs):
        super(TouchGoToInput, self).__init__(**kwargs)
        self.bind(on_dismiss=self.dismiss)
        print('TouchGoToInput.__init__')

    def dismiss(self):
        print('TouchGoToInput_dismiss')

    def addText(self, text):
        self.textInput.text = self.textInput.text + text

    def accept(self):
        print('TouchGoToInput.accept')
        self.returnCB(self)

    def __del__(self):
        print('TouchGoToInput.__del__')
        self.returnCB(self)


class TestApp(App):
    def build(self):
        self.popupContent = TouchGoToInput(returnCB=self.gotoLinePopup)
        self._popup = Popup(title="GoTo...", content=self.popupContent,
                            size_hint=(0.9, 0.9))
        #self._popup.bind(on_dismiss=self.main_dismiss)
        return Factory.Button(text="press me", on_press=self._popup.open)

    def gotoLinePopup(self, instance):
        print('returnCB.text: ', instance.textInput.text)
        self._popup.dismiss()

    def main_dismiss(self, instance):
        print('main_dismiss')

TestApp().run()

1 Ответ

0 голосов
/ 26 августа 2018

В этом примере демонстрируется реализация numpad с использованием всплывающего виджета с привязкой клавиатуры. Он принимает ввод от кнопок, клавиатуры и NumPad.

Всплывающее окно »Отклонить

По умолчанию любой щелчок вне всплывающего окна будет отклонять / закрывать его. если ты если вы этого не хотите, вы можете установить auto_dismiss в False:

Всплывающее окно »auto_dismiss

auto_dismiss

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

auto_dismiss является логическим свойством и по умолчанию имеет значение True.

* * Пример тысяча двадцать-одина * * тысяча двадцать-дв

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.gridlayout import GridLayout
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.core.window import Window


Builder.load_string('''
#:kivy 1.11.0

<NumPad>:
    title: "GoTo..."
    size_hint: (0.9, 0.9)
    auto_dismiss: False

<TouchGoToInput>:
    textInput: textInput
    cols: 1
    size: root.size
    pos: root.pos

    GridLayout:
        cols: 1
        size_hint_y: .25

        TextInput:
            size_hint_x:1.0
            font_size: self.height - 15
            padding_y: [self.height / 2.0 - (self.line_height / 2.0) * len(self._lines), 0]
            id: textInput
            disabled: True

    GridLayout:
        cols: 3
        Button:
            text: "1"
            on_release: root.addText(self.text)
        Button:
            text: "2"
            on_release: root.addText(self.text)
        Button:
            text: "3"
            on_release: root.addText(self.text)
        Button:
            text: "4"
            on_release: root.addText(self.text)
        Button:
            text: "5"
            on_release: root.addText(self.text)
        Button:
            text: "6"
            on_release: root.addText(self.text)
        Button:
            text: "7"
            on_release: root.addText(self.text)
        Button:
            text: "8"
            on_release: root.addText(self.text)
        Button:
            text: "9"
            on_release: root.addText(self.text)
        Button:
            text: "."
            on_release: root.addText(self.text)
        Button:
            text: "0"
            on_release: root.addText(self.text)
        Button:
            text: "Done"
            on_release: 
                app._popup.dismiss()
''')


class TouchGoToInput(GridLayout):

    def addText(self, text):
        self.textInput.text = self.textInput.text + text


class NumPad(Popup):

    def __init__(self, **kwargs):
        super(NumPad, self).__init__(**kwargs)
        self.popupContent = TouchGoToInput()
        self.content = self.popupContent

    def on_open(self):
        # erase previous textInput
        self.popupContent.textInput.text = ''

        # keyboard binding
        self._keyboard = Window.request_keyboard(
            self._keyboard_closed, self, 'text')

        if self._keyboard.widget:
            # If it exists, this widget is a VKeyboard object which you can use
            # to change the keyboard layout.
            pass

        self._keyboard.bind(on_key_down=self._on_keyboard_down)

    def _keyboard_closed(self):
        # keyboard have been closed!
        if self._keyboard is not None:
            self._keyboard.unbind(on_key_down=self._on_keyboard_down)
            self._keyboard = None

    def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
        # check for 0...9, or '.' pressed from keyboard
        if (keycode[0] in list(range(48, 58))) or (keycode[0] == 46):
            # keyboard: 0 / 48 to 9 / 57, or decimal / 46
            self.popupContent.addText(text)

        # check for 0...9, or '.' pressed from numpad
        elif (keycode[0] in list(range(256, 267))):
            # numpad0 / 256 to numpad9 / 265, or numpaddecimal / 266
            if keycode[0] == 266:
                self.popupContent.addText('.')
            else:
                self.popupContent.addText(keycode[1][-1:])

        # Keycode is composed of an integer + a string
        # If we hit escape, release the keyboard
        if keycode[1] == 'escape':
            keyboard.release()

        # Return True to accept the key. Otherwise, it will be used by
        # the system.
        return True

    def on_dismiss(self):
        print('\tNumPad.on_dismiss: self.popupContent.textInput.text=', self.popupContent.textInput.text)
        self._keyboard_closed()


class TestApp(App):

    def build(self):
        self._popup = NumPad()
        return Button(text="press me", on_press=self._popup.open)


if __name__ == "__main__":
    TestApp().run()

выход

Img01 - Numbers and decimal point from Keyboard, NumPad, and Buttons Img02 - Button Done clicked

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...