View Full Version : [JAVA] visualizzare e associare popup all' interno di JMenu
diablo...aka...boss
21-04-2009, 15:56
Cliccando about deve uscire un popup con all' interno delle informazioni
http://img178.imageshack.us/img178/753/28827732.jpg (http://img178.imageshack.us/my.php?image=28827732.jpg)
Il codice che sono riuscito a produrre seguendo il tutorial su java della sun è il seguente:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
public class TheSoundSuite extends JFrame implements ActionListener, ItemListener {
private static final long serialVersionUID = 1L;
JTextArea output;
JScrollPane scrollPane;
String newline = "\n";
public JMenuBar createMenuBar() {
JMenuBar menuBar;
JMenu menu;
JMenuItem menuItem;
//Creo la menu bar e i vari menu.
menuBar = new JMenuBar();
menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_A);
menu.getAccessibleContext().setAccessibleDescription(
"The only menu in this program that has menu items");
menuBar.add(menu);
//a group of JMenuItems
menuItem = new JMenuItem("Open",
KeyEvent.VK_T);
menuItem.setMnemonic(KeyEvent.VK_T); //used constructor instead
menuItem.setAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription(
"This doesn't really do anything");
menu.add(menuItem);
//Build second menu in the menu bar.
menu = new JMenu("Help");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
"This menu does nothing");
menuBar.add(menu);
menuItem = new JMenuItem("About...");
//menuItem.setMnemonic(KeyEvent.VK_B);
menu.add(menuItem);
//menuItem.setMnemonic(KeyEvent.VK_D);
//menu.add(menuItem);
return menuBar;
}
public Container createContentPane() {
//Create the content-pane-to-be.
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setOpaque(true);
//Create a scrolled text area.
output = new JTextArea(5, 30);
output.setEditable(false);
scrollPane = new JScrollPane(output);
//Add the text area to the content pane.
contentPane.add(scrollPane, BorderLayout.CENTER);
return contentPane;
}
public void createPopupMenu() {
JMenuItem menuItem;
//Create the popup menu.
JPopupMenu popup = new JPopupMenu();
menuItem = new JMenuItem("A popup menu item");
menuItem.addActionListener(this);
popup.add(menuItem);
menuItem = new JMenuItem("Another popup menu item");
menuItem.addActionListener(this);
popup.add(menuItem);
//Add listener to the text area so the popup menu can come up.
MouseListener popupListener = new PopupListener(popup);
output.addMouseListener(popupListener);
}
public void actionPerformed(ActionEvent e) {
JMenuItem source = (JMenuItem)(e.getSource());
String s = "Action event detected."
+ newline
+ " Event source: " + source.getText()
+ " (an instance of " + getClassName(source) + ")";
output.append(s + newline);
output.setCaretPosition(output.getDocument().getLength());
}
public void itemStateChanged(ItemEvent e) {
JMenuItem source = (JMenuItem)(e.getSource());
String s = "Item event detected."
+ newline
+ " Event source: " + source.getText()
+ " (an instance of " + getClassName(source) + ")"
+ newline
+ " New state: "
+ ((e.getStateChange() == ItemEvent.SELECTED) ?
"selected":"unselected");
output.append(s + newline);
output.setCaretPosition(output.getDocument().getLength());
}
// Returns just the class name -- no package info.
protected String getClassName(Object o) {
String classString = o.getClass().getName();
int dotIndex = classString.lastIndexOf(".");
return classString.substring(dotIndex+1);
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TheSoundSuite");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TheSoundSuite demo = new TheSoundSuite();
frame.setJMenuBar(demo.createMenuBar());
frame.setContentPane(demo.createContentPane());
//Create and set up the popup menu.
demo.createPopupMenu();
frame.setSize(600, 400);
frame.setVisible(true);
}
public static void main(String[] args) {
/* Schedule a job for the event-dispatching thread:
* creating and showing this application's GUI.
*/
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
class PopupListener extends MouseAdapter {
JPopupMenu popup;
PopupListener(JPopupMenu popupMenu) {
popup = popupMenu;
}
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
}
Però non è proprio quello che mi serve, solo che non riesco a capire come modificarlo. Ora cliccando con il tasto dx in una qualsiasi parte della finestra si apre il popup.
Come faccio ad associare il popup al menu About?
Dove devo inserire ciò che voglio che venga visualizzato all' interno del popup?
Vi ringrazio in anticipo.
Se conoscete un tutorial diverso da quello della sun o qualche esempio ben fatto vi prego di segnalarmelo, ho cercato sul web ma non ho trovato molto.
Oceans11
21-04-2009, 16:29
Forse ti stai confondendo, il "popup" (JPopupMenu) non è la solita finestra che si usa per le informazioni.
Forse dovresti vedere JDialog oppure direttamente JOptionPane.showInformationDialog(...).
Però forse non ho capito io.
Concordo con Oceans.
Per i lettori, il codice postato è un casino. Ma ci sta tutto se è per imparare.
Si tratta semplicemente di:
1. prendere il pulsante del menu a cui vuoi collegare l'apertura della finestra di dialog "About"
2. aggiungerli un ascoltatore di eventi (ActionListener nel nostro caso)
3. nel metodo che gestisce l'evento aprire la finestra di dialogo.
Faccio un esempio rapido che infagotta il codice ancora di più ma è giusto per darti uno spunto.
Nel metodo createMenuBar() prima di "return menuBar" aggiungiamo:
final Component SOURCE= menuItem;
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
javax.swing.JOptionPane.showMessageDialog(SOURCE, "About");
}
});
Cambiando quel che c'è nell'actionPerformed puoi fare cose diverse.
diablo...aka...boss
22-04-2009, 09:28
Ho preso un abbaglio quindi :D
Ok allora adesso guardo JDialog e JOptionPane, e poi dopo che ho risolto vedo/vediamo se riesco a farlo anche nella maniera in qui stavo procedendo adesso.
Vi tengo aggiornati, grazie.
diablo...aka...boss
22-04-2009, 17:01
Ho messo direttamente il codice (prima del return) suggerito da PGI sopra con una leggera modifica per avere anche un titolo
final Component SOURCE= menuItem;
menuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
javax.swing.JOptionPane.showMessageDialog (SOURCE, "The Sound Suite version 0.1\n" + "Autore: XXX yyy" , "About...", JOptionPane.INFORMATION_MESSAGE);
}
});
Aggiungendo sempre lo stesso codice di PGI nel primo codice che ho postato, il risultato che ottengo è il medesimo. Ma sostanzialmente ci sono numerose righe di codice, si corrette, ma che non utilizzo.
dovresti creare separatamente una tua classe che rappresenta la finestrella about attraverso una JDialog. JDialog funziona come JFrame salvo la necessità di avere una finestra a cui agganciarsi. Diciamo che si chiama AboutDialog ed estende JDialog. Bene, nell'actionPerformed diresti:
Frame owner = JOptionPane.getFrameForComponent(SOURCE);
AboutDialog d = new AboutDialog(owner);
d.pack();
d.setVisible(true);
Con un paio di righe in più per centrare la finestra About rispetto al JFrame da cui dipende la la sostanza è quella.
Usando un JDialog o comunque una classe separata eviti di dover impacchettare un bel po' di linee di codice nell'actionPerformed.
Si può fare anche con JOptionPane perchè il secondo argomento del metodo show può essere un Component. Una soluzione sarebbe quindi dire:
JTextArea testo = new JTextArea();
testo.append("autore Gianni Rossi\n");
testo.append("società PimPumPam\n");
testo.append("eccetera");
testo.setEditable(false);
JOptionPane.showMessageDialog(SOURCE, testo, "About" eccetera);
ma come finestra Abount è molto "cheap" :D. Si può fare qualcosa di esteticamente più accattivamente.
diablo...aka...boss
22-04-2009, 17:23
Mi sembra di capire che utilizzando anche JDialog venga qualcosa di più carino e corretto a livello di scrittura di codice...
...allora adesso vedo di farlo come mi hai scritto in quest' ultimo post.
Più corretto a livello di codice no. Il codice è corretto se è formalmente conforme alle norme del linguaggio e corrispondente al modello di sistema.
Ad esempio il codice che hai proposto nel primo messaggio è formalmente corretto ma non corrispondente al modello di sistema a meno che il tuo modello non sia veramente ultra-bizzarro. Ripeto però che ci sta tutto perchè affrontando una nuova libreria uno può anche non star lì a guardare subito il pelo nell'uovo.
Il suggerimento di creare una classe separata è solo una "praticoneria": diciamo che puoi "concentrarti sul contenuto di AboutDialog senza essere distratto dal resto del codice di TheSoundSuite", nulla di più.
diablo...aka...boss
24-04-2009, 15:31
Ok, ho creato la classe AboutDialog a parte, ed effettivamente viene più ordinato, però non riesco neanche a fargli leggere il frame di TheSoundSuite.
Probabilmente perchè non scrivo correttamente, anche perchè non sò bene come scrivere a dirla tutta :D , ovviamente però ho fatto tutto sotto lo stesso package. Quello che devo dire nell actionperformed mi è chiaro.
(C'è un tutorial che spiega ciò? Ok che più si utilizza il linguaggio e più lo si impara, ma essendo io ancora inesperto come faccio a capire ste cose? Il java tutorial mi pare che non lo spieghi. :cry: )
Ti faccio un esempio che si fa prima. E' simile al programma che hai incollato salvo omettere tutto quello che non è necessario a collegare l'apertura di un JDialog ad un pulsante nella barra dei menu.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.Dialog.ModalityType;
class Test extends JFrame implements ActionListener {
private AboutDialog aboutDialog;
private JMenuItem about = new JMenuItem("About");
public Test() {
super("Test");
JMenuBar menuBar = new JMenuBar();
JMenu help = new JMenu("Help");
about.addActionListener(this);
help.add(about);
menuBar.add(help);
setJMenuBar(menuBar);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void actionPerformed(ActionEvent e) {
if(e.getSource() == about) {
showAboutDialog();
}
}
private void showAboutDialog() {
if(aboutDialog == null) {
aboutDialog = new AboutDialog(this);
}
aboutDialog.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
Test test = new Test();
test.setSize(400, 400);
test.setVisible(true);
}
});
}
}
class AboutDialog extends JDialog {
public AboutDialog(JFrame owner) {
super(owner, ModalityType.DOCUMENT_MODAL);
setTitle("About");
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
add(new JLabel("Hello World", JLabel.CENTER);
setSize(300, 200);
}
}
diablo...aka...boss
27-04-2009, 13:55
Ti risp solo ora perchè sto impazzendo con i panel.
Guardando il tuo esempio ho capito come intendevi, invece io pensavo che la nuova classe era da fare esternamente al file principale (sempre all' interno dello stesso package ovviamente). Credo che si possa fare anche così però non mi torna :muro:
Nel frattempo sto guardando anche i panel perchè se mi inpunto su una cosa è la fine e il tempo è tiranno.
Anche se o.t. approfitto di questo 3d:
Io ho il mio frame, dentro a questo frame ci voglio mettere un panel sulla sinistra.
Ma devo utilizare un container o un contentPane come base? E poi ci metto dentro tutti i
JPanle che voglio giusto? Da quanto dice la sun sono arrivato a questa conclusione, penso che
debbo usare uno dei 2 ( container o contentPane) ma non riesco a capire se sono complementari o altro...
Non è necessario usare il contentPane.
Prima bisogna decidere non la disposizione di un singolo componente ma la disposizione generale di tutti i componenti all'interno della finestra.
Diciamo che il nostro frame ha qualcosa a sinistra e qualcos'altro a destra. Quello che c'è a destra si allarga e si restringe con la finestra, quello che c'è a sinistra ha una dimensione che non risponde al ridimensionamento orizzontale. Un comportamento di questo genere è ottenibile con un layout BorderLayout. Dunque dico:
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
JPanel sinistra = new JPanel();
JPanel destra = new JPanel();
frame.add(sinistra, BorderLayout.WEST);
frame.add(destra, BorderLayout.CENTER);
Il contentPane entra in gioco perchè, dietro le quinte, il nostro dire:
frame.setLayout(...)
viene tradotto automaticamente in frame.getContentPane().setLayout(...) così come frame.add(...) è tradotto in frame.getContentPane().add(...).
Usi o non usi il contentPane a seconda che tu voglia esprimere o non esprimere l'indipendenza che sussiste tra la finestra e il suo pannello del contenuto.
diablo...aka...boss
27-04-2009, 15:20
La storia del contentPane e del JPanel ora mi è chiara, l' esempio è perfetto, grazie.
Però se provo a fare una classe esterna, sempre all' interno della classe madre diciamo, il frame non mi viene visto.
Provo a spiegarmi meglio.
Il frame // Creating the frame and setting the option
private static void createAndShowGUI() {
//Create and set up the window.
JFrame soundSuiteFrame = new JFrame("TheSoundSuite");
soundSuiteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TheSoundSuite demo = new TheSoundSuite();
soundSuiteFrame.setJMenuBar(demo.createMenuBar());
soundSuiteFrame.setSize(600, 400);
soundSuiteFrame.setVisible(true);
}
Poi vabbè dopo ho il main e poi mi vorrei creare una classe apposita per i panel, e quindi faccio
class MyPanel extends JPanel {
public MyPanel(JFrame owner) {
soundSuiteFrame.setLayout(new BorderLayout());
JPanel sinistra = new JPanel();
JPanel destra = new JPanel();
frame.add(sinistra, BorderLayout.WEST);
frame.add(destra, BorderLayout.CENTER);
JButton button = null;
button = new JButton("Clicka qui");
sinistra.add(button);
}
Ho provato a fare una cosa molto veloce e a visualizzare semplicemente un bottone nel panel sinistro. Giusto per capire come si imposta la cosa.
Penso che sia un errore di base, perchè deve essere lo stesso che commetto con AboutDialog :(
Io qui ho il sospetto che non si tratti tanto di un problema nell'uso di Swing quanto una questione di linguaggio Java.
Mi fa drizzare le antenne questo createAndShowGUI:
// Creating the frame and setting the option
private static void createAndShowGUI() {
//Create and set up the window.
JFrame soundSuiteFrame = new JFrame("TheSoundSuite");
soundSuiteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
TheSoundSuite demo = new TheSoundSuite();
soundSuiteFrame.setJMenuBar(demo.createMenuBar());
soundSuiteFrame.setSize(600, 400);
soundSuiteFrame.setVisible(true);
}
Per una questione detta name scope (ambito dei nomi) questo pezzo qui:
//Create and set up the window.
JFrame soundSuiteFrame = new JFrame("TheSoundSuite");
soundSuiteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
E' come se non ci fosse. Sai la ragione (anche più o meno, non è necessario essere tecnici) per cui è come se non ci fosse oppure no? Perchè è possibile che il non saperlo sia alla base dal problema che hai con il pulsante. E' una questione molto "semplice", se non ti risulta te la spiego in una trentina di righe (non sono un tipo "riassuntivo" :D).
diablo...aka...boss
27-04-2009, 20:17
JFrame soundSuiteFrame = new JFrame("TheSoundSuite");
Qui mi sembra tutto regolare.
soundSuiteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Il problema suppongo sia questo.
Non penso di averci mai fatto caso perchè comunque il frame lo vedo e la JMenuBar la prende e la vedo e riesco ad usarla.
Forse l' errore può essere di impostazione, ovvero, andando a riguardare ora le slide del prof noto che il tutto viene fatto in modo "leggermente" (:D) diverso.
public class MyFrame extends JFrame {
public MyFrame (String titolo, int posX, int posY, int width, int height) {
this.setTitle(titolo);
this.setLocation(posX, posY);
this.setSize(width, height);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
costruzione del main:
public class Test1
{
public static void main(String[] args)
{
MyFrame myFrame =
new MyFrame("Test JFrame", 20, 20, 600, 200); myFrame.setVisible(true);
}
}
Il test1 a colpo d' occhio non mi torna ma vabbè, quindi soundSuiteFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
non va certo dove l' ho messo io!
Diciamo che se hai voglia (anche domani chiaramente) di scrivermi quelle 30 righe di certo non mi fanno male e te ne sarei molto grato. :)
No, ho fatto confusione io :D. Hai presente quando salendo in cattedra inciampi sul bordo e pesti una facciata per terra? Ecco, una cosa del genere :D. Quindi dimentica quello che ho detto.
T'è andata di lusso, ti sei risparmiato un sermone di 30 righe in cui pontificavo dell'ambito dei nomi.
Allora diciamo che soundSuiteFrame è il tuo JFrame. Vuoi aggiungergli un pannello a destra e uno a sinistra.
Prendi il frame, gli assegni il tuo bel BorderLayout e metti i pannelli uno a destra e uno a sinistra, come hai fatto nel costruttore MyPanel:
JPanel destra = new JPanel();
JPanel sinistra = new JPanel();
soundSuiteFrame.setLayout(new BorderLayout());
soundSuiteFrame.add(sinistra, BorderLayout.WEST);
soundSuiteFrame.add(destra, BorderLayout.EAST);
Puoi fare questi passaggi in una classe separata? Sì, un po' come hai fatto in MyPanel. Nota però che non è necessario che MyPanel estenda JPanel (un po' come apparentemente non è necessario che Test estenda JFrame mentre serve l'estensione in MyFrame). Basta dire:
class MyPanel {
MyPanel(JFrame aFrame) {
aFrame.setLayout(new BorderLayout());
JPanel sinistra = new JPanel();
JPanel destra = new JPanel();
aFrame.add(sinistra, BorderLayout.WEST);
aFrame.add(destra, BorderLayout.EAST);
}
}
Nel main dopo aver creato il frame theSoundSuite puoi invocare:
new MyPanel(theSoundSuite);
Non vedi niente perchè i JPanel non hanno un aspetto proprio, però funziona.
Per curiosità, il codice che hai incollato nell'ultimo post viene dalle slide del vostro prof, vero? Dimmi di no, menti se necessario :D:
diablo...aka...boss
27-04-2009, 20:51
Direi che si è creata abbastanza confusione in questi ultimi post :)
però penso proprio di aver capito ciò che intendi.
domani mattina mi rileggo tutto e vedo di implementare la versione corretta come si vede di ciò che devo fare.
In riferimento all' ultima domanda: vengono da un doc che mi sono fatto io sulle GUI! E' vero. Però dimmi il perchè :D
Un costruttore non dovrebbe invocare metodi pubblici a meno che la classe in cui si trova non sia final o siano final i singoli metodi invocati. E' un problema che ha a che fare con la catena di inizializzazione degli oggetti e con i rischi che si corrono nel caso in cui la classe sia estesa. Il metodo main visualizza il frame con un certo spregio del pericolo per via dell'architettura a thread unico di Swing. Ma se sono appunti tutto fa brodo.
diablo...aka...boss
29-04-2009, 11:13
Sono appunti fatti con le slide del prof...quello era giusto un esempio per farci capire come funzionavano i frame, forse per quello è stato fatto così. bho...
Seguendo quello che mi hai penso di essere riuscito nell' intento di ordinare il codice facendo classi separate, funziona quindi qualcosa di buono c'è penso
Ora ho la classe principale con il main
public class TheSoundSuite {
public static void main(String[] args) {
SuiteFrame myFrame = new SuiteFrame("The Sound Suite", 300, 300, 600, 400);
myFrame.setVisible(true);
}
}
e poi ho fatto una classe separata per il frame (la menuBar e poi ci inserirò anche il panel)
public class SuiteFrame extends JFrame {
private static final long serialVersionUID = 1L;
public SuiteFrame(String titolo, int i, int j, int k, int l) {
// constructor stub
this.setTitle("The Sound Suite");
this.setLocation(300, 300);
this.setSize(600, 400);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.add(createMenuBar());
}
public static JMenuBar createMenuBar() {
JMenuBar menuBar;
JMenu file, help;
JMenuItem open, about;
// Creo la menu bar, i menù File e Help, e i sottomenù Open e About.
menuBar = new JMenuBar();
file = new JMenu("File");
file.setMnemonic(KeyEvent.VK_A);
file.getAccessibleContext().setAccessibleDescription(
"The only menu in this program that has menu items");
menuBar.add(file);
open = new JMenuItem("Open", KeyEvent.VK_T);
open.setMnemonic(KeyEvent.VK_T); // used constructor instead
open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1,
ActionEvent.ALT_MASK));
open.getAccessibleContext().setAccessibleDescription(
"This menu does nothing");
file.add(open);
help = new JMenu("Help");
help.setMnemonic(KeyEvent.VK_N);
help.getAccessibleContext().setAccessibleDescription(
"This menu does nothing");
menuBar.add(help);
about = new JMenuItem("About...");
about.setMnemonic(KeyEvent.VK_B);
about.setMnemonic(KeyEvent.VK_D);
help.add(about);
final Component SOURCE = about;
about.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
javax.swing.JOptionPane
.showMessageDialog(
SOURCE,
"The Sound Suite version 0.1\n\nAutori:\nMauro Bianchi\nAndrea Rossi\n\nThe Sound Suite è un programma freeware",
"About...", JOptionPane.INFORMATION_MESSAGE);
}
});
return menuBar;
}
}
L'unica nota negativa che non riesco a capire è perchè mi posizioni la menuBar verticalmente sulla sinistra, inoltre me ne fa una per file e una per help
:confused:
Sbaglio a pensare che l' impostazione del progetto, ovvero il fatto di avere due classi, sia fatta correttamente?
Ancora grazie per il tuo aiuto.
JMenuBar è un JComponent quindi puoi usarlo come tale. Nel tuo codice lo fai nel momento in cui dici:
this.add(createMenuBar());
Se vuoi che la barra dei menu occupi la posizione comune devi usare il metodo setJMenuBar di JFrame:
this.setJMenuBar(createMenuBar());
Il metodo createMenuBar può anche non essere statico. In genere se un metodo è statico è perchè esiste la necessità di invocarlo da qualche altra unità di compilazione. Se lo usi solo in TheSoundSuite puoi renderlo private senza static.
La correttezza dell'impostazione di un programma orientato agli oggetti dipende dal modello di sistema. Gli oggetti e le relazioni tra oggetti che esprimi nel programma Java altro non sono che una traduzione degli oggetti e delle relazioni che esistono nel sistema che vuoi riprodurre - salvo le necessità imposte dalle regole del linguaggio Java. Non conoscendo il modello si sistema non posso dirti se il codice sia o non sia corrispondente e quindi corretto. Posso dire che l'impostazione è "comune", nel senso che un normale programma Java è più o meno sempre fatto così. Non è molto ma la regolarità ha i suoi vantaggi.
Una nota. Il tuo metodo main dovrebbe essere fatto così:
public class TheSoundSuite {
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
SuiteFrame myFrame = new SuiteFrame("The Sound Suite", 300, 300, 600, 400);
myFrame.setVisible(true);
}
});
}
}
Per una questione di concorrenza. Ci sono due cose da tenere a mente. La prima è che il metodo main è eseguito da un Thread detto Main creato dalla JVM. La seconda è che Swing è "single-thread" in due sensi. Il un primo senso la maggior parte dei metodi degli oggetti Swing è progettato per essere eseguito da un solo e unico Thread. Quindi usando più di un Thread per interagire con oggetti Swing si può incappare in uno stallo o in un data race. Nel secondo senso Swing è single-thread perchè crea e gestisce autonomamente quell'unico e solo Thread che "fa girare" i suoi componenti. Il Thread è noto come Event Dispatcher Thread o EDT.
Per interagire con l'EDT (cioè per far eseguire del codice all'EDT anche se il Thread corrente non è l'EDT) si usa la coda degli eventi di sistema.
La faccenda è un po' più lunga e interessante di così ma, in sintesi, per far eseguire del codice all'EDT si incapsula quel codice nel metodo run di un oggetto Runnable e si usa quel Runnable come argomento dell'invocazione EventQueue.invokeLater. Il risultato è che il contenuto del metodo run è eseguito dall'EDT.
La correzione al main che ho incollato fa esattamente questo. Runnable è un'interfaccia quindi per creare un'istanza di Runnable occorre prima creare una classe che derivi da Runnable e definire il metodo run, mettendoci dentro il codice che si vuol far eseguire all'EDT. Il tutto è compresso nell'istanziazione di classe interna locale anonima "new Runnable() {...eccetera...}". Nel metodo run della classe interna locale anonima che implementa Runnable c'è il codice che crea un SuiteFrame e lo visualizza, il tutto viene passato al metodo invokeLater di EventQueue.
E il gioco è fatto. E' un po' prolisso per via della mancanza di una sintassi ad hoc per i funtori in Java ma non è complicato. E' importante tenere presente la faccenda del single-thread.
diablo...aka...boss
30-04-2009, 13:01
:sbavvv: wow che spiegazione, io la sapevo molto molto molto più terra terra (peccato che non trovo più dove l' ho scritto). Grazie 1000, ho capito.
Ho messo tutto a posto e ora oltre ad essere ordinato, funziona come si deve.
Ora manca tutto il resto :muro: :muro: :muro:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.