|
8 | 8 | derived widget. For example, it can be combined with a
|
9 | 9 | :class:`~kivy.uix.gridlayout.GridLayout` to add selection to the layout.
|
10 | 10 |
|
| 11 | +Compound selection concepts |
| 12 | +--------------------------- |
| 13 | +
|
11 | 14 | At its core, it keeps a dynamic list of widgets that can be selected.
|
12 | 15 | Then, as the touches and keyboard input are passed in, it selects one or
|
13 | 16 | more of the widgets based on these inputs. For example, it uses the mouse
|
14 | 17 | scroll and keyboard up/down buttons to scroll through the list of widgets.
|
15 | 18 | Multiselection can also be achieved using the keyboard shift and ctrl keys.
|
16 |
| -Finally, in addition to the up/down type keyboard inputs, it can also |
17 |
| -accepts letters from the keyboard to be used to select nodes with |
| 19 | +
|
| 20 | +Finally, in addition to the up/down type keyboard inputs, compound selection |
| 21 | +can also accept letters from the keyboard to be used to select nodes with |
18 | 22 | associated strings that start with those letters, similar to how files
|
19 | 23 | are selected by a file browser.
|
20 | 24 |
|
| 25 | +Selection mechanics |
| 26 | +------------------- |
| 27 | +
|
21 | 28 | When the controller needs to select a node, it calls :meth:`select_node` and
|
22 | 29 | :meth:`deselect_node`. Therefore, they must be overwritten in order alter
|
23 | 30 | node selection. By default, the class doesn't listen for keyboard or
|
|
30 | 37 | -------
|
31 | 38 |
|
32 | 39 | To add selection to a grid layout which will contain
|
33 |
| -:class:`~kivy.uix.Button` widgets:: |
| 40 | +:class:`~kivy.uix.Button` widgets. For each button added to the layout, you |
| 41 | +need to bind the :attr:`~kivy.uix.widget.Widget.on_touch_down` of the button |
| 42 | +to :meth:`select_with_touch` to pass on the touch events:: |
| 43 | +
|
| 44 | + from kivy.uix.behaviors.compoundselection import CompoundSelectionBehavior |
| 45 | + from kivy.uix.button import Button |
| 46 | + from kivy.uix.gridlayout import GridLayout |
| 47 | + from kivy.core.window import Window |
| 48 | + from kivy.app import App |
34 | 49 |
|
35 |
| - class SelectableGrid(CompoundSelectionBehavior, GridLayout): |
36 | 50 |
|
| 51 | + class SelectableGrid(CompoundSelectionBehavior, GridLayout): |
37 | 52 | def __init__(self, **kwargs):
|
| 53 | + """ Use the initialize method to bind to the keyboard to enable |
| 54 | + keyboard interaction e.g. using shift and control for multi-select. |
| 55 | + """ |
38 | 56 | super(CompoundSelectionBehavior, self).__init__(**kwargs)
|
39 | 57 | keyboard = Window.request_keyboard(None, self)
|
40 | 58 | keyboard.bind(on_key_down=self.select_with_key_down,
|
41 |
| - on_key_up=self.select_with_key_up) |
| 59 | + on_key_up=self.select_with_key_up) |
| 60 | +
|
| 61 | + def add_widget(self, widget): |
| 62 | + """ Override the adding of widgets so we can bind and catch their |
| 63 | + *on_touch_down* events. """ |
| 64 | + widget.bind(on_touch_down=self.button_touch_down, |
| 65 | + on_touch_up=self.button_touch_up) |
| 66 | + return super(SelectableGrid, self).add_widget(widget) |
| 67 | +
|
| 68 | + def button_touch_down(self, button, touch): |
| 69 | + """ Use collision detection to select buttons when the touch occurs |
| 70 | + within their area. """ |
| 71 | + if button.collide_point(*touch.pos): |
| 72 | + self.select_with_touch(button, touch) |
| 73 | +
|
| 74 | + def button_touch_up(self, button, touch): |
| 75 | + """ Use collision detection to de-select buttons when the touch |
| 76 | + occurs outside their area and *touch_multiselect* is not True. """ |
| 77 | + if not (button.collide_point(*touch.pos) or self.touch_multiselect): |
| 78 | + self.deselect_node(button) |
42 | 79 |
|
43 | 80 | def select_node(self, node):
|
44 | 81 | node.background_color = (1, 0, 0, 1)
|
45 |
| - return super(CompoundSelectionBehavior, self).select_node(node) |
| 82 | + return super(SelectableGrid, self).select_node(node) |
46 | 83 |
|
47 | 84 | def deselect_node(self, node):
|
48 | 85 | node.background_color = (1, 1, 1, 1)
|
49 |
| - super(CompoundSelectionBehavior, self).deselect_node(node) |
| 86 | + super(SelectableGrid, self).deselect_node(node) |
| 87 | +
|
| 88 | + def on_selected_nodes(self, gird, nodes): |
| 89 | + print("Selected nodes = {0}".format(nodes)) |
| 90 | +
|
| 91 | +
|
| 92 | + class TestApp(App): |
| 93 | + def build(self): |
| 94 | + grid = SelectableGrid(cols=3, rows=2, touch_multiselect=True, |
| 95 | + multiselect=True) |
| 96 | + for i in range(0, 6): |
| 97 | + grid.add_widget(Button(text="Button {0}".format(i))) |
| 98 | + return grid |
| 99 | +
|
| 100 | +
|
| 101 | + TestApp().run() |
50 | 102 |
|
51 |
| -Then, for each button added to the layout, bind the |
52 |
| -:attr:`~kivy.uix.widget.Widget.on_touch_down` of the button |
53 |
| -to :meth:`select_with_touch` to pass on the touch events. |
54 | 103 |
|
55 | 104 | .. warning::
|
56 | 105 |
|
@@ -92,7 +141,7 @@ class CompoundSelectionBehavior(object):
|
92 | 141 |
|
93 | 142 | touch_multiselect = BooleanProperty(False)
|
94 | 143 | '''A special touch mode which determines whether touch events, as
|
95 |
| - processed with :meth:`select_with_touch`, will add the currently touched |
| 144 | + processed by :meth:`select_with_touch`, will add the currently touched |
96 | 145 | node to the selection, or if it will clear the selection before adding the
|
97 | 146 | node. This allows the selection of multiple nodes by simply touching them.
|
98 | 147 |
|
|
0 commit comments