在 kivy 中使用多个 treeview 小部件

use multiple treeview widgets in kivy

test.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
import sys
Window.clearcolor = (.152, .149, .149, 0)
Window.size = (700, 330)


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)

rows = [('1','1','city1'),('2','2','city2'),('3','3','city3')]
tree = []

for r in rows:
    tree.append({'node_id': r[2], 'children': []})


class TreeViewLabel(Label, TreeViewNode):
    pass

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

    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)

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

rows = [('1','1','area1'),('2','2','area2'),('3','3','area3')]
treeArea = []

for r in rows:
    treeArea.append({'node_id': r[2], 'children': []})

class TreeviewArea(Popup):
    treeviewArea = ObjectProperty(None)
    tv = ObjectProperty(None)
    #ti = ObjectProperty()

    def __init__(self, **kwargs):
        super(TreeviewArea, self).__init__(**kwargs)
        self.tv = TreeView(root_options=dict(text=""),
                       hide_root=False,
                       indent_level=4)
        for branch in treeArea:
            populate_tree_view_area(self.tv, None, branch)
        self.remove_widgets()
        self.treeviewArea.add_widget(self.tv)

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

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

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

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


class FactArea(App):
    def build(self):
        self.root = Builder.load_file('test.kv')
        return self.root



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

test.kv

:基维 1.10.0

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

<TreeviewGroup>:
    id: treeview
    treeview: treeview
    title: "Select City"
    size_hint: None, None
    size: 400, 350
    auto_dismiss: False

    BoxLayout
        orientation: "vertical"
        #TextInput:
            #id: ti
            #size_hint_y: .1
            #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()

<TreeviewGroupArea>:
    id: treeviewArea
    treeviewArea: treeviewArea
    title: "Select City"
    size_hint: None, None
    size: 400, 350
    auto_dismiss: False

    BoxLayout
        orientation: "vertical"
        #TextInput:
            #id: ti
            #size_hint_y: .1
            #on_text: root.filter(self.text)
        BoxLayout:
            id: treeviewArea
            #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.200

AreaScreen:
    cityName: cityName

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

        Label:
            text: 'City'
            text_size: self.size
            valign: 'middle'
            padding_x: 50


        SingleLineTextInput:
            id: cityName
            font_size_valign:self.height*0.4
            on_text: root.display_cities(self)

        Label:
            text: 'Area'
            text_size: self.size
            valign: 'middle'
            padding_x: 50


        SingleLineTextInput:
            id: areaName
            on_text: root.display_areas(self)


        GreenButton:
            text: 'Ok'
            on_press: root.insert_data(cityName.text, areaName.text)



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

如果我在城市中输入任何内容,那么城市会显示在 treeview.But 我输入任何内容 在 area 然后还显示 city.I 已经为 area 编写了单独的函数,但我不知道出了什么问题?如果可能的话,使用相同的函数和 if else 条件用于城市树视图和 area treeview.Code 不会重复一遍,这样会更好。

I select city then value put in city TextBox 但 i select area then value also set in city TextBox.How to put value in separate TextBox?City treeView value put in city TextBox 和 Area TreeView 值放在区域 TextBox 中。

我知道你试图修改,但这还不够,你必须为每个弹出窗口重新定义 TreeView class 和 TreeViewLabel

我只会post区域弹出窗口所必需的

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

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

rowsa = [('1','1','area1'),('2','2','area2'),('3','3','area3')]
treeArea = []

for r in rowsa:
    treeArea.append({'node_id': r[2], 'children': []}) 

class TreeViewLabelArea(Label, TreeViewNode):
    pass

class TreeviewArea(Popup):
#You can let it as it is

...

class AreaScreen(Screen):
    groupName = ObjectProperty(None)
    popupcity = ObjectProperty(None)
    popuparea = ObjectProperty(None)
    #statecode = StringProperty('')

    ...

    def display_areas(self, instance):
        if len(instance.text) > 0:
            if self.popuparea is None:
                self.popuparea = TreeviewArea()
            #self.popup.filter(instance.text)
            self.popuparea.open()

然后在您的 kv 中将 TreaviewGroupArea 替换为 main 中定义的 TreeViewArea 并添加 TreeViewLabelArea 规则

...
<TreeViewLabelArea>:
    height: 24
    on_touch_down:
        app.root.areaName.text = self.text
        #app.root.select_node(self)
        app.root.popuparea.dismiss()

最后在 AreaScreen 规则中添加 areaName 属性

...
AreaScreen:
    cityName: cityName
    areaName: areaName
...

希望对您有所帮助