Kivy – Grid Layouts ”; Previous Next GridLayout is one of the commonly used layout types in Kivy. A GridLayout object acts as a container grid. It divides the window area in specified number of rows and columns and puts other widgets in the cells. GridLayout class is defined in kivy.uix.gridlayout module. The object must have at least one of the properties – rows and cols – defined. If you do not specify any of these two, Kivy throws GridLayoutException. from kivy.uix.gridlayout import GridLayout grid = GridLayout(**kwargs) The properties of GridLayout object are as follows − cols − Number of columns in the grid. You can no longer set this to a negative value. cols is a NumericProperty and defaults to None. rows − Number of rows in the grid. You can no longer set this to a negative value. rows is a NumericProperty and defaults to None. cols_minimum − Dict of minimum width for each column. The dictionary keys are the column numbers, (e.g. 0, 1, 2…).It is a DictProperty and defaults to {}. rows_minimum − Dict of minimum height for each row. The dictionary keys are the row numbers, (e.g. 0, 1, 2…). It is a DictProperty and defaults to {}. minimum_width − Automatically computed minimum width needed to contain all children. It is a NumericProperty and defaults to 0. It is read only. minimum_height − Automatically computed minimum height needed to contain all children. It is a NumericProperty and defaults to 0. It is read only. orientation − Orientation of the layout. This property determines how the widgets are placed in successive cells in the grid. “orientation” is an OptionProperty. Its valid values are − ”lr-tb” − cells filled in left to right and top to bottom order. ”tb-lr” − cells filled in top to bottom and left to right order. ”rl-tb” − cells filled in right to left and top to bottom order. ”tb-rl” − cells filled in top to bottom and right to left order. ”lr-bt” − cells filled in left to right and bottom to top order. ”bt-lr” − cells filled in bottom to top and left to right order. ”rl-bt” − cells filled in right to left and bottom to top order. ”bt-rl” − cells filled in bottom to top and right to left order. Default value of orientation property is ”lr-tb”. row_default_height − Default minimum size to use for row. row_default_height is a NumericProperty and defaults to 0. row_force_default − If True, ignore the height and size_hint_y of the child and use the default row height. row_force_default is a BooleanProperty and defaults to False. spacing −: Spacing between children: [spacing_horizontal, spacing_vertical]. spacing is a VariableListProperty and defaults to [0, 0]. padding − Padding between the layout box and its children: [padding_left, padding_top, padding_right, padding_bottom]. padding is a VariableListProperty and defaults to [0, 0, 0, 0]. By default, all the widgets have the same size. This is because the default size_hint is (1,1). def build(self): self.lo = GridLayout(cols=2) self.b1 = Button(text=”Button 1”, font_size=20) self.b2 = Button(text=”Button 2”, font_size=20) self.b3 = Button(text=”Button 3”, font_size=20) self.b4 = Button(text=”Button 4”, font_size=20) self.lo.add_widget(self.b1) self.lo.add_widget(self.b2) self.lo.add_widget(self.b3) self.lo.add_widget(self.b4) return self.lo With this code, you will get the following layout − Now, let”s fix the size of Hello buttons to 250px instead of using “size_hint_x=None”. self.lo = GridLayout(cols = 2) self.b1 = Button( text=”Button 1”, font_size=20, size_hint_x=None, width=250 ) self.b2 = Button(text=”Button 2”, font_size=20) self.b3 = Button( text=”Button 3”, font_size=20, size_hint_x=None, width=250 ) self.b4 = Button(text=”Button 4”, font_size=20 The App window appears as below − If we define row_default_height to 100 and set “row_force_default=True” − self.lo = GridLayout( cols=2, row_force_default=True, row_default_height=100 ) self.b1 = Button( text=”Button 1”, font_size=20, size_hint_x=None, width=250 ) self.b2 = Button(text=”Button 2”, font_size=20) self.b3 = Button( text=”Button 3”, font_size=20, size_hint_x=None, width=250 ) self.b4 = Button(text=”Button 4”, font_size=20) Now the window appears like this − Example 1 In this program, we add 15 buttons in a grid layout with four columns. The caption of each button is a unique but randomly generated number between 1 to 15. The randint() function in random module is used for this purpose. from kivy.app import App from kivy.uix.button import Button from kivy.uix.gridlayout import GridLayout from kivy.config import Config import random Config.set(”graphics”, ”width”, ”720”) Config.set(”graphics”, ”height”, ”400”) Config.set(”graphics”, ”resizable”, ”1”) class MyApp(App): def build(self): self.grid = GridLayout(cols = 4) nums=[] for i in range(1,16): while True: num = random.randint(1,15) if num not in nums: nums.append(num) self.grid.add_widget(Button(text = str(num))) break return self.grid if __name__ == ”__main__”: MyApp().run() Output When you run this code, it will produce the following output window − Example 2 The GridLayout in Kivy doesn”t have the provision to span a widget across rows and/or columns. It is also not possible to place a widget by its row and column numbers. It is required to arrange a few labels and text input boxes in a two column grid, but the submit button below should span across two columns. To achieve this, we place a 2 column grid inside a on column grid, and a button below it. from kivy.app import App from kivy.uix.label import Label from kivy.uix.button import Button from kivy.uix.textinput import TextInput from kivy.uix.gridlayout import GridLayout from kivy.core.window import Window Window.size = (720, 400) class DemoApp(App): def build(self): self.grid = GridLayout(rows=2) self.top_grid = GridLayout( cols=2, row_force_default=True, row_default_height=100 ) self.top_grid.cols = 2 self.top_grid.add_widget( Label(text=”Name: “, size_hint_x=None, width=250) ) self.fname = TextInput( multiline=False, size_hint_x=None, width=650 ) self.top_grid.add_widget(self.fname) self.top_grid.add_widget(Label(text=”Address: “)) self.address = TextInput(multiline=True) self.top_grid.add_widget(self.address) self.top_grid.add_widget(Label(text=”College: “)) self.college = TextInput(multiline=False) self.top_grid.add_widget(self.college) self.grid.add_widget(self.top_grid) self.b1 = Button(text=”Submit”, size_hint_y=None, height=200) self.grid.add_widget(self.b1) return self.grid if __name__ == ”__main__”: DemoApp().run() Output When you
Category: kivy
Kivy – Inspector
Kivy – Inspector ”; Previous Next Kivy provides a very useful tool called Inspector, which helps you in rectifying the problems encountered when implementing the interface designed with the “kv” script or programmatically. The Inspector tool has a command-line interface, and it can also be used from within the code. The command-line usage is − python main.py -m inspector To use it programmatically, call the create_inspector() function in the “kivy.modules.inspector” module. from kivy.modules import inspector class Demo(App): def build(self): button = Button(text=”Test”) inspector.create_inspector(Window, button) return button Obviously, the command-line usage is more convenient. Let us find out the utility of this tool. Assume that you have developed a Kivy application with slider.py program that has the following interface. The app has three slider controls that help in changing the color of the text above. Start the program from the command prompt with the following command − python sliderdemo.py -m inspector The above screen will be displayed. Press ctrl+E keys to display the Inspector bar. The bar can be moved to top or bottom for convenience. Click on any of the components on the window. The wide button displays the Object ID of the clicked widget. Now press the Parent button. The Parent widget of the select widget will be highlighted. Double click on the wide button. It will now show three panes with splitters to adjust the sizes. The left pane shows the widget tree, the middle pane shows all the properties of the selected widget and the one on the right shows the value of selected property. The following figure shows that the BLUE slider is selected from the widget tree, its properties are displayed in the middle pane, and the max property value is seen in the right pane. You can also change the property value from the inspector tool. Scroll down the middle pane to locate the value property and change its value in the right pane text box. The Inspector tool can be very useful in troubleshooting the user interfaces. Print Page Previous Next Advertisements ”;
Kivy – OpenGL
Kivy – OpenGL ”; Previous Next The Kivy framework is equipped with powerful graphics capabilities built on top of OpenGL and SDL instructions. Kivy uses OpenGL ES 2 graphics library, and is based on Vertex Buffer Object and shaders. The “kivy.graphics.opengl” module is a Python wrapper around OpenGL commands. A shader is a user-defined program designed to run on some stage of a graphics processor. Shaders are written in OpenGL Shading Language (GLSL), which is a high-level shading language with a syntax based on the C programming language. The two commonly used shaders to create graphics on the web are Vertex Shaders and Fragment (Pixel) Shaders. Vertex shaders − They take the input from the previous pipeline stage (e.g. vertex positions, colors, and rasterized pixels) and customize the output to the next stage. Fragment shaders − They take 2D position of all pixels as input and customize the output color of each pixel. A detailed discussion on the features and syntax of GLSL is beyond the scope of this tutorial. We shall use an open-source shader file (kaleidoscope.glsl) in this chapter. #ifdef GL_ES precision highp float; #endif uniform vec2 resolution; uniform float time; uniform sampler2D tex0; uniform sampler2D tex1; void main(void){ vec2 p = -1.0 + 2.0 * gl_FragCoord.xy / resolution.xy; vec2 uv; float a = atan(p.y,p.x); float r = sqrt(dot(p,p)); uv.x = 7.0*a/3.1416; uv.y = -time+ sin(7.0*r+time) + .7*cos(time+7.0*a); float w = .5+.5*(sin(time+7.0*r)+ .7*cos(time+7.0*a)); vec3 col = texture2D(tex0,uv*.5).xyz; gl_FragColor = vec4(col*w,1.0); } In our Kivy application code, we use a .kv file that simply draws a rectangle on the canvas of a FloatLayout widget. <ShaderWidget>: canvas: Color: rgb: 1, 0, 0 Rectangle: pos: self.pos size: self.size The ShaderWidget rule of this “kv” file corresponds to the ShaderWidget class. It schedules a clock interval to be fired after each second to update the glsl variables in the shader definition. class ShaderWidget(FloatLayout): fs = StringProperty(None) def __init__(self, **kwargs): self.canvas = RenderContext() super(ShaderWidget, self).__init__(**kwargs) Clock.schedule_interval(self.update_glsl, 1 / 60.) The “fs” class variable stores the code from glsl file. The RenderContext() method from kivy.graphics module stores all the necessary information for drawing, i.e., the vertex shader and the fragment shader, etc. The “fs” StringProperty is bound to the “on_fs()” method which will set the shader. def on_fs(self, instance, value): shader = self.canvas.shader old_value = shader.fs shader.fs = value if not shader.success: shader.fs = old_value raise Exception(”failed”) The update_glsl() method will be called each time the scheduled clock event occurs. It basically updates the fragment color of each pixel on the application window. def update_glsl(self, *largs): self.canvas[”time”] = Clock.get_boottime() self.canvas[”resolution”] = list(map(float, self.size)) win_rc = Window.render_context self.canvas[”projection_mat”] = win_rc[”projection_mat”] self.canvas[”modelview_mat”] = win_rc[”modelview_mat”] self.canvas[”frag_modelview_mat”] = win_rc[”frag_modelview_mat”] The App class simple loads the ShaderWidget from the kv file and class definition. Example The complete code is given below − from kivy.clock import Clock from kivy.app import App from kivy.uix.floatlayout import FloatLayout from kivy.core.window import Window from kivy.graphics import RenderContext from kivy.properties import StringProperty from kivy.core.window import Window Window.size=(720,400) file=open(”kaleidoscope.glsl”) shader=file.read() class ShaderWidget(FloatLayout): fs = StringProperty(None) def __init__(self, **kwargs): self.canvas = RenderContext() super(ShaderWidget, self).__init__(**kwargs) Clock.schedule_interval(self.update_glsl, 1 / 60.) def on_fs(self, instance, value): shader = self.canvas.shader old_value = shader.fs shader.fs = value if not shader.success: shader.fs = old_value raise Exception(”failed”) def update_glsl(self, *largs): self.canvas[”time”] = Clock.get_boottime() self.canvas[”resolution”] = list(map(float, self.size)). win_rc = Window.render_context self.canvas[”projection_mat”] = win_rc[”projection_mat”] self.canvas[”modelview_mat”] = win_rc[”modelview_mat”] self.canvas[”frag_modelview_mat”] = win_rc[”frag_modelview_mat”] class ”kaleidoscopeApp(App): title=”kaleidoscope” def build(self): return ShaderWidget(fs=shader) ”kaleidoscopeApp().run() Output Run this code and check the output − Print Page Previous Next Advertisements ”;
Kivy – Tree View
Kivy – Tree View ”; Previous Next Most of the GUI toolkits, including Kivy, provide a TreeView widget with which a user can navigate and interact with hierarchical data presented as nodes in a tree-like format. The file and directory structure shown in the file explorer of an operating system is a typical example of TreeView. The “kivy.uix.treeview” module includes the definitions of three important classes: TreeView, TreeViewNode, and TreeViewLabel. Objects of these classes constitute the tree view widget. A TreeView is populated by the instances of TreeViewNode instances. Any widget from the library such as a label or a button, or a user-defined widget object is combined with TreeViewNode. The root of the tree view is the TreeView object itself. from kivy.uix.treeview import TreeView tv = TreeView() One or more nodes can be directly added below this root. A TreeViewLabel is used as argument for add_node method from kivy.uix.treeview import TreeViewLabel n1 = tv.add_node(TreeViewLabel(text=”node 1”)) Instead of adding a node to the root of the tree, you can add it to a node itself. Provide the instance of the parent node as the second argument to the add_node() method − n2 = tv.add_node(TreeViewLabel(text=”Political Sci”), n1) The root widget of the tree view is opened by default and its default caption is ”Root”. To change that, you can use the TreeView.root_options property. This will pass options to the root widget − tv = TreeView(root_options=dict(text=”My root”)) The TreeViewLabel itself is a label, and hence cannot generate any event as on_press. For that you should define a class that inherits TreeView and a Button. class TreeViewButton(Button, TreeViewNode): pass You can then process different events such as − on_node_expand − Fired when a node is being expanded on_node_collapse − Fired when a node is being collapsed Example The code given below composes a simple tree view of subjects available in each faculty of a college. A vertical box layout houses a treeview widget and a button. The root of the tree view is open. To expand a node, click the “>” button to its left. It turns to a downward arrow. If clicked again, the node is collapsed. from kivy.app import App from kivy.uix.treeview import TreeView, TreeViewLabel from kivy.uix.button import Button from kivy.uix.boxlayout import BoxLayout from kivy.core.window import Window Window.size = (720, 350) class DemoApp(App): def build(self): lo = BoxLayout(orientation=”vertical”) self.tv = TreeView(root_options={ ”text”: ”Faculty-wise Subjects”, ”font_size”: 20} ) self.n1 = self.tv.add_node(TreeViewLabel(text=”Arts”)) self.n2 = self.tv.add_node(TreeViewLabel(text=”Commerce”)) self.n3 = self.tv.add_node(TreeViewLabel(text=”Science”)) self.n4 = self.tv.add_node( TreeViewLabel(text=”Sociology”), self.n1 ) self.n5 = self.tv.add_node( TreeViewLabel(text=”History”), self.n1 ) self.n6 = self.tv.add_node( TreeViewLabel(text=”Political Sci”), self.n1 ) self.n7 = self.tv.add_node( TreeViewLabel(text=”Accountancy”), self.n2 ) self.n8 = self.tv.add_node( TreeViewLabel(text=”Secretarial Practice”), self.n2 ) self.n9 = self.tv.add_node( TreeViewLabel(text=”Economics”), self.n2 ) self.n10 = self.tv.add_node( TreeViewLabel(text=”Physics”), self.n3 ) self.n11 = self.tv.add_node( TreeViewLabel(text=”Mathematics”), self.n3 ) self.n12 = self.tv.add_node( TreeViewLabel(text=”Chemistry”), self.n3 ) lo.add_widget(self.tv) return lo DemoApp().run() Output Print Page Previous Next Advertisements ”;
Kivy – Layouts in Layouts
Kivy – Layouts in Layouts ”; Previous Next A Layout in Kivy is a container widget. It provides an effective mechanism to construct a GUI having different widgets. Kivy library includes different Layout widgets such as GridLayout, BoxLayout, AnchorLayout, etc. A layout itself is a subclass of Widget class. Hence, we can strategically place one or more layouts inside a layout. In this way, a hierarchy of widget structure can be constructed to design an effective GUI for the app. Any Layout can be enclosed in any other layout. It all depends upon how the app design is envisaged by the developer. Let us plan our app interface layout as per the following schematic figure − Here, we need an uppermost one-column grid layout. Inside it, we want to put a TextInput and two more horizontal box layouts. The first box contains three buttons. The one below it has an Image control and an AnchorLayout widget that has a slider control in it. Example The following “kv” language script uses this planned structure − GridLayout: cols: 1 size: root.width, root.height TextInput: text: “Hello World!” font_size: 32 size_hint: (1, .2) BoxLayout: orientation:”horizontal” size_hint: (1, .2) Button: text:”Btn 1″ font_size:32 Button: text:”Btn 2″ font_size:32 Button: text:”Btn 3″ font_size:32 FloatLayout: Image: source: “kivy-logo.png.png” size_hint: .5, .75 pos_hint: {“center_x”: 0.25} AnchorLayout: anchor_x : ”center” anchor_y : ”top” size_hint: .5, .75 pos_hint: {“center_x”: 0.75} Slider: min:0 max:100 value:25 You can load this “kv” script in the following App class − from kivy.app import App from kivy.uix.widget import Widget from kivy.animation import Animation from kivy.core.window import Window Window.size = (720,400) class MyLayoutApp(App): def build(self): pass if __name__ == ”__main__”: MyLayoutApp().run() Output When you run this code, it will produce the following output window − The final appearance of the app window is similar to the initial plan, which uses “layouts in a layout”. Print Page Previous Next Advertisements ”;
Kivy – Bezier
Kivy – Bezier ”; Previous Next In this chapter, we shall create a Kivy app that will interactively draw a Bezier line along the list of points. If a closed line is drawn making use of the x and y coordinates computed with the help of following code segment, the resulting figure resembles a Pacman character − from math import cos, sin, radians x = y = 300 z = 200 self.points = [x, y] for i in range(45, 360, 45): i = radians(i) self.points.extend([x + cos(i) * z, y + sin(i) * z]) with self.layout.canvas: Color(1.0, 0.0, 1.0) self.line = Line( points=self.points + self.points[:2], dash_offset=10, dash_length=100 ) It generates a line pattern as the following − Then, we draw a Bezier line making use of the same list of points. Color(1.0, 0.0, 1.0) self.line = Line( points=self.points + self.points[:2], dash_offset=0, dash_length=100 ) The Line as well as the Beizer will appear as this − Now we want to construct these two curves dynamically. We use two slidersto change the dash length and offset values of both the line instruction and Bezier instruction as the value property of each slider changes with the following event handlers − def _set_bezier_dash_offset(self, instance, value): # effect to reduce length while increase offset self.bezier.dash_length = 100 – value self.bezier.dash_offset = value def _set_line_dash_offset(self, instance, value): # effect to reduce length while increase offset self.line.dash_length = 100 – value self.line.dash_offset = value As a result, change the slider values to see how the two curves are redrawn dynamically. Example The complete code is given below − from kivy.app import App from kivy.uix.floatlayout import FloatLayout from kivy.uix.label import Label from kivy.uix.slider import Slider from kivy.graphics import Color, Bezier, Line from kivy.core.window import Window Window.size = (720,400) class Main(App): title=”Bezier Example” def _set_bezier_dash_offset(self, instance, value): # effect to reduce length while increase offset self.bezier.dash_length = 100 – value self.bezier.dash_offset = value def _set_line_dash_offset(self, instance, value): # effect to reduce length while increase offset self.line.dash_length = 100 – value self.line.dash_offset = value def build(self): from math import cos, sin, radians x = y = 300 z = 200 # Pacman ! self.points = [x, y] for i in range(45, 360, 45): i = radians(i) self.points.extend([x + cos(i) * z, y + sin(i) * z]) print (self.points) self.layout = FloatLayout() with self.layout.canvas: Color(1.0, 0.0, 0.0) self.bezier = Bezier( points=self.points, segments=150, loop=True, dash_length=100, dash_offset=10 ) Color(1.0, 0.0, 1.0) self.line = Line( points=self.points + self.points[:2], dash_offset=10, dash_length=100) l1=Label( text=”Beizer offset”, pos_hint={”x”:.1}, size_hint=(.1, None), height=50 ) self.layout.add_widget(l1) s1 = Slider( y=0, pos_hint={”x”: .3}, size_hint=(.7, None), height=50 ) self.layout.add_widget(s1) s1.bind(value=self._set_bezier_dash_offset) l2=Label( text=”Line offset”, y=50, pos_hint={”x”:.1}, size_hint=(.1, None), height=50 ) self.layout.add_widget(l2) s2 = Slider( y=50, pos_hint={”x”: .3}, size_hint=(.7, None), height=50 ) self.layout.add_widget(s2) s2.bind(value=self._set_line_dash_offset) return self.layout if __name__ == ”__main__”: Main().run() Output The following screenshots show the curves at two different slider positions − Print Page Previous Next Advertisements ”;
Kivy – Miscellaneous
Kivy – Miscellaneous ”; Previous Next Kivy – Exception Handling In programming, Exception handling refers to the mechanism to prevent the program from crashing if it encounters run-time errors. Kivy provides a class called ExceptionHandler that can manage exceptions raised by Kivy or by your own code. The ExceptionManager class is defined in the “kivy.base” module. You need to import it from “kivy.base” and access the instance that handles Kivy exceptions. You can use this class to add custom handlers for different types of exceptions, or to override the default behavior of Kivy when an exception occurs. For example, you can use the handle_exception method to log the exception, show a message to the user, or exit the app gracefully. from kivy.base import ExceptionHandler, ExceptionManager from logging import Logger class handler(ExceptionHandler): def handle_exception(self, inst): Logger.exception(”Exception caught by ExceptionHandler”) return ExceptionManager.PASS ExceptionManager.add_handler(handler()) A handler function that takes the exception as an argument and returns one of the following values − ExceptionManager.PASS − The exception should be ignored as it was handled by the handler. ExceptionManager.RAISE − The exception should be re-raised. ExceptionManager.USER_HANDLED − The exception was handled by the user and should not be logged. You can also use the handle_exception method to manually handle an exception using the registered handlers. Kivy – Resources Management The “kivy.resources” module includes the functionality to for searching for specific resources across a list of paths particularly if you application deals with multiple paths and projects. When Kivy looks for any resource such as an image file, or a “kv” file, it searches through a predetermined set of folders. You can modify this folder list using the resource_add_path() and resource_remove_path() functions. If you want to use any alternative for the default style.kv or data/defaulttheme0.png you can add the path to your preferred alternatives via the resource_add_path() method. Following functions are defined in the “kivy.resources” module − resource_add_path(path) − Add a custom path to search in. resource_find(filename, use_cache=False) − Search for a resource in the list of paths. Find results are cached for 60 seconds. This can be disabled using use_cache=False. resource_remove_path(path) − Remove a search path. Kivy – Weak Proxy Python uses reference counting algorithm for garbage collection, by keeping count of how many objects are referencing a certain object. If the garbage collector finds that an object is referenced by another object, it can”t be garbage collected. If the counter reaches zero, the garbage collector will free that object. A weak reference is a reference that does not protect the object from getting garbage collected. To create weak references, Python has provided us with a module named weakref. Kivy defines WeakProxy class in kivy.weakproxy module. In order to allow garbage collection, the WeakProxy class provides weak references to objects. It effectively enhances the weakref.proxy by adding comparison support. Kivy – Context The Kivy objects Clock, Cache and Builder are global objects. To use them in the context of the present application you will have to register it. The kivy.context module defines a Context class, which inherits the properties of Python”s built-in dict class. In addition to the dict methods, we have the following functions defined in this module − get_current_context() − Return the current context. egister_context(name, cls, *args, **kwargs) − Register a new context. Print Page Previous Next Advertisements ”;
Kivy – File Syntax
Kivy – File Syntax ”; Previous Next Kivy framework provides a concise and declarative approach to define the widget structure and appearance, with the use of Kivy Language (also known as Kv language). It is a declarative language, used exclusively for building user interfaces in Kivy applications. Its main advantage is that you can separate the UI design from the application logic written in Python. The UI design is defined in a text file which must have a “.kv” extension. It contains the hierarchical sequence of widgets in the application window. The file adapts a tree-like structure, showing the parent-child-sibling relationship among the widgets. Below each widget, its properties, events and event handlers are specified. The kv design language stipulates the following conventions while creating a “.kv” file, so that Python and the Kivy framework can identify and load the appropriate widget structure − Name of the file must be in lowercase It must match with the main class in your application. This class is inherited from the App class. If the name of the class ends with “app” or “App” (for example, HelloApp), the “.kv” file must exclude “app” from its name. It means, for HelloApp class, the name of the “.kv” file must be “hello.kv”. The “.kv” file must be in the same folder in which the Python application file (.py) is present. While using the “.kv” file, the App class doesn”t override the build() method. Declaring a class simply with a pass statement is enough. When the run() method is invoked, Kivy automatically loads the UI from the respective “.kv” file. Let us first remove the build() method from the HelloApp class − Example from kivy.app import App class HelloApp(App): pass app = HelloApp() app.run() The User interface is defined in “hello.kv” file in the same folder. We have a top level BoxLayout with vertical orientation, under which two labels are placed. Save the following script as “hello.kv” file BoxLayout: orientation: ”vertical” Label: text: ”Python Kivy Tutorial” font_size: ”30pt” Label: text: ”From TutorialsPoint” font_size: ”50” color: (1,0,0,1) Now, if you run the “hello.py” program, it will produce the following output − Output In latter chapters, we shall learn how to add event handlers to the widgets in the “.kv” file. Print Page Previous Next Advertisements ”;
Kivy – Inputs
Kivy – Inputs ”; Previous Next The Kivy framework is equipped to receive and process different types of inputs from mouse, touchscreen, gyroscope, accelerometer, etc. Most of the times, Kivy automatically detects available hardware. However, if you want to support custom hardware, you will need to configure kivy accordingly. All the events generated by different input sources are represented by corresponding event classes. The MotionEvent is the base class used for events provided by pointing devices – both touch and non-touch events. Touch events − a motion event that contains at least an X and Y position. All the touch events are dispatched across the Widget tree. No-touch events − An example of non-touch event is the accelerometer as it is a continuous event, without position. It never starts or stops. These events are not dispatched across the Widget tree. Kivy applies post-processing to the input and analyzes it to make meaningful interpretations like − Is it a Double/triple-tap detection? (according to a distance and time threshold) Making events more accurate when the hardware is not accurate Reducing the amount of generated events if the native touch hardware is sending events with nearly the same position After processing, the motion event is dispatched to the Window. if it”s only a motion event, it will be dispatched to on_motion(). On the other hand, if it”s a touch event, the (x,y) position of the touch (0-1 range) will be scaled to the Window size (width/height), and dispatched to − on_touch_down() on_touch_move() on_touch_up() Example In the following example, we”ve defined a new class, called widget, which inherits from Widget. We need to import the Widget class with the following statement − from kivy.uix.widget import Widget There are three methods in the widget class − on_touch_down − It is the initial press. on_touch_move − It is the movement following and while there is a press. on_touch_up − It is the “release” of a press. class widget(Widget): def on_touch_down(self, touch): print(“Down:”,touch) def on_touch_move(self, touch): print(“Move:”,touch) def on_touch_up(self, touch): print(“UP!”,touch) Next, the build() method of App class, returns the widget() object. class MotionApp(App): def build(self): return widget() You can test the code by clicking and dragging on the screen. You should see the mouse”s location for all the movement and pressing you do. Here is the complete code. You can save and run it − from kivy.app import App from kivy.uix.widget import Widget from kivy.config import Config # Configuration Config.set(”graphics”, ”width”, ”720”) Config.set(”graphics”, ”height”, ”400”) Config.set(”graphics”, ”resizable”, ”1”) class widget(Widget): def on_touch_down(self, touch): print(“Down:”,touch) def on_touch_move(self, touch): print(“Move:”,touch) def on_touch_up(self, touch): print(“UP!”,touch) class MotionApp(App): def build(self): return widget() if __name__ == ”__main__”: MotionApp().run() Output The output is an empty application window without any UI widgets in it. Click with the mouse anywhere in the window. Both the “on_touch_down” and “on_touch_up” events will be captured, showing the location of the mouse touch as follows − Down: <MouseMotionEvent spos=(0.4228094575799722, 0.38596491228070173) pos=(304.0, 154.0)> UP! <MouseMotionEvent spos=(0.4228094575799722, 0.38596491228070173) pos=(304.0, 154.0)> Down: <MouseMotionEvent spos=(0.5730180806675939, 0.5137844611528822) pos=(412.0, 205.0)> UP! <MouseMotionEvent spos=(0.5730180806675939, 0.5137844611528822) pos=(412.0, 205.0)> Down: <MouseMotionEvent spos=(0.2517385257301808, 0.5588972431077694) pos=(181.0, 223.0)> UP! <MouseMotionEvent spos=(0.2517385257301808, 0.5588972431077694) pos=(181.0, 223.0)> The spos property of the MouseMotionEvent gives a relative location in the 0-1 coordinate system. The bottom-left corner of the application window corresponds to (0,0) and right-up corner corresponds to (1,1) The pos property shows the actual coordinates where the mouse was clicked. In the above example, it is 378.85 to right and 281.39 pixels upwards from the (0,0) position. Keep the mouse pressed and move it across the window, you will get the instantaneously changing values of the spos and pos properties. For example − Move: <MouseMotionEvent spos=(0.41863699582753827, 0.5338345864661654) pos=(376.3546592489569, 266.38345864661653)> Move: <MouseMotionEvent spos=(0.4172461752433936, 0.531328320802005) pos=(375.1043115438108, 265.1328320802005)> Move: <MouseMotionEvent spos=(0.41585535465924894, 0.5288220551378446) pos=(373.8539638386648, 263.88220551378447)> Event Profiles Based on the input provider and the type of the hardware being used, the event profile contains more information about the input event. The profile is a device specific property if the MotionEvent object. For example, a touch input has an (x,y) position, but might also have pressure information, blob size, an acceleration vector, etc. By adding the following statement in the touch_down event handler, we can find out the features supported by the current device. def on_touch_down(self, touch): print(touch.profile) The output will depend on the type of device. It could be − [”pos”, ”button”] Or, [”pos”, ”angle”] Profile Values The following are some of the profile values supported by default. Sr.No Profile value & Description 1 Angle 2D angle. Accessed via the “a” property. 2 Button Mouse button (”left”, ”right”, ”middle”, ”scrollup” or ”scrolldown”). Accessed via the button property. 3 Markerid Marker or Fiducial ID. Accessed via the fid property. 4 Pos 2D position. Accessed via the x, y or pos properties. 5 pos3d 3D position. Accessed via the x, y or z properties. 6 Pressure Pressure of the contact. Accessed via the pressure property. 7 Shape Contact shape. Accessed via the shape property. Touch Shape In Kivy, the area of interaction during touch event is represented by the term “touch shape”. It refers to the geometric shape used to represent a touch or touch event on the screen. If the touch has a shape, it will be reflected in the ”shape” property. Different touch shapes supported by Kivy are ellipse, rectangle, circle and square. Double / Triple Tap In the context of multi-touch devices, a double tap is the
Kivy – Round Buttons
Kivy – Round Buttons ”; Previous Next All the widgets in Kivy framework are rectangular in shape. A button object always has right-angled corners. Hence, creating buttons with rounded corners doesn”t have a straightforward solution, however we can achieve it by a couple of tricks. Using Image as a Button We can define a class which extends ButtonBehavior mixin and Image class. Using any photo editor, create an elliptical shape looking like a round button, and use it as source property of Image object. You can override the on_press() method of ButtonBehavior class that lets the image be used as a button. from kivy.uix.behaviors import ButtonBehavior from kivy.uix.image import Image class imgbtn(ButtonBehavior, Image): def __init__(self, **kwargs): super(imgbtn, self).__init__(**kwargs) self.source = ”hello.png” self.pos_hint= {”center_x”:.5, ”center_y”:.6} def on_press(self): print(“Button pressed”) We can now use imgbtn object in a Kivy App. KivyMD Buttons Using KivyMD extension, we can design more attractive interfaces. KivyMD is a collection of Material Design widgets, to be used in a Kivy app. The KivyMD library provides different button objects with rounded corners. MDRoundFlatButton MDRoundFlatIconButton MDFillRoundFlatButton MDFillRoundFlatIconButton First, install the KivyMD extension (ensure that Kivy framework is installed earlier) pip3 install KivyMD The App class must be a subclass of MDApp class instead of App class. In this example, we will use MDRoundFlatButton class. Most of its properties are the same as Kivy Button. from kivymd.app import MDApp from kivymd.uix.button import MDRoundFlatButton btn = MDRoundFlatButton( text= ”Hello Python”, font_size= 20, size_hint= (.3, .1), pos_hint= {”center_x”:.5, ”center_y”:.3}, line_width=3 ) Example In the following example, we have a MDApp class. The build() method puts an image button and a MDRoundButton object in the application window. from kivymd.app import MDApp from kivy.core.window import Window from kivy.uix.floatlayout import FloatLayout from kivy.uix.image import Image from kivy.uix.behaviors import ButtonBehavior from kivymd.uix.button import MDRoundFlatButton Window.size = (720, 300) class imgbtn(ButtonBehavior, Image): def __init__(self, **kwargs): super(imgbtn, self).__init__(**kwargs) self.source = ”btnnormal.png” self.pos_hint= {”center_x”:.5, ”center_y”:.6} def on_press(self): print(“Button pressed”) class ButtonApp(MDApp): def build(self): flo = FloatLayout() self.btn1 = imgbtn() self.btn2 = MDRoundFlatButton( text= ”Hello Python”, font_size= 20, size_hint= (.3, .1), pos_hint= {”center_x”:.5, ”center_y”:.3}, line_width=3 ) flo.add_widget(self.btn1) flo.add_widget(self.btn2) return flo if __name__ == ”__main__”: ButtonApp().run() Output Run the application. You should get the following output, having rounded buttons. Using Canvas In Kivy, canvas is the root object for drawing by a widget. To simulate a Label to work as a circular button, we define a class that extends ButtonBehavior and a Label. The “kv” file defines the structure of this object as − <RoundCorneredButton>: canvas: Color: rgb: (1, 0, 0, 1) if self.state == ”normal” else (0, 0, 0, 1) RoundedRectangle: size: (self.size) pos: (self.pos) radius: [200, ] on_release: print(“This is the button made up by the canvas”) The class definition is as follows − class RoundCorneredButton(ButtonBehavior, Label): pass Example We shall use the above class and the kv design in the following App code − from kivy.app import App from kivy.uix.label import Label from kivy.config import Config from kivy.uix.button import ButtonBehavior from kivy.graphics import Rectangle, Color # Configuration Config.set(”graphics”, ”width”, ”720”) Config.set(”graphics”, ”height”, ”300”) Config.set(”graphics”, ”resizable”, ”1”) from kivy.app import App class RoundCorneredButton(ButtonBehavior, Label): pass class HelloApp(App): def build(self): return RoundCorneredButton() HelloApp().run() Output Run the code now. You will get a button with a circular shape, as shown here − Print Page Previous Next Advertisements ”;