0

So, I'm depeloping a Python/GTK app which, after showing an assistant, it hides the assistant's window and runs an external app. The problem is that window.hide() doesn't works if, after the command, there's an app call using os.system() or call(). When the call is done, the window seems to hang and it doesn't disappears until all the calls are done. So... what can be done?

4
  • We are making a client/server app, and we have some troubles with gtk, it seams to lock our thread in the Gtk.main(). So we might be interested about using your solution, but where did you put those lines ? Jun 24, 2012 at 21:32
  • Yep, I had the same problem with an app which I've done. Let me check...
    – Xerz
    Jun 24, 2012 at 21:43
  • OK, it seems to fix the hanged thread error. Just insert it before the code which causes the problem, and done! :)
    – Xerz
    Jun 24, 2012 at 21:49
  • Wait... I'm not sure, try it anyway.
    – Xerz
    Jun 24, 2012 at 21:52

3 Answers 3

1

After some time googling possible solutions, I've found this simple answer, which waits to GTK until it finished all its working tasks. You may think that makes the app slower, but the difference is almost unexistent.

This workaround can be used with any version of Python. It works with PyGTK and with GTK+3 (with GTK+3, change gtk per Gtk... :P )

while gtk.events_pending():
    gtk.main_iteration()

Just add this before the code which causes the problem... and done! :)

0

In my applications I tend to replace os.system() and subprocess.call() with subprocess.Popen (see https://stackoverflow.com/a/636570/2372604).

1
  • I've been using subprocess.Popen recently and it's really delightful. If only I knew back then!
    – Xerz
    Jan 27, 2016 at 9:25
0

Using openSUSE Leap 15.5, Python 3.6.15 and GTK 4.6.9 here.

In short, the idea is: hide the window by calling Gtk.Window.hide(), then start a thread using threading.Timer() (non-blocking). In that thread, run the external app with subprocess.run() (blocking) then show the window again with Gtk.Window.show().

Here is a complete working example:

#!/usr/bin/python3

import subprocess
import sys
import threading
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gdk


class MainWindow(Gtk.ApplicationWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.set_default_size(600, 250)
        self.set_title('MyApp')

        self.box1 = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        self.set_child(self.box1)

        self.button = Gtk.Button(label='Launch')
        self.button.connect('clicked', self.on_button_clicked)
        self.box1.append(self.button)

    def on_button_clicked(self, button):
        self.hide()
        t = threading.Timer(1, self.launch)
        t.start()

    def launch(self):
        subprocess.run(['gnome-calculator'])
        self.show()


class MyApp(Gtk.Application):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.connect('activate', self.on_activate)

    def on_activate(self, app):
        self.main_window = MainWindow(application=app)
        self.main_window.present()


app = MyApp(application_id='com.example.MyApp')
app.run(sys.argv)

These may be useful:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .