Domanda

Sto usando il seguente approccio per creare componenti e restituire i valori da swing a / da fuori EDT. Per esempio, il seguente metodo potrebbe essere una proroga per JFrame, per creare un JPanel e aggiungerlo alla JFrame genitore:

public JPanel threadSafeAddPanel() {

    final JPanel[] jPanel = new JPanel[1];

    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                jPanel[0] = new JPanel();
                add(jPanel[0]);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }

    return jPanel[0];
}

L'array 1-lunghezza locale è usato per trasferire il "risultato" dall'interno del Runnable, che viene richiamato nel EDT. Beh, sembra "un po '" hacky, e così le mie domande:

  1. Ha senso? È qualcun altro fare qualcosa di simile?
  2. è la matrice 1 di lunghezza un buon modo per trasferire il risultato?
  3. C'è un modo più semplice per fare questo?
È stato utile?

Soluzione

  • L'ingestione di eccezioni senza nemmeno la registrazione: male !! - vi odio te stesso quando si arriva su una cosa del genere dopo un 2 ore di bug-caccia
  • No, la matrice non è un buon modo; Per prima cosa, offre nessun metodo facile per il codice chiamante di attendere per il thread EDT per eseguire il Runnable prima di andare a prendere il risultato
  • C'è una classe progettata esplicitamente per questo genere di cose: SwingWorker

Altri suggerimenti

Sebbene tale metodo può avere senso in alcune situazioni, sarà inutile la maggior parte del tempo.

Il motivo è che la creazione di più (se non tutti) i componenti saranno sempre verificarsi da EDT, a seguito di un'azione utente (voce di menu o il pulsante cliccato) che sono sempre eseguito dal EDT.

Nei casi in cui si hanno grandi lavori da eseguire prima di creare il vostro pannello e non si desidera bloccare l'EDT, allora si dovrebbe, come suggerito da qualcun altro, utilizzare SwingWorker o un quadro swing che offrono supporto per le attività di lunghi ( generalmente basati sulla SwingWorker internamente ogni caso, ma non necessariamente).

Per quanto riguarda la tua domanda 2, purtroppo, non si dispone di molti modi per farlo:

  • utilizzare un array 1-oggetto come hai fatto tu, che è la soluzione più semplice, ma anche più brutto
  • Creare una classe ItemHolder (vedi di seguito) che fa quasi lo stesso, richiede un po 'più di lavoro, ed è più pulita, a mio parere
  • Ultimo, uso java.util.concurrent strutture (futuri e Callable); che sarebbe il cleaniest credo, ma anche che richiede il massimo sforzo

Ecco, semplificato, la classe ItemHolder:

public class ItemHolder<T> {
    public void set(T item) {...}
    public T get() {...}
    private T item;
}
  1. a) Ha senso. b) Non che io sappia.
  2. Buono come qualsiasi.
  3. Crea le JPanel al di fuori della chiamata invokeAndWait

// Questa linea aggiunto per placare Markdown

public JPanel threadSafeAddPanel() {
    final JPanel jPanel = new JPanel();
    try {
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                add(jPanel);
            }
        });
    } catch (InterruptedException ex) {
    } catch (InvocationTargetException ex) {
    }
    return jPanel;
}

Si può facilmente verificare se il thread corrente è l'EDT e quindi eseguire in modo corretto e più semplicemente in quel contesto. Come per l'utilizzo della matrice finale per ottenere il valore di ritorno, che è il modo più semplice quando si deve utilizzare una classe interna anonima come questo.

public JPanel threadSafeAddPanel() throws InterruptedException, 
        InvocationTargetException {
    if (EventQueue.isDispatchThread()) {
        JPanel panel = new JPanel();
        add(panel);

        return panel; 
    } else {
        final JPanel[] jPanel = new JPanel[1];
        EventQueue.invokeAndWait(new Runnable() {
            public void run() {
                jPanel[0] = new JPanel();
                add(jPanel[0]);
            }
        });

        return jPanel[0];
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top