Kivy Clear_widget奇怪的行为(附带可复制的代码) [英] Kivy Clear_widget strange behaviour (reproducible code attached)

查看:41
本文介绍了Kivy Clear_widget奇怪的行为(附带可复制的代码)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是我要做的事情的摘要.我在FloaLayout小部件中有两个TextInput小部件,都在.kv文件中定义,如下所示. (我在kivy论坛上问了这个问题,但是所提供的解决方案没有奏效,所以我在这里问它以获取一些新想法)

just a rundown of what I'm trying to do. I've got two TextInput widgets in a FloaLayout widget, all defined in a .kv file as shown below. (I asked this question on kivy forums but the solution offered didn't work out so I'm asking it here to get some new ideas)

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)中输入任何文本时,程序将执行的操作是在字符串中搜索该文本.每当TextInput小部件文本更改时,都会执行此搜索.因此,基本上,只要您开始输入,搜索就会动态地开始.搜索结果可以有很多匹配项(所有这些匹配项都存储在一个名为result_list的列表中(请参见下面的代码)),并根据匹配项的数量添加一个GridLayout,其按钮数量等于结果的数量(即搜索中result_list中的元素数).现在,当我单击按钮时,发生的事情是它将按钮文本传输到另一个TextInput小部件(如上图所示的t4).以下是.py文件中的全部代码.该程序基本上是具有自动完成功能的搜索实用程序.我遇到的问题是clear_widgets在当前上下文中似乎不起作用.因此,我彼此之间有许多小部件,并且需要单击它们以摆脱它们(请参阅下面的代码以获取清晰的说明)

Now when I enter any text in one of the TextInput widgets (t2), what the program does is it searches for that text in a string. This search is performed whenever the TextInput widgets text changes. So basically as soon as you start typing the search begins dynamically. The search result can have many matches (all these matches are stored in a list called result_list (see below code)) and based on the number of matches, I add a GridLayout with the number of buttons that equal to the number of results (i.e. number of elements in the result_list) from the search. Now when I click the button, what happens is that it transfers the button text to the other TextInput widget (t4 as shown above). Below is the entire code from the .py file The program basically is a search utility with auto-complete functionality. The problem that I'm encountering is that clear_widgets doesn't seem to work in the current context. So I get many widgets on top of eachother and I need to click through each of them to get rid of them (refer to the code below for a clear explanation)

我建议您在计算机上运行代码以大致了解正在发生的事情(尝试在t2 textinput小部件中输入"silicon",然后您可以看到clear_widgets如何不起作用).

I'd suggest you run the code on your machine to get a good idea of what is happening (try entering 'silicon' in t2 textinput widget and you can see how clear_widgets is not working).

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() 

谢谢!

推荐答案

您正在尝试清除Scrollview,应该在其中清除添加到ScrollView的布局.

You are trying to clear the Scrollview, where you should be clearing the layout you add to the ScrollView.

Widget.Clear_widget()仅清除当前窗口小部件的子级,它不是递归的,并非意味着如此.

Widget.Clear_widget() only clears the current widget's children, it's not recursive and is not meant to be so.

Kivy不提供传统的可编辑组合框. Kivy如何使您非常容易地创建结合了TextInput和DropDown的小部件.

Kivy doesn't provide a traditional editable combo-box. How ever Kivy makes it extremely easy for you to create your own widget combining a TextInput and a DropDown.

您应该使用摘要wiki 中所示的ComboEdit之类的东西,并对其进行修改以适合您的需求.

You should be using something like a ComboEdit as shown in the snippets wiki, and modifying it to suit your needs.

因此,您想要实现的目标可以像这样:

So, what you are trying to achieve can be done like so::

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()

这篇关于Kivy Clear_widget奇怪的行为(附带可复制的代码)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆