プラグインをサポートする PyQt4 プログラムを作成したいと考えています。基本的に、ユーザーが PyQt4 で QWidget サブクラスを記述し、GUI を介してメイン アプリケーション ウィンドウから追加/削除できるようにしたいと考えています。特にプラグインメカニズムはどうすればいいですか?
2 に答える
まず、QFileDialogまたはより便利な静的関数QFileDialog.getOpenFileName.py
を使用して、ユーザーが GUI に「プラグイン」するファイルを選択できるようにします。
次に、ディスク上のどこからでもプラグインをインポートできるようにしたい場合(sys.path
たとえば、環境変数を介して以前に に追加された特定のディレクトリからではなくPYTHONPATH
)、「正しく行う」ことができます (無視できない量の作業)、標準の Python ライブラリのimpモジュールを介して)、または次のように「手抜き」を行うことができます (がファイルへのパスであり、ネイティブの Unicode ファイル名を持つファイルシステム/プラットフォームを使用していると仮定します-それ以外の場合filepath
)プラットフォームとファイルシステムに必要QString
なものを追加する.encode
必要があります)...:
import sys, os
def importfrom(filepath):
ufp = unicode(filepath)
thedir, thefile = os.path.split(ufp)
if sys.path[0] != thedir:
sys.path.insert(0, thedir)
themodule, theext = os.path.splitext(thefile)
return __import__(themodule)
に副作用がある可能性があるため、これはスレッドセーフではありません。そのため、sys.path
「手抜きをしている」と言いました...しかし、スレッドセーフなインポート(および「どこでも」からの「クリーンな」インポート)を行うことは本当に大変な作業です(おそらく、必要に応じて別の質問をする価値があります。これは、この質問の要点や PyQt などとはあまり関係がないためです)。
モジュール オブジェクト (importfrom
上記の結果) を取得したら、次のことをお勧めします。
from PyQt4 import QtGui
import inspect
def is_widget(w):
return inspect.isclass(w) and issubclass(w, QtGui.QWidget)
def all_widget_classes(amodule):
return [v for n, v in inspect.getmembers(amodule, is_widget)]
これは、 module で (最上位で) 定義されているすべてのウィジェットクラスamodule
(存在する場合) のリストを返します。
もちろん、次に何をしたいかはあなた次第です。おそらく、リストが空の場合 (または複数の項目がある場合) に何らかのエラー メッセージを表示したり、使用するウィジェット クラスをどのように決定したりするか、またはウィジェット クラスをインスタンス化します (何回?どの座標で?など -- あなただけが答えられる質問) を表示し、結果のウィジェットをウィンドウの適切な場所に表示します。
プラグイン用のディレクトリを用意し、それらのプラグイン用のインターフェースを定義し、それらをインポートするディレクトリを歩きます。
Python でこれを行ったことはありませんが、C で行った方法は、プラグインが実装する必要がある多くの関数を定義することでした。必要な基本的な重要な要素は、プラグイン内のモノの名前 (ユーザーがそれらをインスタンス化できるように UI に表示できるようにするため) と、実際にモノを作成するためのファクトリです。Python では、モジュールから返すことができる 1 つの dict としてそれらを行うのはかなり簡単だと思います。
たとえば、すべてのプラグインが、name:class マッピングの辞書を返す GetPluginInfo() という関数を作成する必要があることを宣言します。
実際に考えてみると、おそらくファイルをインポートして、気になるもののサブクラスであり、明示的な API を実装する必要のないクラスを探すことができます。私はその多くを行っていませんが、基本的には、モジュールの dir() を調べて、それぞれが QWidget のサブクラスであるかどうかをテストします (たとえば)。