python - 如何在子节点中也应用搜索

标签 python python-2.7 kivy kivy-language

演示.py

import sqlite3 as lite

from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.popup import Popup
from kivy.uix.treeview import TreeView, TreeViewLabel, TreeViewNode
from kivy.uix.label import Label
from kivy.properties import ObjectProperty,StringProperty

Window.size = (700, 530)


def populate_tree_view(tree_view, parent, node):
    if parent is None:
        tree_node = tree_view.add_node(TreeViewLabel(text=node['node_id'],
                                                     is_open=True))
    else:
        tree_node = tree_view.add_node(TreeViewLabel(text=node['node_id'],
                                                     is_open=True), parent)

    for child_node in node['children']:
        populate_tree_view(tree_view, tree_node, child_node)


tree = []

tree = [{'node_id': 'Capital Account',
         'children': [{'node_id': 'Reserves & Surplus',
                       'children': [{'node_id': '1.1.1',
                                     'children': [{'node_id': '1.1.1.1',
                                                   'children': []}]},
                                    {'node_id': '1.1.2',
                                     'children': []},
                                    {'node_id': '1.1.3',
                                     'children': []}]},
                       {'node_id': '1.2',
                        'children': []}]},
        {'node_id': 'Current Assests',
         'children': []}]


class TreeViewLabel(Label, TreeViewNode):
    pass

class TestViewLabel():
    pass


class TreeviewGroup(Popup):
    treeview = ObjectProperty(None)
    tv = ObjectProperty(None)
    ti = ObjectProperty()
    abc = StringProperty('c')

    def __init__(self, **kwargs):
        super(TreeviewGroup, self).__init__(**kwargs)
        self.tv = TreeView(root_options=dict(text=""),
                       hide_root=False,
                       indent_level=4)
        for branch in tree:
            populate_tree_view(self.tv, None, branch)
        self.remove_widgets()
        self.treeview.add_widget(self.tv)

    def remove_widgets(self):
        for child in [child for child in self.treeview.children]:
            self.treeview.remove_widget(child)

    def filter(self, f):
        self.treeview.clear_widgets()
        self.tv = TreeView(root_options=dict(text=""),
                           hide_root=False,
                           indent_level=4)
        new_tree = []
        for n in tree:
            if f.lower() in n['node_id'].lower():
                new_tree.append(n)
        for branch in new_tree:
            populate_tree_view(self.tv, None, branch)

        self.treeview.add_widget(self.tv)



class CityScreen(Screen):
    groupName = ObjectProperty(None)
    popup = ObjectProperty(None)
    statecode = StringProperty('')

    def display_states(self, instance):
        if len(instance.text) > 0:
            if self.popup is None:
                self.popup = TreeviewGroup()
            self.popup.filter(instance.text)
            self.popup.open()

    def select_node(self, node):
        '''Select a node in the tree.
            '''

class MyApp(App):

    def build(self):
        self.root = Builder.load_file('demo.kv')
        return self.root


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

演示.kv

#:kivy 1.10.0

<TreeViewLabel>:
    on_touch_down:
        app.root.stateName.text = self.text
        app.root.select_node(self)
        app.root.popup.dismiss()

<TestViewLabel>:
    on_touch_down:
        app.root.stateName.text = self.text
        app.root.select_node(self)
        app.root.popup.dismiss()

<TreeviewGroup>:
    id: treeview
    treeview: treeview
    size_hint: None, None
    size: 400, 400
    auto_dismiss: False

    BoxLayout
        orientation: "vertical"
        TextInput:
            id: ti
            size_hint_y: .1
            text: root.abc
            on_text: root.filter(self.text)
        BoxLayout:
            id: treeview
            #on_press: root.select_node(self.text)
        Button:
            size_hint: 1, 0.1
            text: "Close"
            on_release: root.dismiss()


<CustomLabel@Label>:
    text_size: self.size
    valign: "middle"
    padding_x: 5

<SingleLineTextInput@TextInput>:
    multiline: False

<GreenButton@Button>:
    background_color: 1, 1, 1, 1
    size_hint_y: None
    height: self.parent.height * 0.150

CityScreen:
    stateName: stateName

    GridLayout:
        cols: 2
        padding : 30,30
        spacing: 10, 10
        row_default_height: '40dp'

        CustomLabel:
            text: 'Text'

        SingleLineTextInput:
            id: stateName
            on_text: root.display_states(self)

        #Spinner:
            #text: "State Code"
            #values: ["111", "112", "113", "114"]
            #values: app.r
            #background_color: color_button if self.state == 'normal' else color_button_pressed
            #background_down: 'atlas://data/images/defaulttheme/spinner'
            #color: color_font
            #option_cls: Factory.get("MySpinnerOption")
            #size_hint: None, None

        GreenButton:
            text: 'Ok'
            on_press: root.insert_data(stateName.text)


        GreenButton:
            text: 'Cancel'
            on_press: app.stop()

        Label:

        Label:
  1. 当我在文本文本框中输入内容时,将显示一个弹出窗口。然后如何将值从文本文本框传递到弹出窗口中的搜索框。

  2. SearchBox 非常适合父节点。它不适用于子节点。这将如何工作?

最佳答案

  1. When i type something in text TextBox then a pop up will be show.Then how to pass value from text TextBox to searchbox in pop up like attached image.

由于打开弹出窗口时有文本输入属性,因此您可以传递文本:

...
<TreeviewGroup>:
    id: treeview
    treeview: treeview
    size_hint: None, None
    size: 400, 400
    auto_dismiss: False
    ti: ti
    BoxLayout
        orientation: "vertical"
        TextInput:
            id: ti
            size_hint_y: .1
            on_text: root.filter(self.text)

然后在.py中:

...

class CityScreen(Screen):
    groupName = ObjectProperty(None)
    popup = ObjectProperty(None)
    statecode = StringProperty('')

    def display_states(self, instance):
        if len(instance.text) > 0:
            if self.popup is None:
                self.popup = TreeviewGroup()
            self.popup.ti.text = instance.text
            self.popup.filter(instance.text)
            self.popup.open()
...

2 SearchBox working perfect for parent node.It's not working for child node.How will this work?

这并不容易做到,这个问题值得悬赏

为了在 treeView 的 subview 也是父 View 时创建过滤器,我做了很多递归

首先,将这些函数添加到您的 .py

...
def get_children(n):
    '''get all the children in the node whithout her children'''
    if len(n['children']) == 0:
        return []
    else:
        children = [e['node_id'] for e in n['children']]
        for child in n['children']:
            children.extend([c for c in get_children(child)])
        return children


def get_children2(n, t):
    '''get the node with n as id'''
    if t is []:
        return False
    else:
        for child in t:
            if child['node_id'] == n:
                return child
            else:
                r = get_children2(n, child['children'])
                if r:
                    return r

def roots(n):
    '''return the roots (if a node have child it is a root)'''
    if len(n['children']) == 0:
        return [None]
    else:
        l = [n['node_id']]
        for c in n['children']:
            l.extend(roots(c))
        return l


def get_roots(t):
    '''this one is just to remove the None from the result of the first one'''
    fl = []
    for n in t:
        l = roots(n)
        li = []
        for e in l:
            if e is not None:
                li.append(e)
        fl.extend(li)
        if len(n['children']) == 0:
            fl.append(n['node_id'])
    return fl

...

现在您可以更改TreeView的过滤方法:

...
class TreeviewGroup(Popup):
    treeview = ObjectProperty(None)
    tv = ObjectProperty(None)
    ti = ObjectProperty()

    ...

    def filter(self, f):
        self.tv = TreeView(root_options=dict(text=""),
                           hide_root=False,
                           indent_level=4)
        for branch in tree:
            populate_tree_view(self.tv, None, branch)
        self.remove_widgets()
        self.treeview.add_widget(self.tv)
        l = []
        l_roots = get_roots(tree)
        dict_roots = []
        for node in self.tv.iterate_all_nodes():
            l.append(node)
        for i in range(len(l)):
            if l[i].text in l_roots:
                dict_roots.append({'ind': i, 'id': l[i].text})
        roots_childs = {}
        for e in l:
            try:
                nod = get_children2(e.text, tree)
                roots_childs[e.text] = get_children(nod)
            except TypeError:
                pass
        to_remove = []            
        for e in roots_childs:
            for child in roots_childs[e]:
                if child not in l_roots:
                    if f.lower() not in child.lower():
                        if child not in to_remove:
                            to_remove.append(child)
            n = 0
            for child in roots_childs[e]:
                if child in to_remove:
                    n += 1
            if n == len(roots_childs[e]):
                if f.lower() not in e.lower():
                    to_remove.append(e)
        for n in l:
            if n.text in to_remove:
                self.tv.remove_node(n)

更新我忘记在 kv 的 TreeViewGroop 中添加 ti ,现在已修复

关于python - 如何在子节点中也应用搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47323210/

相关文章:

python - Django:使用管理上下文扩展基于类的 View 的上下文

python - 笛卡尔积 - 使用 BackTracking - Python

python - 带有图像和线程的 kivy 故障

python - 交换多维 Python 列表的轴

python - 使用列表中未显示的字段进行后续搜索

python - 按 'escape' 时离开 kivy 应用程序

python - Kivy 时钟和弹出窗口

python - 试图从一个类中调用一个对象

javascript - 使用 BS4 python 单击并抓取 aspx 页面

python - 从 Python 中的集合中选择一个项目