質問は少しあいまいです。私は以下でより良く説明しようとします:
私のアプリ(python/gtk)は主にインジケーターです。このインジケータを使用して、メインウィンドウの表示/非表示を選択できます。
アプリの新しいインスタンスを開こうとすると、アプリが既に実行されているかどうかを確認するために作成しました。その場合、アプリを実行しようとして中止されます。
今、私はそれを調整したいので、中止する前に、すでにアクティブなアプリのメインウィンドウを前面に持って来たいです。このウィンドウが現在開かれていない場合でも。
私の質問は、新しいアプリから既にアクティブなアプリの(グローバル?)変数/インスタンスを取得するにはどうすればよいと思いますか? (したがって、メインウィンドウを前面に表示できます)
編集:
APIでこのメソッドを見つけました: GtkWindow-set_startup_id() 。
通常、起動識別子は自動的に管理されるため、この関数は他のプロセスからフォーカスを移動するなどの特別な場合にのみ使用する必要があります。
したがって、これは、別のプロセスからウィンドウにフォーカスを移動できるようにする必要があることを意味します。しかし、このIDはどのように取得できますか?そして、このIDをどのように使用してフォアグラウンドに持ってくるのでしょうか?
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()
上記のコードのさらなる改訂については、次の要点を参照してください。
まず、たくさんの方法があると言ってみましょう。通常、プログラムの起動時にトークン/識別子を設定するため、後のインスタンスはそのトークンの存在を検索できます。
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()
を呼び出す必要があります。
これが探しているIDかどうかわからない:
アプリケーションに移動するか、System Monitor
を押すか、端末CTRL+ALT+DEL
を入力して、gnome-system-monitor
を開きます。
トップバーのView
タブに移動します。 [All Processes
]および[依存関係]を選択します。 Edit
タブのトップバーに移動し、Preferences
を開きます。
Processes
タブのInformation Fields
で、ID
を選択します。
次に、リストからプログラムを見つけてください。幸運を!