-
-
Save ooohiroyukiooo/7d81b6dc95d128c49865bc5ed664b2a2 to your computer and use it in GitHub Desktop.
Hybrid Kivy and GTK application
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#: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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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