web-dev-qa-db-ja.com

そのアプリの新しいインスタンスを開こうとするときに、既にアクティブなアプリのウィンドウを表示する方法

質問は少しあいまいです。私は以下でより良く説明しようとします:

私のアプリ(python/gtk)は主にインジケーターです。このインジケータを使用して、メインウィンドウの表示/非表示を選択できます。

アプリの新しいインスタンスを開こうとすると、アプリが既に実行されているかどうかを確認するために作成しました。その場合、アプリを実行しようとして中止されます。

今、私はそれを調整したいので、中止する前に、すでにアクティブなアプリのメインウィンドウを前面に持って来たいです。このウィンドウが現在開かれていない場合でも。

私の質問は、新しいアプリから既にアクティブなアプリの(グローバル?)変数/インスタンスを取得するにはどうすればよいと思いますか? (したがって、メインウィンドウを前面に表示できます)

編集:

APIでこのメソッドを見つけました: GtkWindow-set_startup_id()

通常、起動識別子は自動的に管理されるため、この関数は他のプロセスからフォーカスを移動するなどの特別な場合にのみ使用する必要があります。

したがって、これは、別のプロセスからウィンドウにフォーカスを移動できるようにする必要があることを意味します。しかし、このIDはどのように取得できますか?そして、このIDをどのように使用してフォアグラウンドに持ってくるのでしょうか?

6
Nick Lemaire

xubuntixの素晴らしい答え のおかげで、簡単にするモジュールを作成しました:

"""
Allow an application to activate a running instance of itself instead of
starting another instance.
"""

import sys

import gtk
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop

def _get_path(app_id):
    return '/' + app_id.replace('.', '/')

def listen_for_activation(app_id, window):
    """
    Listen for 'activate' events. If one is sent, activate 'window'.
    """
    class MyDBUSService(dbus.service.Object):                                                                                                       
        def __init__(self, window):
            self.window = window

            bus_name = dbus.service.BusName(app_id, bus=dbus.SessionBus())                                                     
            dbus.service.Object.__init__(self, bus_name, _get_path(app_id))

        @dbus.service.method(app_id)                                                                         
        def activate(self):
            print "The process was activated by another instance."
            self.window.present()

    DBusGMainLoop(set_as_default=True)
    _myservice = MyDBUSService(window)

def activate_if_already_running(app_id):
    """
    Activate the existing window if it's already running. Return True if found
    an existing window, and False otherwise.
    """
    bus = dbus.SessionBus()
    try:
        programinstance = bus.get_object(app_id, _get_path(app_id))
        activate = programinstance.get_dbus_method('activate', app_id)
    except dbus.exceptions.DBusException:
        return False
    else:
        print "A running process was found. Activating it."
        activate()
        return True
    finally:
        bus.close()

def test():
    APP_ID = 'com.example.myapp'

    activated = activate_if_already_running(APP_ID)
    if activated:
        sys.exit(0)

    w = gtk.Window()
    b = gtk.Button("Hello!")
    b.set_size_request(200, 200)
    w.add(b)
    w.connect('delete-event', gtk.main_quit)
    w.show_all()

    listen_for_activation(APP_ID, w)

    gtk.main()

if __== '__main__':
    test()

上記のコードのさらなる改訂については、次の要点を参照してください。

1
Noam

まず、たくさんの方法があると言ってみましょう。通常、プログラムの起動時にトークン/識別子を設定するため、後のインスタンスはそのトークンの存在を検索できます。

Dbusを使用する1つの方法を説明します。

概要:

プログラムを起動すると、セッションdbusに一意の名前(たとえば、「org.nicklemaire.myprogram」)で自分自身を登録できます。プログラムのさらなるインスタンスは、そのようなアクセスポイントが既に登録されているかどうかを確認でき、登録されている場合、このdbusアクセスポイントを介してプログラムに何をするかを伝えます(例えば、フォーカスを取得し、ウェブサイトを開き、曲を再生します)。 「firefox askubuntu.com」に似た動作が必要な場合は、おそらく最後の部分が必要です。これは、すでに実行中のインスタンスの新しいタブでこのページを開きます。

コード:

#!/usr/bin/env python                                                                                                                           
import sys                                                                                                                                      
import gtk                                                                                                                                      
import dbus                                                                                                                                     
import dbus.service                                                                                                                             
from dbus.mainloop.glib import DBusGMainLoop                                                                                                    
from multiprocessing import Process                                                                                                             

class MyDBUSService(dbus.service.Object):                                                                                                       
    def __init__(self):                                                                                                                         
        bus_name = dbus.service.BusName('org.nicklemaire.myprogram', bus=dbus.SessionBus())                                                     
        dbus.service.Object.__init__(self, bus_name, '/org/nicklemaire/myprogram')                                                              

    @dbus.service.method('org.nicklemaire.myprogram', in_signature='s')                                                                         
    def startup(self, arg):                                                                                                                     
        print "got the following parameter from another instance:", arg                                                                         

def call_instance():                                                                                                                            
    try:                                                                                                                                        
        bus = dbus.SessionBus()                                                                                                                 
        programinstance = bus.get_object('org.nicklemaire.myprogram',  '/org/nicklemaire/myprogram')                                            
        bus = dbus.SessionBus()                                                                                                                 
        programinstance = bus.get_object('org.nicklemaire.myprogram',  '/org/nicklemaire/myprogram')                                            
        startup = programinstance.get_dbus_method('startup', 'org.nicklemaire.myprogram')                                                       
        try:                                                                                                                                    
            arg = sys.argv[1]                                                                                                                   
        except IndexError:                                                                                                                      
            arg = ""                                                                                                                            
        startup(arg)                                                                                                                            
        print "Another instance was running and notified."                                                                                      
    except dbus.exceptions.DBusException:                                                                                                       
        exit(-1) # process had an error                                                                                                         

if __== "__main__":                                                                                                                      
    p = Process(target=call_instance)                                                                                                           
    p.start() 
    p.join()                                                                                                                                    
    if p.exitcode > 0: # process had an error                                                                                                   
        DBusGMainLoop(set_as_default=True)                                                                                                      
        myservice = MyDBUSService()                                                                                                             
        gtk.main()

テスト:

ターミナルを開き、プログラムを実行します:myprogram.py。現在、実行して2番目のインスタンスの開始を待機させたいため、終了しません。

これを実行します。別のターミナルを開いて、今度は追加の引数myprogram.py askubuntu.comを使用してプログラムを再度実行します。 「別のインスタンスが実行され、通知されました。」と出力されるはずです。最初の端末では、次のような出力が表示されます。「別のインスタンスから次のパラメーターを取得しました:askubuntu.com」

あなたの質問の他の部分:プログラムを上げることはここに記述されています: https://stackoverflow.com/questions/9054462/how-do-i-raise-a-window-that-is-minimized-or- covered-with-pygobject

基本的に、startupメソッドでmywindow.present()を呼び出す必要があります。

1
xubuntix

これが探しているIDかどうかわからない:

アプリケーションに移動するか、System Monitorを押すか、端末CTRL+ALT+DELを入力して、gnome-system-monitorを開きます。

トップバーのViewタブに移動します。 [All Processes]および[依存関係]を選択します。 Editタブのトップバーに移動し、Preferencesを開きます。

ProcessesタブのInformation Fieldsで、IDを選択します。

次に、リストからプログラムを見つけてください。幸運を!

0
David M. Sousa