2

私がやろうとしていることの概要です。以下に示すように、FloaLayout ウィジェットに 2 つの TextInput ウィジェットがあり、すべて .kv ファイルで定義されています。(kivy フォーラムでこの質問をしましたが、提供された解決策がうまくいかなかったので、新しいアイデアを得るためにここで質問しています)

test.kv

<TESTGUI>:
    t2: TI2
    t4: TI4
    fl1: FL1

FloatLayout:
    orientation: 'lr-bt'
    id: FL1
    size: root.size
    TextInput:
        id: TI2
        size_hint: 1, 0.1  
        pos_hint: {'top': 1}
        font_size: 35
        on_text: root.realTimeSearch(TI2, TI2.text)
    TextInput:
        id: TI4
        size_hint: 1, 0.1
        pos_hint: {'top': 0.86}
        font_size: 15

ここで、TextInput ウィジェット (t2) の 1 つに任意のテキストを入力すると、プログラムは文字列内のそのテキストを検索します。この検索は、TextInput ウィジェットのテキストが変更されるたびに実行されます。基本的に、入力を開始するとすぐに、検索が動的に開始されます。検索結果には多くの一致が含まれる可能性があり (これらの一致はすべて、result_list というリストに格納されます (以下のコードを参照))、一致の数に基づいて、結果の数に等しい数のボタンを持つ GridLayout を追加します (つまり、検索からの result_list 内の要素の数)。ボタンをクリックすると、ボタンのテキストが他の TextInput ウィジェット (上記の t4) に転送されます。以下は .py ファイルのコード全体です。プログラムは基本的に、オートコンプリート機能を備えた検索ユーティリティです。私の問題 m 遭遇したのは、clear_widgets が現在のコンテキストでは機能していないように見えることです。そのため、多くのウィジェットが重なり合っており、それぞれをクリックして削除する必要があります (明確な説明については、以下のコードを参照してください)。

マシンでコードを実行して、何が起こっているかを把握することをお勧めします (t2 textinput ウィジェットに「silicon」と入力してみてください。clear_widgets が機能していないことがわかります)。

import re
import sys
import kivy
kivy.require('1.5.1')
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.textinput import TextInput
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.popup import Popup
from kivy.uix.scrollview import ScrollView
from collections import Counter
from functools import partial
reload(sys)
sys.setdefaultencoding('utf-8')

rtsstr =",,,Substrate1,,,Substrate1,,,Substrate1,,,Substrate1,,,Substrate1,,,Substrate_coating,,,silicon,,,silicon_Substrate,,,substrate_silicon,,,"
#rtsstr is the string on which search is being performed


class TESTGUI(Widget):

t2 = ObjectProperty(None)
t4 = ObjectProperty(None)
fl1 = ObjectProperty(None)

def realTimeSearch(self, instance, value):
    """
    this function is used as a real time update of search results based on the search query. It also identifies partial matches (e.g. a search for silicon can result in entries such as silicon, silicon nitride, silicon dioxide etc. being displayed
    """
    if value != '':            
        match = re.findall("(?<=,{3})(?:(?!,{3}).)*?%s.*?(?=,{3})" % value, rtsstr, re.IGNORECASE)
        result_list = list(set(match)) #using a set to remove duplicates, if any.
        self.create_search(result_list)

def create_search(self, result_list):
    layt = GridLayout(cols=3, size_hint_y = None)
    layt.bind(minimum_height=layt.setter('height'))
    scrlv = ScrollView(size_hint=(1, 0.8), pos_hint={'top': 0.8})
    self.fl1.remove_widget(scrlv)

    for result in result_list:
        buttn2 = Button(text = str(result), size_hint = (0.3, None), height = 40)
        buttn2.bind(on_press = partial(self.transferSearchText, buttn2.text, scrlv))
        layt.add_widget(buttn2)
    scrlv.add_widget(layt)
    self.fl1.add_widget(scrlv)   

def transferSearchText(self, text, scrlv, *args):
    self.t4.insert_text(text + ',')
    scrlv.clear_widgets()
    self.fl1.remove_widget(scrlv) 
    self.t2.text = ''                     

class TestApp(App):
    def build(self):
        return TESTGUI()


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

ありがとう!

4

1 に答える 1

3

ScrollView に追加したレイアウトをクリアする必要がある Scrollview をクリアしようとしています。

Widget.Clear_widget() は、現在のウィジェットの子のみをクリアします。これは再帰的ではなく、そのようにすることを意図していません。

Kivy は、従来の編集可能なコンボ ボックスを提供しません。Kivy を使用すると、TextInput と DropDown を組み合わせて独自のウィジェットを非常に簡単に作成できます。

スニペット wikiに示されているように ComboEdit のようなものを使用し、ニーズに合わせて変更する必要があります。

したがって、あなたが達成しようとしていることは次のように行うことができます::

from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
from kivy.properties import ListProperty, StringProperty

import re

from kivy.lang import Builder

Builder.load_string('''
<MainView>:
    ComboEdit:
        size_hint: .5, .3
        pos_hint: {'center':(.5, .5)}
        # `args` is the keyword for arguments passed to `on_text` in kv language
        on_text: root.on_text(self, args[1])
''')

class ComboEdit(TextInput):
    '''
    This class defines a Editable Combo-Box in the traditional sense
    that shows it's options 
    '''

    options = ListProperty(('', ))
    '''
    :data:`options` defines the list of options that will be displayed when
    touch is released from this widget.
    '''

    def __init__(self, **kw):
        ddn = self.drop_down = DropDown()
        ddn.bind(on_select=self.on_select)
        super(ComboEdit, self).__init__(**kw)

    def on_options(self, instance, value):
        ddn = self.drop_down
        # clear old options
        ddn.clear_widgets()
        for option in value:
            # create a button for each option
            but = Button(text=option,
                        size_hint_y=None,
                        height='36sp',
                        # and make sure the press of the button calls select
                        # will results in calling `self.on_select`
                        on_release=lambda btn: ddn.select(btn.text))
            ddn.add_widget(but)

    def on_select(self, instance, value):
        # on selection of Drop down Item... do what you want here
        # update text of selection to the edit box
        self.text = value

class MainView(FloatLayout):

    rtsstr = StringProperty("".join(("Substrate1,,,Substrate1,,,Substrate1,,,",
                            "Substrate1,,,Substrate1,,,Substrate_coating",
                            ",,,silicon,,,silicon_Substrate,,,substrate_",
                            "silicon,,,")))

    def on_text(self, instance, value):
        if value == '':
            instance.options=[]
        else:
            match = re.findall("(?<=,{3})(?:(?!,{3}).)*?%s.*?(?=,{3})" % value,\
                                self.rtsstr, re.IGNORECASE)
            #using a set to remove duplicates, if any.
            instance.options = list(set(match))
        instance.drop_down.open(instance)

class TestApp(App):

    def build(self):
        return MainView()

if __name__ == '__main__':
    TestApp().run()
于 2013-03-04T11:19:43.873 に答える