Kivy is intended for touch-screen devices. The processing of input devices, such as keyboards and remote controls, is relatively weak. However, sometimes we need to process keys, such as switching the focus through the direction keys, this article discusses how to implement it.
Before reading the following code, it is best to have a basic understanding of the kivy UI system.
By convention, we first go to the code and then explain the Code:
Focustest. py
import kivykivy.require('1.8.0')from kivy.app import Appfrom kivy.properties import StringProperty,BooleanPropertyfrom kivy.core.window import Windowfrom kivy.uix.widget import Widgetfrom kivy.uix.button import Buttonfrom kivy.graphics import Color, Ellipse, Line,Rectanglefrom kivy.uix.boxlayout import BoxLayoutclass MyButton(Button): focus = BooleanProperty(False) def __init__(self,**kwargs): super(MyButton,self).__init__(**kwargs)# with self.canvas.before: rect=(self.pos[0]+4,self.pos[1]+4,self.size[0]-8,self.size[1]-8) with self.canvas.after: self.edge_color = Color(0,0,0,0) self.edge = Line(rectangle=rect,width=4,joint='round') self.edge_center_color = Color(1,1,1,0) self.edge_center = Line(rectangle=rect,width=1) # listen to size and position changes self.bind(pos=self.update_rect,size=self.update_rect) self.focus=False def update_rect(self,instance,value): rect=(self.pos[0]+4,self.pos[1]+4,self.size[0]-8,self.size[1]-8) self.edge.rectangle=rect self.edge_center.rectangle=rect def set_focus(self): self.focus = True self.parent.on_focus_changed(self) def on_focus(self,instance,focused): print '++++++++++++++on_focus:',focused if focused: self.edge_color.rgba = (0.4,0.4,1,1) self.edge_center_color.rgba=(1,1,1,1) else: self.edge_color.rgba = (0,0,0,0) self.edge_center_color.rgba=(0,0,0,0) def on_press(self): pass def on_release(self): pass def on_touch_down(self,touch): print '++++++++++++++++++on_touch_down:',touch if self.collide_point(*touch.pos): self.set_focus() super(MyButton,self).on_touch_down(touch)class FocusTest(BoxLayout): def __init__(self,**kargs): super(FocusTest,self).__init__(**kargs) self.buttons = [] btn1 = MyButton(text='1',on_press=self.on_press) btn1.size_hint=(0.5,0.5) self.add_widget(btn1) Window.bind(on_key_down=self.on_key_down) btn = MyButton(text='2',on_press=self.on_press) btn.size_hint=(0.2,0.2) btn.pos_hint={'top':0.8} self.add_widget(btn) btn = MyButton(text='3',on_press=self.on_press) btn.size_hint=(0.2,0.3) self.add_widget(btn) self.children[-1].set_focus() self.index = len(self.children) - 1 with self.canvas.before: Color(0, 1, 0, 1) self.rect = Rectangle(size=self.size,pos=self.pos) Color(1, 1, 0, 1) self.border = Line(rectangle=self.pos+self.size,width=3) # listen to size and position changes self.bind(pos=FocusTest.update_rect, size=FocusTest.update_rect) for item in self.children: print item.text def on_focus_changed(self,focusitem): index = 0 for item in self.children: if focusitem is item: self.index = index else: item.focus = False index += 1 def on_key_down(self,window,key,scancode,a,b): print 'on_key_down:',key,scancode if key == 275: #left if self.index == 0: self.index = len(self.children) - 1 else: self.index -= 1 elif key == 276: #right if self.index == len(self.children) - 1: self.index = 0 else: self.index += 1 self.children[self.index].set_focus() def on_key_up(self,window,key,scancode): pass def on_press(self,control): print control def on_release(self,control): print control def update_rect(self,value): self.rect.pos = self.pos self.rect.size = self.size self.border.rectangle=self.pos+self.sizeclass MyApp(App): def build(self): return FocusTest() def on_pause(self): return Trueif __name__ == '__main__': MyApp().run()
Run this example to create three buttons. you can press the left and right arrow keys to switch the focus between the three buttons, as shown in:
Next, let's take a look at what the code of the 130 lines has done:
First of all:
In focustest. _ init _, there is a line of critical code:
Window. BIND (on_key_down = self. on_key_down)
This line of code is used to register a key-down message listener in the window to receive key messages.
Next, let's take a look at what on_key_down has done:
def on_key_down(self,window,key,scancode,a,b): print 'on_key_down:',key,scancode if key == 275: #left if self.index == 0: self.index = len(self.children) - 1 else: self.index -= 1 elif key == 276: #right if self.index == len(self.children) - 1: self.index = 0 else: self.index += 1 self.children[self.index].set_focus()
Here we implement the function of switching focus based on the left and right direction keys. The most important thing is the last line of code:
Self. Children [self. Index]. set_focus ()
Let's take a look at what mybutton. set_focus has done:
Def set_focus (Self ):
Self. Focus = true
Self. Parent. on_focus_changed (Self)
Self. Focus is a booleanproperty. Assigning a value to it will trigger: on_focus. If you have any questions, refer to the following article:
Kivy A to Z -- properties of kivy
The on_focus method draws different rectangular boxes based on whether mybutton obtains the focus:
Def on_focus (self, instance, focused ):
Print '++ on_focus:', focused
If focused:
Self. edge_color.rgba = (0.4, 0.4)
Self. edge_center_color.rgba = (1, 1, 1)
Else:
Self. edge_color.rgba = (0, 0, 0)
Self. edge_center_color.rgba = (0, 0, 0)
Finally, let's take a look at what self. Parent. on_focus_changed (Self) has done. parent is focustest:
Def on_focus_changed (self, focusitem ):
Index = 0
For item in self. Children:
If focusitem is item:
Self. Index = index
Else:
Item. Focus = false
Index + = 1
The code here is to set other buttons to a non-focus state.
Finally, let's take a look at the following in mybutton. _ init:
Self. BIND (Pos = self. update_rect, size = self. update_rect)
The function of this line of code is to listen to button size and position changes, and adjust the size of the rectangle frame when the focus is drawn.
OK, that's all