GUI non creata da un software che carica il mio come plugin

angeloulivieri

Utente Attivo
8 Set 2009
71
0
0
Salve a tutti,
ho un problema con una gui Java. Ho una classe GraphCreate e una GraphCreateGUI.
GraphCreate fa delle operazioni attivabili da GraphCreateGUI. Tutto è all'interno di un package che ho inserito come plugin in un software (Cytoscape).
Se faccio partire il programma da compilatore (Eclipse) funziona. Ma quando lo inserisco come plugin la GUI non parte ( Viene creato un frame vuoto e senza nome e si blocca il programma.
Scrivo sotto le funzioni che ho usato per inserirlo come plugin e richiamarlo dal menù del sw (sono istruzioni ufficiali del softare). Credo che sia un problema di Java però.. nel senso che non ho richiamato bene qualcosa. Perché Cytoscape in precedenza era riuscito ad attivare la GUI (quando ancora non avevo inserito il plugin richiamabile dal menù)

Scusate per i commenti in inglese!
This is the constructor that adds a menu item (It works! ):
public GraphCreate() {
//create a new action to respond to menu activation
GraphCreateAction action = new GraphCreateAction();
//set the preferred menu
action.setPreferredMenu("Plugins");
//and add it to the menus
Cytoscape.getDesktop().getCyMenus().addAction(action);

}

/ This class gets attached to the menu item.
public class GraphCreateAction extends CytoscapeAction {
private static final long serialVersionUID = 1L;//Version Number
* The constructor sets the text that should appear on the menu item.
*/
public GraphCreateAction() {
super("GraphCreate");
}

/**
* This method is called when the user selects the menu item.
*/
public void actionPerformed(ActionEvent ae) {
gui=new GraphCreateGUI();//I don't know if the problem is here!
startOperationsNewGUI();
}
}

public static void startOperationsNewGUI(){
try{
//This while says to the program to wait until a start button in the gui is pressed
while(true){
while(!gui.start){
Thread.sleep(100);

}
gui.start=false;
inizializza(gui);//Start computations using parameters on the GUI
}
}
catch(InterruptedException exc){
}

}
 

angeloulivieri

Utente Attivo
8 Set 2009
71
0
0
allora ragazzi... ci ho sbattuto un pò la testa e il problema credo sia dovuto alla gestione dei processi e thread che guidano il plugin con la GUI.

Spiego meglio:
Creo un .jar e lo metto nella cartella plugin del software (Cytoscape). Nel costruttore indico il menù in cui deve comparire la voce del mio programma.
Nella classe principale del mio programma (graphCreate) ho un listener che quando clicchi nell'apposito menù in Cytoscape fa delle cose. Per come l'ho impostato io succede questo.
La GUI si chiama GraphCreateGUI e l'ho creata con Eclipse e Visual Editor. Dunque la crea lui stesso come thread. La GUI è semplicemente l'impostazione di alcuni parametri e un pulsante Start.
Allo start corrisponde un listener che mi deve avviare la computazione in GraphCreate.
Cioè.. è un mezzo casino da implementare!
GraphCreate e la GUI devono essere due thread ? Come li implementereste?
Chi chiama cosa? Come permetto alla GUI di aprirsi e aprire Graph Create che fa partire la computazione solo dopo la pressione di Start?
Posso partire da Graph Create o devo creare un'altra classe che istanzia i due separatamente?
...wow sembra un esercizio sulla programmazione a oggetti!
 

angeloulivieri

Utente Attivo
8 Set 2009
71
0
0
[RISOLTO]GUI non creata da un software che carica il mio come plugin

Salve a tutti.... risolto e spiego come... magari diffondo un pò di competenze! :D

Creare una GUI in Java non è per niente una cosa facile nè intuitiva. Anche se la classe AWT e Swing forniscono metodi che riescono a mettere in pratica ogni nostro desiderio. Nel nostro caso si vuole usare l'interfaccia come semplice punto di ingresso a un programma, portando dei parametri.

Tralasciando i metodi per implementare bottoni, textArea e textField (utilissimi questi due per mostrarci lo stato delle operazioni quando il System.out.println non ce l'abbiamo) passiamo a come gestire tramite thread l'esecuzione.

Nel nostro caso il software è un plugin per un altro sw, chiamato Cytoscape. Questo programma ha le sue cassi e il suo modo di installare i plugin. Che in questa sede tralasciamo, una volta aggiunto il nostro programma al menù del sw.

Sono state create 4 classi in particolare: GraphCreate, GraphCreateGUI, Semaforo e GraphCreateMain.
- GraphCreate gestisce le operazioni. Nel nostro caso, a partire da alcuni file che può scegliere l'utente, crea un grafo tramite alcuni parametri da prendere nella GUI. GraphCreate è un thread e dunque estende la classe Runnable e implementa il metodo Run
- GraphCreateGUI gestisce l'interfaccia tramite un frame e un pannello in cui sono inseriti bottoni per l'apertura dei file e comboBox per la scelta dei parametri. Anche questa classe deve essere un thread e estendere Runnable etc..
- Semaforo è una semplice classe che gestisce una variabile condivisa. Il cui accesso non deve essere per forza sincronizzato.
- GraphCreateMain è la classe di partenza che crea un nuovo item nel menù del programma. Questo avviene tramite funzioni di Cytoscape che in questa sede tralascio.

Vediamo il tutto come funziona:
alla pressione del tasto dal menù del software di partenza viene lanciato GraphCreateMain. Esso crea: il Semaforo (un oggetto che sarà condiviso), istanzia un GraphCreateGUI e un GrapphCreate. L'ordine è precisamente questo perché al costruttore della GUI dobbiamo passare il semaforo condiviso appena creato e al costruttore di GraphCreate dobbiamo passare sia il semaforo che la GUI.

All'interno della GUI il costruttore chiama il metodo Run in cui costruiamo il pannello e settiamo il valore del semaforo a 0 (libero) che significa che la GUI è stata creata. All'interno dell'oggeto GraphCreate il costruttore chiamerà subito un metodo che mette l'oggetto in attesa che il semaforo sia libero (=0) e che il bottone Start, all'interno dell'interfaccia grafica, sia stato premuto.
Lo Start è un attributo della GUI, che ho realizzato come oggetto int di default impostato a zero.

Quando il bottone è premuto il listener mette start=1 e l'oggetto GraphCreate si sveglia dal sonno. (Questo meccanismo può essere implementato tramite un altro semaforo e la sincronizzazione, ma IMHO non è necessario). Quando il GraphCreate si sveglia lancia subito un metodo che prende tutti i necessari parametri dalla GUI e comincia l'elaborazione. Una volta finita, azzeriamo tutti i campi necessari nella GUI (sempre dall'oggetto GraphCreate, magari realizzando un metodo nella GUI che azzera tutto) e risettiamo il valore start=0. Il GraphCreate tornerà nel loop (che nel mio caso ho scelto fose infinito - while(true) ) e si metterà di nuovo in attesa dell'interfaccia.

Ci si potrebbe chiedere se, visto l'uso dello Start, ci fosse veramente bisogno della classe Semaforo. Il problema è che anche se la GUI viene creata prima dell'oggetto GraphCreate, essendo due thread, non sappiamo quale dei due partirà prima. Dunque GraphCreate potrebbe trovare GraphCreateGUI.start=null perché non è ancora stato creato, provocando un errore.
Questa è la soluzione migliore, e anche più veloce, che ho saputo trovare.

Spero possa tornare utile a qualcuno e di non irritare troppo i Javisti Senior convinti... :D:mavieni: