]> git.jsancho.org Git - blog.git/commitdiff
New post "Designing forms with Python and Kivy"
authorJavier Sancho <jsf@jsancho.org>
Fri, 3 Aug 2018 10:35:22 +0000 (12:35 +0200)
committerJavier Sancho <jsf@jsancho.org>
Fri, 3 Aug 2018 10:35:22 +0000 (12:35 +0200)
images/form.jpg [new file with mode: 0644]
posts/20180802-kivyforms.html [new file with mode: 0644]

diff --git a/images/form.jpg b/images/form.jpg
new file mode 100644 (file)
index 0000000..f77f6ec
Binary files /dev/null and b/images/form.jpg differ
diff --git a/posts/20180802-kivyforms.html b/posts/20180802-kivyforms.html
new file mode 100644 (file)
index 0000000..692e5cb
--- /dev/null
@@ -0,0 +1,95 @@
+title: Designing forms with Python and Kivy
+date: 2018-08-03 13:43
+tags: form, python, kivy, kivyforms
+---
+<div>
+  <a href="images/form.jpg"><img src="images/form.jpg" alt="form" width="300" height="200" class="image-right" /></a>
+
+  <p>There are many libraries to create graphical interfaces with Python. For example, I tried with <a href="https://wxpython.org/">wxPython</a>, <a href="https://riverbankcomputing.com/software/pyqt/">PyQt</a> and <a href="https://kivy.org/">Kivy</a>. The latter is the one I liked the most for a number of reasons:</p>
+
+  <ul>
+    <li>It's multiplatform and works in GNU/Linux, Windows, OS X, Android, iOS and Raspberry Pi. I've only tried the first two, but I've been able to verify that it's designed for use with keyboard and mouse or with touch screens.</li>
+    <li>It's not based on the platforms native widgets but has its own, so the applications look the same on all platforms.</li>
+    <li>It's fast; the graphics engine works on OpenGL ES 2 and many parts are written with Cython.</li>
+    <li>You can design the interfaces directly with Python or using Kv language.</li>
+    <li>It's a relatively new project, and well maintained.</li>
+    <li>Good documentation and many examples.</li>
+  </ul>
+
+  <p>I'm working on an apps development framework, so I need developers to be able to design forms quickly, WYSIWYG way, and they can also include their own themes, colors, etc. Thanks to <a href="https://kivy.org/docs/guide/lang.html">Kv language</a>, this task is easier for me. It's something similar to QML in Qt, and allows to save compositions in text files that can be loaded later by the application, without having to modify any code.</p>
+
+  <p>For example, the <a href="https://kivy.org/">Kivy</a> <i>Hello World</i> would be:</p>
+
+  <pre>
+    # main.py file
+    from kivy.app import App
+
+    class TestApp(App):
+        pass
+
+    TestApp().run()
+
+    # test.kv file
+    Button:
+        text: 'Hello World'
+  </pre>
+
+  <p>To design the forms, I created a widget that provides a canvas, in which it's possible to add buttons, labels, text fields and things like that. The project is called <a href="https://gitlab.com/jsancho/kivyforms">KivyForms</a> and is currently beta. You can also watch a <a href="https://www.youtube.com/watch?v=512Jfl2CUdY">video with an example of using KivyForms</a>. The idea is that the widget has a powerful API to be integrated into any application that needs forms composition.</p>
+
+  <p>Look what the widget contains:</p>
+
+  <pre>
+    class FormCanvas(BoxLayout):
+        def __init__(self, *args, **kwargs):
+            super(FormCanvas, self).__init__(*args, **kwargs)
+
+            self._canvas = StackLayout(
+                orientation='lr-tb',
+                padding=[10, 10, 10, 10],
+                spacing=[10, 10]
+            )
+            super(FormCanvas, self).add_widget(self._canvas)
+  </pre>
+
+  <p>FormCanvas is based on a Kivy BoxLayout, and has a StackLayout inside, where form widgets will be added. The StackLayout allows other widgets to stack without occupying the full size of the screen.</p>
+
+  <pre>
+    def add_widget(self, widget):
+        g = Grabbable(
+            height=self.widgets_height,
+            size_hint=self.widgets_size_hint
+        )
+        g.add_widget(widget)
+        self._canvas.add_widget(g)
+  </pre>
+
+  <p>Each time we add a widget, a <b>Grabbable</b> item is instantiated for containing the widget we want to add. It's this <b>Grabbable</b> item that we really add to the canvas. This allows us to select the widget and move it around the form to design the composition.</p>
+
+  <p>There is a <b>Destination</b> item to indicate where the widget will be placed when the drag operation ends.</p>
+  
+  <pre>
+    class Destination(Label):
+        def __init__(self, **kwargs):
+            super(Destination, self).__init__(**kwargs)
+            self.text = 'Widget goes here'
+            self.color = [1, 1, 0, 1]
+            with self.canvas.after:
+                Color(1, 1, 0, 1)
+                self.box = Line(dash_length=8, dash_offset=4)
+
+        def update_box(self):
+            self.box.points = [
+                self.x, self.y,
+                self.x, self.y + self.height,
+                self.x + self.width, self.y + self.height,
+                self.x + self.width, self.y,
+                self.x, self.y
+            ]
+  </pre>
+
+  <p>This item, which is a simple label with dotted border, is very useful for the developer to be able to place widgets in the right place.</p>
+
+  <p>Finally, it's possible to export the composition to Kv language. KivyForms is in charge of filtering all the <b>Grabbable</b> items and the configuration needed for the design of the form, so we can save the composition directly to a file, ready to be used in our programs.</p>
+
+  <p><a href="https://gitlab.com/jsancho/kivyforms">KivyForms</a> is distributed under <a href="https://opensource.org/licenses/MIT">MIT license</a>. Although I prefer GPL licenses, in this case I have decided to use, for consistency, the same license as Kivy, so you are invited to collaborate on the project.</p>
+</div>