![](/img/trans.png)
[英]In kivy, How can I control the height of the VKeyboard used by TextInput
[英]how can i create a autocomplete textinput in kivy
这是 my.py 文件我需要创建一个自动完成文本输入我已经创建了 textinput 和 RV class 子类 recycleview 和 dropdown 但问题是它没有下降它下降到并且当它下降时文本输入被最小化这是python 文件
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.recycleview import RecycleView
from kivy.uix.dropdown import DropDown
from kivy.uix.scrollview import ScrollView
from kivy.lang import Builder
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.recycleboxlayout import RecycleBoxLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
from kivy.properties import NumericProperty,ListProperty, BooleanProperty, ObjectProperty
from kivy.uix.textinput import TextInput
import sqlite3
from kivy.uix.button import Button
from collections import OrderedDict
class SelectableRecycleBoxLayout(FocusBehavior, LayoutSelectionBehavior,
RecycleBoxLayout):
''' Adds selection and focus behaviour to the view. '''
class SelectableLabel(RecycleDataViewBehavior, Label):
''' Add selection support to the Label '''
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(True)
def refresh_view_attrs(self, rv, index, data):
''' Catch and handle the view changes '''
self.index = index
return super(SelectableLabel, self).refresh_view_attrs(
rv, index, data)
def on_touch_down(self, touch):
''' Add selection on touch down '''
if super(SelectableLabel, self).on_touch_down(touch):
return True
if self.collide_point(*touch.pos) and self.selectable:
return self.parent.select_with_touch(self.index, touch)
def apply_selection(self, rv, index, is_selected):
''' Respond to the selection of items in the view. '''
self.selected = is_selected
class ListcreationWindow(BoxLayout):
code_inp = ObjectProperty()
flt_list = ObjectProperty()
word_list = ListProperty()
def __init__(self, **kwargs):
super(ListcreationWindow, self).__init__(**kwargs)
self.cart = []
self.qty = []
self.total = 0.00
class MyLayout(BoxLayout):
code_inp = ObjectProperty()
rv = ObjectProperty()
def __init__(self, **kwargs):
super(MyLayout, self).__init__(**kwargs)
class MyTextInput(TextInput):
code_inp = ObjectProperty()
flt_list = ObjectProperty()
word_list = ListProperty()
# this is the variable storing the number to which the look-up will start
starting_no = NumericProperty(3)
suggestion_text = ''
def __init__(self, **kwargs):
super(MyTextInput, self).__init__(**kwargs)
def on_text(self, instance, value):
# find all the occurrence of the word
matches = [self.word_list[i] for i in range(len(self.word_list)) if
self.word_list[i][:self.starting_no] == value[:self.starting_no]]
display_data = []
for i in matches:
display_data.append({'text': i})
#ensure the size is okay
if len(matches) <= 10:
self.parent.height = (50 + (len(matches) * 20))
else:
self.parent.height = 240
def keyboard_on_key_down(self, window, keycode, text, modifiers):
if self.suggestion_text and keycode[1] == 'tab':
self.insert_text(self.suggestion_text + ' ')
return True
return super(MyTextInput, self).keyboard_on_key_down(window, keycode, text, modifiers)
class RV(DropDown):
def __init__(self, **kwargs):
super(RV, self).__init__(**kwargs)
notes = ['Features', 'Suggestions', 'Abreviations', 'Miscellaneous']
for note in notes:
btn = Button(text='%r' % note, size_hint_y=None, height=30)
btn.bind(on_release=lambda btn: self.select(btn.text))
self.add_widget(btn)
mainbutton = MyTextInput()
mainbutton.bind(on_text=self.open)
self.bind(on_select=lambda instance, x: setattr(mainbutton, 'text', x))
class ListcreationApp(App):
def build(self):
return ListcreationWindow()
if __name__=='__main__':
ListcreationApp().run()
这是 my.kv 文件,用于创建在此处创建 RV 小部件的 ui
<SelectableLabel>:
# Draw a background to indicate selection
color: 0,0,0,1
canvas.before:
Color:
rgba: (0, 0, 1, 5) if self.selected else (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
<MyTextInput>:
readonly: False
multiline: False
<RV>:
bar_width: 1
bar_color: 1, 0, 0, 1 # red
bar_inactive_color: 0, 0, 1, 1 # blue
viewclass: 'SelectableLabel'
SelectableRecycleBoxLayout:
default_size: dp(50), dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: False
touch_multiselect: True
<FlatButton@ButtonBehavior+Label>:
font_size: 14
<ListcreationWindow>:
id:main_win
orientation:'vertical'
pos: self.pos
size: self.size
canvas.before:
Color:
rgba:(1,1,1,1)
Rectangle:
size:self.size
pos:self.pos
BoxLayout:
id:header
size_hint_y:None
canvas.before:
Color:
rgba:(.06, .45, .45, 1)
Rectangle:
size:self.size
pos:self.pos
Label:
text: "Nadeem POS system"
size_hint_x: .9
bold: True
color:(1,1,1,1)
FlatButton:
id:loggedin_user
text:'nadeem'
color:(1,1,1,1)
BoxLayout:
id:current
size_hint_y:None
height:50
canvas.before:
Color:
rgba:(.06, .45, .45, 1)
Rectangle:
size:self.size
pos:self.pos
Button:
text:'Current Item'
background_normal:''
background_color:(.06, .32 , .32, 1)
size_hint_x: .4
Button:
id:cur_product
text:'Default Product'
background_normal:''
background_color:(.06, .4 , .4, 1)
Button:
id:cur_price
text:'0.00'
background_normal:''
background_color:(.06, .65 , .65, 1)
size_hint_x: .2
BoxLayout:
padding:10
BoxLayout:
id: product_details
orientation: "vertical"
size_hint_x: .8
spacing:10
BoxLayout:
id:product_labels
size_hint_y:None
height:40
canvas.before:
Color:
rgba:(.06,.45,.45, 1)
Rectangle:
size:self.size
pos:self.pos
FlatButton:
text:'Qty'
size_hint_x: .1
FlatButton:
text:'Product Code'
size_hint_x: .3
FlatButton:
text:'Product Name'
size_hint_x: .2
FlatButton:
text:'Price'
size_hint_x: .1
BoxLayout:
id:product_inputs
size_hint_y:None
height: 30
spacing:5
TextInput:
id:qty_inp
size_hint_x:.1
MyLayout:
orientation: 'vertical'
spacing: 2
code_inp: code_inp
MyTextInput:
id: code_inp
size_hint_x:1
multiline:False
size_hint_y:1
on_text_validate:root.update_purchases()
RV:
id:rv
size_hint_x:1
TextInput:
id:disc_inp
size_hint_x:.2
TextInput:
id:price_inp
size_hint_x:.1
BoxLayout:
id:add_to_cart
orientation:"vertical"
BoxLayout:
size_hint_y:None
height:30
canvas.before:
Color:
rgba:(.06,.45,.45,1)
Rectangle:
size:self.size
pos:self.pos
Label:
text:'Code'
size_hint_x:.2
Label:
text:'Product name'
size_hint_x:.3
Label:
text:'Qty'
size_hint_x:.1
Label:
text:'Price'
size_hint_x:.1
GridLayout:
id: products
cols: 1
BoxLayout:
id:preview
orientation:'vertical'
size_hint_x:.2
TextInput:
id:receipt_preview
readonly:True
text:"\t\t\t\tThe Collector\n\t\t\t\t123 Main St\n\t\t\t\tKnowhere, Space\n \n\t\t\t\tTel:(555)-123-456\n\t\t\t\tReceipt No:\n\t\t\t\t Gate:\n\n"
Button:
id:button_pro
text:'Process'
size:75,40
size_hint: None,None
BoxLayout:
id:footer
size_hint_y:None
height:30
canvas.before:
Color:
rgba:(.06,.47,.47,1)
Rectangle:
pos:self.pos
size:self.size
Label:
text:'maintained by nadeem'
这是DropDown
的破解版本,可让您指定是否希望DropDown
始终位于它所附加的Widget
下方。
class CustomDropDown(DropDown):
force_below = BooleanProperty(False) # if True, DropDown will be positioned below attached to Widget
def __init__(self, **kwargs):
super(CustomDropDown, self).__init__(**kwargs)
self.do_not_reposition = False # flag used to avoid repositioning recursion
def _reposition(self, *largs):
if self.do_not_reposition:
return
super(CustomDropDown, self)._reposition(*largs)
if self.force_below:
self.make_drop_below()
def make_drop_below(self):
self.do_not_reposition = True # avoids recursion triggered by the changes below
if self.attach_to is not None:
wx, wy = self.to_window(*self.attach_to.pos)
self.height = wy # height of DropDown will fill window below attached to Widget
self.top = wy # top of DropDown will be at bottom of attached to Widget
self.do_not_reposition = False # now turn auto repositioning back on
要使用它,您只需调用CustomDropDown(force_below=True)
。 当然,如果Window
底部的Widget
下面的空间太小,这个就不能用了。 更通用的方法将允许指定低于、高于或正常的定位选择。
这可以在您的MyTextInput
class 中使用:
class MyTextInput(TextInput):
code_inp = ObjectProperty()
flt_list = ObjectProperty()
word_list = ListProperty()
# this is the variable storing the number to which the look-up will start
starting_no = NumericProperty(3)
suggestion_text = ''
def __init__(self, **kwargs):
super(MyTextInput, self).__init__(**kwargs)
self.dropdown = CustomDropDown(force_below=True)
notes = ['Features', 'Suggestions', 'Abreviations', 'Miscellaneous']
for note in notes:
# when adding widgets, we need to specify the height manually (disabling
# the size_hint_y) so the dropdown can calculate the area it needs.
btn = Button(text='%r' % note, size_hint_y=None, height=30)
# for each button, attach a callback that will call the select() method
# on the dropdown. We'll pass the text of the button as the data of the
# selection.
btn.bind(on_release=lambda btn: self.dropdown.select(btn.text))
# then add the button inside the dropdown
self.dropdown.add_widget(btn)
# one last thing, listen for the selection in the dropdown list and
# assign the data to the button text.
self.dropdown.bind(on_select=lambda instance, x: setattr(self, 'text', x))
def on_text(self, instance, value):
# only open DropDown if it is not already open and this TextInput is displayed
if self.dropdown.parent is None and self.get_parent_window() is not None:
self.dropdown.open(self)
def keyboard_on_key_down(self, window, keycode, text, modifiers):
if self.suggestion_text and keycode[1] == 'tab':
self.insert_text(self.suggestion_text + ' ')
return True
return super(MyTextInput, self).keyboard_on_key_down(window, keycode, text, modifiers)
还需要在operator.kv
中注释掉RV
:
MyLayout:
orientation: 'vertical'
spacing: 2
code_inp: code_inp
MyTextInput:
id: code_inp
size_hint_x:1
multiline:False
size_hint_y:1
on_text_validate:root.update_purchases()
# RV:
# id:rv
# size_hint_x:1
这基本上只是一个概念证明。 显然,需要更多的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.