python 有没有办法让一个TextInput框自动搜索一个地址列表?

i2loujxw  于 2023-08-02  发布在  Python
关注(0)|答案(3)|浏览(80)

我希望用户能够开始在一个TextInput框中键入地址,当他们开始键入它是通过列表搜索和brining匹配的选项。这是在kivy可以做到的吗?
我可以找到一个例子,如果它不够清楚,但他们到处都可以看到在大多数网站上,你必须填写一个地址(例如送货地址)

ttvkxqim

ttvkxqim1#

下面是使用Spinner的另一种方法的开始:

from kivy.app import App
from kivy.properties import StringProperty, ListProperty
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.spinner import Spinner

class AddressChooser(FocusBehavior, Spinner):
    addressfile = StringProperty()
    addresslist = ListProperty([])

    def __init__(self, **kwargs):
        self.addressfile = kwargs.pop('addressfile', '')
        self.sync_height = True
        super(AddressChooser, self).__init__(**kwargs)
        self.modifiers = []
        self.bind(addressfile=self.load_addresses)
        self.load_addresses()

    def on_parent(self, widget, parent):
        self.focus = True

    def load_addresses(self):
        if self.addressfile:
            with open(self.addressfile) as fd:
                for line in fd:
                    self.addresslist.append(line)
        else:
            self.addresslist = []
        self.values = []
        if len(self.text) > 0:
            self.on_text(self, self.text)

    def on_text(self, chooser, text):
        values = []
        for addr in self.addresslist:
            if addr.startswith(text):
                values.append(addr)
        self.values = values
        self.is_open = True

    def keyboard_on_key_up(self, window, keycode):
        if keycode[0] == 304:
            self.modifiers.remove('shift')
        super(AddressChooser, self).keyboard_on_key_up(window, keycode)

    def keyboard_on_key_down(self, window, keycode, text, modifiers):
        if keycode[0] == 304:   # shift
            self.modifiers.append('shift')
        elif keycode[0] == 8 and len(self.text) > 0:   # backspace
            self.text = self.text[:-1]
        else:
            if 'shift' in self.modifiers:
                self.text += text.upper()
            else:
                self.text += text
        super(AddressChooser, self).keyboard_on_key_down(window, keycode, text, modifiers)

class TestApp(App):
    def build(self):
        layout = RelativeLayout()
        chooser = AddressChooser(addressfile='adresses.txt', size_hint=(0.5,None), height=50, pos_hint={'center_x':0.5, 'center_y':0.5})
        layout.add_widget(chooser)
        return layout

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

字符串

tzdcorbm

tzdcorbm2#

下面是另一种使用TextInputDropDown的方法:

# -*- encoding: utf-8 -*-
"""
Chooser
=======

Uses TextInput with a DropDown to choose from a list of choices

The 'choicesfile' attribute can be used to specify a file of possible choices (one per line)
The 'choiceslist' attribute can be used to provide a list of choices

When typing in the TextInput, a DropDown will show the possible choices
and a suggestion will be shown in the TextInput for the first choice.
Hitting enter will select the suggested choice.

"""

from kivy.properties import ListProperty, StringProperty
from kivy.uix.button import Button
from kivy.uix.dropdown import DropDown
from kivy.uix.textinput import TextInput

class Chooser(TextInput):
    choicesfile = StringProperty()
    choiceslist = ListProperty([])

    def __init__(self, **kwargs):
        self.choicesfile = kwargs.pop('choicesfile', '')  # each line of file is one possible choice
        self.choiceslist = kwargs.pop('choiceslist', [])  # list of choices
        super(Chooser, self).__init__(**kwargs)
        self.multiline = False
        self.halign = 'left'
        self.bind(choicesfile=self.load_choices)
        self.bind(text=self.on_text)
        self.load_choices()
        self.dropdown = None

    def open_dropdown(self, *args):
        if self.dropdown:
            self.dropdown.open(self)

    def load_choices(self):
        if self.choicesfile:
            with open(self.choicesfile) as fd:
                for line in fd:
                    self.choiceslist.append(line.strip('\n'))
        self.values = []

    def keyboard_on_key_down(self, window, keycode, text, modifiers):
        if self.suggestion_text and keycode[0] == ord('\r'):  # enter selects current suggestion
            self.suggestion_text = ' '  # setting suggestion_text to '' screws everything
            self.text = self.values[0]
            if self.dropdown:
                self.dropdown.dismiss()
                self.dropdown = None
        else:
            super(Chooser, self).keyboard_on_key_down(window, keycode, text, modifiers)

    def on_text(self, chooser, text):
        if self.dropdown:
            self.dropdown.dismiss()
            self.dropdown = None
        if text == '':
            return
        values = []
        for addr in self.choiceslist:
            if addr.startswith(text):
                values.append(addr)
        self.values = values
        if len(values) > 0:
            if len(self.text) < len(self.values[0]):
                self.suggestion_text = self.values[0][len(self.text):]
            else:
                self.suggestion_text = ' '  # setting suggestion_text to '' screws everything
            self.dropdown = DropDown()
            for val in self.values:
                self.dropdown.add_widget(Button(text=val, size_hint_y=None, height=48, on_release=self.do_choose))
            self.dropdown.open(self)

    def do_choose(self, butt):
        self.text = butt.text
        if self.dropdown:
            self.dropdown.dismiss()
            self.dropdown = None

if __name__ == '__main__':
    from kivy.app import App
    from kivy.uix.relativelayout import RelativeLayout

    class TestApp(App):
        def build(self):
            layout = RelativeLayout()
            choices = ['Abba', 'dabba', 'doo']
            chooser = Chooser(choiceslist=choices, hint_text='Enter one of Fred\'s words', size_hint=(0.5,None), height=30, pos_hint={'center_x':0.5, 'center_y':0.5})
            layout.add_widget(chooser)
            return layout

    TestApp().run()

字符串

brgchamk

brgchamk3#

import re

from kivy.clock import Clock
from kivy.factory import Factory
from kivy.properties import ListProperty, StringProperty, ObjectProperty
from kivy.lang import Builder

Builder.load_string('''
<DDNButton@Button>
    size_hint_y: None
    height: dp(45)
''')

class ComboBox(Factory.TextInput):

    options = ListProperty(('', ))
    _options = ListProperty(('', ))
    option_cls = ObjectProperty(Factory.DDNButton)

    select = StringProperty('')

    def __init__(self, **kw):
        ddn = self.drop_down = Factory.DropDown()
        ddn.bind(on_select=self.set_select)
        super().__init__(**kw)
        self.trigger_dropdown = Clock.create_trigger(self.drop_down_triggered, 1/2)
        self.write_tab = False
        self.multiline = False

    def on_text_validate(self):
        if not self._options:
            return

        # print(self.text, self._options[-1])
        if not self.text in self._options[-1]:
            return

        self.set_select(self, self._options[-1])

    def on_options(self, instance, value):
        self._options = value

    def on__options(self, instance, value):
        ddn = self.drop_down
        ddn.clear_widgets()
        for option in value:
            widg = self.option_cls(text=option)
            widg.bind(on_release=lambda btn: ddn.select(btn.text))
            ddn.add_widget(widg)

    def set_select(self, *args):
        # print('on_select', args)
        if self.text != args[1]:
            self.select = args[1]
            self.text = args[1]
            self.drop_down.dismiss()

    def on_text(self, instance, value):
        self.trigger_dropdown()

    def drop_down_triggered(self, dt):
        value = self.text
        instance = self
        # print(f'on_text {instance} "{value}"')
        if value == '':
            instance._options = self.options
            return
        else:
            # print(f'on_text {instance} "{value}" on_else')
            if value in self.options:
                self.drop_down.pos = 0, -1000
                return

            r = re.compile(f".*{value}", re.IGNORECASE)
            match = filter(r.match, instance.options)
            #using a set to remove duplicates, if any.
            instance._options = list(set(match))
            # print(instance._options)

            instance.drop_down.dismiss()
            # print(instance.parent, instance.pos)
            Clock.schedule_once(lambda dt: instance.drop_down.open(instance), .1)

    def on_touch_up(self, touch):
        # print('focus', value, self.text)
        if touch.grab_current == self:
            self.text = ''
            self.drop_down.open(self)
        # else:
        #     self.drop_down.dismiss()

if __name__ == '__main__':
    from kivy.app import App
    class MyApp(App):
        def build(self):
            return Builder.load_string('''
FloatLayout:
    BoxLayout:
        size_hint: .5, None
        pos: 0, root.top - self.height
        ComboBox:
            options: ['Hello', 'World']
        ComboBox:
            options: ['Hello', 'World']
        Button

''')
    MyApp().run()

字符串
试试这个

相关问题