Kivy A to Z -- How to Implement focus Switching

Source: Internet
Author: User

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






Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.