Вот версия вашего кода, которая, я думаю, делает то, что вы хотите:
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()
Проблемы включали:
inputGrid.add_widget = inputBubbleButtons(text = x)
должно быть inputGrid.add_widget(inputBubbleButtons(text = x))
. - В вашем
buttonfunctions()
вы ссылаетесь на text_input
, но это не было определено. Я заменил его довольно сложным путем к фактическому text_inputs
. self.on_focus = RHS.show_input(self)
, который запускает метод show_input()
и присваивает возвращаемое значение (равное None
) self.on_focus
. Я удалил эту строку и поместил self.nangleInput.bind(focus=self.show_input)
в класс RHS
, что, по моему мнению, выполняет ваши намерения. - В вашем методе
show_inputs()
вы проверяете наличие атрибута с именем bubblein
,но ваш код не создает его. Я изменил первую строку в этом блоке if
на self.bubblein = inputBubble()
, что создает этот атрибут. Другие изменения также для доступа к новому атрибуту. - В классе
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()