Pregunta

He estado usando el siguiente método para crear componentes y valores de retorno de la oscilación hacia / desde fuera del EDT. Por ejemplo, el siguiente método podría ser una extensión de JFrame, para crear un JPanel y añadirlo a la matriz JFrame:

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];
}

La matriz de 1 de longitud local se utiliza para transferir el "resultado" desde el interior del Runnable, que se invoca en el EDT. Bueno, parece "un poco" hacky, y así mis preguntas:

  1. ¿Esto tiene sentido? ¿Hay alguien más haciendo algo como esto?
  2. es la matriz 1 de longitud una buena manera de transferir el resultado?
  3. ¿Hay una manera más fácil de hacer esto?
¿Fue útil?

Solución

  • La ingestión de excepciones sin siquiera ingresar a: mal !! - te odio a sí mismo cuando se encuentra con algo así como que después de un error de caza de 2 horas
  • No, la matriz no es una buena manera; Por un lado, no ofrece ningún método fácil para el código de llamada que esperar a que el hilo EDT para ejecutar el Runnable antes de ir a buscar el resultado
  • No es una clase diseñada expresamente para este tipo de cosas: SwingWorker

Otros consejos

A pesar de que el método puede tener sentido en algunas situaciones, será inútil la mayor parte del tiempo.

La razón es que la creación de la mayoría (si no todos) de sus componentes siempre se produce a partir de la EDT, como resultado de una acción del usuario (elemento de menú o un botón hecho clic) que siempre se ejecuta desde la EDT.

En los casos donde se tiene gran trabajo para llevar a cabo antes de crear su panel y que no desea bloquear la EDT, entonces debería, según lo sugerido por otra persona, o utilizar SwingWorker un marco oscilación que ofrecen apoyo a las tareas largas ( en general, sobre la base de SwingWorker internamente de todos modos, pero no necesariamente).

En cuanto a su pregunta 2, por desgracia, no tienes muchas maneras de hacerlo:

  • Utilice una matriz de 1 punto como lo hizo, eso es la solución más fácil, pero también más fea
  • Crea una clase ItemHolder (véase más adelante) que hace casi lo mismo, requiere un poco más de trabajo y es más limpio, en mi opinión
  • Por último, el uso java.util.concurrent instalaciones (futuros y se puede llamar); que sería el cleaniest pienso, sino que también se requiere el mayor esfuerzo

Aquí es decir, simplificada, la clase ItemHolder:

public class ItemHolder<T> {
    public void set(T item) {...}
    public T get() {...}
    private T item;
}
  1. a) Tiene sentido. b) No que yo sepa.
  2. Tan bueno como cualquiera.
  3. Crear los JPanel fuera de la llamada invokeAndWait

// Esta línea añade a apaciguar 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;
}

Puede comprobar fácilmente si el hilo actual es la EDT y luego ejecutar correctamente y de manera más simple en ese contexto. En cuanto a usar la matriz final para conseguir el valor de retorno, que es la forma más fácil cuando se tiene que utilizar una clase interna anónima como este.

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];
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top