Domanda

Voglio fare un programma PyQt4 che supporta i plugin. Fondamentalmente voglio che l'utente sia in grado di scrivere sottoclassi QWidget in PyQt4 e aggiungere / rimuovere dal finestra principale dell'applicazione tramite una GUI. Come avrei fatto che, in particolare il meccanismo di plug-in?

È stato utile?

Soluzione

In primo luogo, utilizzare un QFileDialog o più comodamente la funzione statica QFileDialog.getOpenFileName per lasciare che il all'utente di scegliere il file .py vogliono "plug in" GUI.

Poi, se si desidera consentire l'importazione del plugin dal ovunque sul disco (al contrario di, da specifiche directory precedentemente aggiunti alla tua sys.path, ad esempio attraverso l'PYTHONPATH variabile d'ambiente), è possibile " farlo bene"(una quantità non trascurabile di lavoro), tramite il imp modulo libreria standard di Python), oppure si può "angoli tagliati" come segue (supponendo filepath è il QString con il percorso del file, e che si sta utilizzando un file system / piattaforma con nativamente Unicode nomi di file - altrimenti dovrete aggiungere qualunque .encode la propria piattaforma e filesystem richiedono) ...:

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)

Questa non è thread-safe perché può avere un effetto collaterale sulla sys.path, che è il motivo per cui ho detto che è "angoli di taglio" ... ma poi, che le importazioni siano thread-safe (e importazioni "pulite" da "ovunque ") è davvero il duro lavoro (probabilmente vale la pena una domanda separata se è necessario, dal momento che ha davvero nulla a che fare con l'essenza di questa, o PyQt, ecc).

Una volta che si ha l'oggetto modulo (il risultato da importfrom sopra), vi consiglio:

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)]

Questa funzione restituisce un elenco con tutti i widget di classi (se del caso) definita (al livello superiore) nel modulo amodule.

Che cosa si vuole fare dopo è a voi, naturalmente. Forse si vuole dare un qualche tipo di messaggi di errore se l'elenco è vuoto (o forse anche se ha più di una voce? Altrimenti come si fa a decidere quale widget di classe da utilizzare?), Oppure creare un'istanza della classe widget di (quante volte? a che coordina e così via -?. domande solo tu puoi rispondere) e mostrare i conseguenti widget di (s) nel punto appropriato (s) sulla vostra finestra

Altri suggerimenti

Avere una directory per i plugin, definire un'interfaccia per i plugin, e camminare la directory di importarli.

Non ho mai fatto questo in Python, ma in C il modo in cui l'ho fatto è stato quello di definire un numero di funzioni che il plugin necessario per attuare. Gli elementi chiave di base che sono necessari è il nome delle cose nel plug-in (in modo da poterli visualizzare nel interfaccia utente in modo che l'utente li può istanziare) e una fabbrica per creare realmente le cose. Suppongo che in Python sarebbe abbastanza banale da fare solo quelli come uno dict che si può tornare dal modulo.

es. dichiarano che tutti i plugin devono all'autore una funzione chiamata GetPluginInfo (), che restituisce un dizionario di nome:. mappature di classe

In realtà, ora che ci penso si potrebbe probabilmente solo importare il file e il look per le classi che sono sottoclassi di qualsiasi che ti interessano e non richiede alcuna API esplicita essere implementato. Non ho fatto un sacco di che ma fondamentalmente si piacerebbe camminare dir del modulo () e test per vedere se ogni cosa è una sottoclasse di QWidget (per esempio).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top