在kivy中使用多个treeview小部件

时间:2017-11-21 15:23:24

标签: python python-2.7 kivy kivy-language

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

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

如果我在城市中输入任何内容,那么城市会在树视图中显示。但我输入任何内容 在区域,然后也显示city.I已经为区域编写了单独的功能,但我不知道有什么问题?如果可以使用相同的功能与if else条件的城市树视图和区域treeview.Code将不会重复所以它会更好。

我选择城市然后将值放入城市TextBox但是我选择区域然后在城市TextBox中设置值。如何将值放在单独的TextBox中?城市treeView值放在城市TextBox和Area TreeView值放在区域TextBox。

1 个答案:

答案 0 :(得分:1)

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

我只会发布“区域”弹出窗口所需的内容

...
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中用TreeViewArea替换TreaviewGroupArea,如main中所定义,并添加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
...

我希望这会有所帮助