Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Hybrid Kivy and GTK application
#:kivy 1.8.0
<Root>:
orientation: "vertical"
Button:
text: "Start GTK thread" if not app.gtk_started else "Stop GTK thread"
on_release: app.start_gtk_thread()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.properties import BooleanProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivy.clock import mainthread
from gi.repository import Gtk, GObject
from threading import Thread
class MyWindow(Gtk.Window):
def __init__(self):
window = Gtk.Window.__init__(self, title="Secondary GTK thread")
self.box = Gtk.VBox()
self.add(self.box)
button1 = Gtk.Button(label="Add button in Kivy app")
button1.connect("clicked", self.add_kivy_button)
self.box.add(button1)
button2 = Gtk.Button(label="Remove button from Kivy app")
button2.connect("clicked", self.remove_kivy_button)
self.box.add(button2)
def add_kivy_button(self, widget):
App.get_running_app().add_button("Hello world!!!")
def remove_kivy_button(self, widget):
App.get_running_app().remove_button(0)
class GTKThread(Thread):
def run(self):
self.win = MyWindow()
self.win.connect("delete-event", Gtk.main_quit)
self.win.show_all()
GObject.threads_init()
Gtk.main()
def stop(self):
Gtk.main_quit()
class Root(BoxLayout):
pass
class KivyGTKApp(App):
gtk_started = BooleanProperty(False)
def build(self):
return Root()
def start_gtk_thread(self, *args):
if self.gtk_started:
# Stopping the mainloop doesn't work reliably. Avoid doing it.
self.gtk.stop()
self.gtk_started = False
else:
self.gtk = GTKThread()
# Set this if you want GTK to (abruptly) shut down with Kivy
# daemon = True
# You can probably start more than one thread, if you keep track
# of every instance
self.gtk.start()
self.gtk_started = True
# This works without the decorator. However you should always
# use it if you plan to call a method that does GUI stuff from
# another thread, as it's not thread-safe to do so.
# Another way to do it is to use Clock to schedule a call to
# the method.
#@mainthread
def add_button(self, text):
b = Button(text=text, size_hint_y=None, height="30dp")
self.root.add_widget(b)
#@mainthread
def remove_button(self, index):
if len(self.root.children) > 1:
self.root.remove_widget(self.root.children[index])
if __name__ == "__main__":
KivyGTKApp().run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.