python - 有没有办法创建一个气泡弹出窗口,可用于将文本输入到不同的文本输入中?
问题描述
我正在尝试创建一个标准数字键盘,当用户触摸屏幕上的文本输入时会弹出该键盘,以便用户无需使用鼠标和键盘即可输入数字值。我正在关注允许输入到一个文本框中的这个问题,但是当尝试使用它来将值输入到多个文本输入中时,我无法让程序正常运行。我仅限于使用 Python,而不是 Kivy 语言,所以我可以理解编码有点尴尬。
我的计划是为 Bubble (inputBubble)、Bubble Buttons (inputBubbleButtons) 和文本输入框 (text_inputs) 创建一个类,其中 text_inputs 小部件从 RHS()(我的主要布局之一)调用一个应该显示的函数泡泡。我似乎无法从 test.kv 文件中复制 app.root.text_input.text += self.text,所以我当前的错误是“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 上时,我希望这会创建一个气泡,但是我收到错误消息“AttributeError:'text_inputs' 对象没有属性'bubblein'”。
解决方案
这是您的代码的一个版本,我认为它可以满足您的需求:
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()
推荐阅读
- java - Spring JMS 消息侦听器找不到 JNDI 查找
- angular - 我想使用 Angular 实现 datePicker,但日历显示不正确
- javascript - 找不到变量:_objectSpread
- php - 如何打印is_int()的结果
- react-native - react-native-scrollable-tab-view Android 问题 #999
- sharepoint - SharePoint 快速启动未打开
- python - 如何创建或移动 pg_trgm--1.3.sql 到正确的路径以清除此 SIMILARITY 错误?
- flutter - 如何通过更改对象状态来触发动作?
- python - 如何使用 PyQT5 附加和分离外部应用程序或停靠外部应用程序?
- javascript - 从 API 写入数据时,使用 SQLite3 处理并发的正确方法是什么?