Buscar
Social
Ofertas laborales ES

Foro sobre Java SE > Asegurar dibujado de pantalla en Swing antes de tarea

Por el título del mensaje ya veis que es difícil de describir lo que quiero, y en realidad debería ser algo muy sencillo, pero no consigo encontrar la solución. Tengo este código dentro del método actionPerformed de un objeto que extiende AbstractAction:


@Override
public void actionPerformed(ActionEvent e) {
// Establece un texto en la barra de estado de la aplicación
Main.mainWindow.getStatusBar().setInfoText("Creating window, please wait...");
Main.mainWindow.getStatusBar().repaint();

// Si no está ya previamente creado, crea un JPanel con controles de usuario
if (editContentPanel == null) {
// Esto tarda 1-2 segundos, porque internamente crea un EntityManager de JPA
editContentPanel = new EditContentPanel();
}
// Añade el panel como una pestaña nueva a la ventana de la aplicación
Main.mainWindow.addTab(editContentPanel, TITLE);
// Hemos acabado, limpiamos la barra de estado
Main.mainWindow.getStatusBar().clearText();
}

El problema es que la primera línea (setInfoText) solo se refleja en el GUI después de que se haya creado el EditContentPanel. Si pongo la última línea (clearText), no veo ningún mensaje en absoluto mientras espero y, si no la pongo, el mensaje se queda ahí (lógicamente).

Vale, crear la instancia de EditContentPanel es una tarea que consume tiempo así que, ¿por qué no desviarla a un SwingWorker? Pues quizá sea posible, pero como estoy creando componentes Swing y dependo de que se haya inicializado el panel por completo para añadirlo a la ventana, no quiero convertirlo en una tarea en fondo. Solo quiero que el mensaje sea procesado por el EDT antes de comenzar a crear el EditContentPanel.

He mirado EventQueue (por un post en StackOverflow) y SwingUtilities, pero no veo ninguna manera de forzar que se vacíe el EDT antes de continuar la ejecución. ¿Alguien tiene alguna solución mágica? :-) Muchas gracias por anticipado.


Nota 1: el problema no lo tengo solo con el EditContentPanel, claro. Me pasa con todas las acciones que invocan un panel que tarda en inicializarse (con todas las acciones, en realidad, pero obviamente el mensaje solo lo necesito en los que tardan).

Nota 2: sí, el chequeo de null no es nada ortodoxo, porque podría tener dos pestañas con el mismo panel, así que tendré que crear una instancia diferente o impedir que haya más de una pestaña con la misma instancia de panel, pero eso ya lo resolveré. :-)

mayo 25, 2015 | Registered Commenterrickiees

hola rickiees,
se me ocurre que crees un Thread,
por ejemplo asi, usando clases anonimas.

public void actionPerformed(ActionEvent e) {
// Establece un texto en la barra de estado de la aplicación
Main.mainWindow.getStatusBar().setInfoText("Creating window, please wait...");
Main.mainWindow.getStatusBar().repaint();
Thread Tarea=new Thread(new Runnable(){
public void run(){
// Si no está ya previamente creado, crea un JPanel con controles de usuario
if (editContentPanel == null) {
// Esto tarda 1-2 segundos, porque internamente crea un EntityManager de JPA
editContentPanel = new EditContentPanel();
}
// Añade el panel como una pestaña nueva a la ventana de la aplicación
Main.mainWindow.addTab(editContentPanel, TITLE);
// Hemos acabado, limpiamos la barra de estado
Main.mainWindow.getStatusBar().clearText();
}
});

Tarea.start();
}

No recuerdo sin en java, te salta el error de no poder cambiar atributos de los componentes de interfaz grafica desde un hilo distinto al principal. como sucede en .net, o android. pero prueba y nos cuentas.

saludos.

mayo 27, 2015 | Registered Commenterjhosep

Pues, aparentemente... funciona. :-)

Lo que pasa es que creo que no es una solución correcta, en el sentido de que no va a funcionar bien el 100 % de las veces. Se supone que la interacción con los componentes gráficos debe hacerse exclusivamente en el EDT, en el que se ejecuta el objeto Action (pero no el nuevo Thread creado). En lugar de un Thread normal tendría que usar un SwingWorker (que es lo que quería evitar).

Lo tengo que pensar más despacio, ya os contaré si averiguo algo.

mayo 30, 2015 | Registered Commenterrickiees

Si funciona, no es correcta en el sentido del diseño y problemas a futuro que te puede traer en eso estoy de acuerdo contigo, la sugerí porque a veces las soluciones poco ortodoxas te salvan el día, y te dan tiempo a buscar la solución adecuada.

pues no le veo tanto problema a usar swingworker en
el public String doInBackground() {
//creacion del editContentPanel
}

y en

protected void done() {
// Añade el panel como una pestaña nueva a la ventana de la aplicación
Main.mainWindow.addTab(editContentPanel, TITLE);
// Hemos acabado, limpiamos la barra de estado
Main.mainWindow.getStatusBar().clearText();
}
claro tenes que solucionar los accesos de la clase que implementa swingworker a tu interfaz, pero sin mas información que el bloque de código que tienes poco puedo ayudarte.

una pregunta para la creación de EditContentPanel,no quedaría bien usar el patron de diseño singleton?
http://es.wikipedia.org/wiki/Singleton

Saludos y exitos.

junio 1, 2015 | Registered Commenterjhosep