Los botones no se deshabilitan en Java
Frecuentes
Visto 198 veces
0
He creado un botón.. Quiero que cada vez que haga clic en el botón, primero deshabilite los otros dos botones y luego haga otras tareas que he programado.. pero deshabilite los botones al final.
Extract.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Button1.setEnabled(false);
Button2.setEnabled(false);
obj.showData();
obj.extractClassesPackagesImports();
obj.inheritanceRelation();
obj.doubleinheritanceRelation();
JOptionPane.showMessageDialog(null, "Done");
}
});
Ahora el programa anterior deshabilita los botones después de mostrar el cuadro de mensaje... alguien puede averiguar qué es lo que está mal aquí... gracias de antemano
3 Respuestas
1
¿Puedes probar esto?
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, "Done");
}
});
Respondido el 11 de Septiembre de 13 a las 14:09
¿Llamas a invocar más tarde cuando ya estás en el hilo de envío del evento? Si entiendo correctamente, ¿no es esto como tomar el autobús para ir a donde ya estás? - Menelaos
Llamar a invocarLater debería permitir que se procesen las actualizaciones de la interfaz gráfica de usuario antes de mostrar el cuadro de diálogo. - vikingosteve
@meewoK De esa manera, la acción dentro del Runnable
está en cola para ser ejecutado después del código actual, en lugar de ejecutarlo en el acto. - afsantos
Debería es un término muy indefinido. Mientras ejecuta su código, se ejecuta tan rápido que no es el caso. Si no sucede mucho más en la GUI, estamos hablando de un retraso mínimo (en el rango de MS). - Menelaos
@vikingsteve probablemente desee que todo el código después de las dos llamadas a setEnable(false) se llame con SwingUtilities.invokeLater(). El operador probablemente quiera ver los botones deshabilitados justo después de esas dos llamadas. (Si lo hace, seguirá bloqueando toda la GUI durante el tiempo, pero los botones se mostrarán como deshabilitados) - nuestros
1
Como dijo @vikingsteve, lo más probable es que no permita que el subproceso de la GUI actualice el cuadro de diálogo.
Si agrega Thread.Sleep(1000);
seguramente verá un retraso entre la desactivación y el cuadro de mensaje.
Sin embargo, no entiendo la utilidad de por qué marca la diferencia si los botones están deshabilitados antes o después del cuadro de diálogo.
Noticias
He agregado un subproceso adicional para poder utilizar Thread.sleep(5000) , sin congelar completamente el subproceso de envío de eventos (GUI).
Sin embargo, dado que ahora mi código está llamando a showMessageDialog desde un nuevo subproceso, debo usar invocarLater.
Además, dado que el código original permitirá al usuario hacer clic en los botones aunque estemos esperando que finalicen las actividades, creo que todas las acciones deben moverse a un hilo separado como este:
Extract.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//Disable Buttons since we are in Event Dispatching Thread
Button1.setEnabled(false);
Button2.setEnabled(false);
//Tasks moved to separate Thread
new Thread(new Runnable() {
public void run() {
try {
//Perform Tasks
obj.showData();
obj.extractClassesPackagesImports();
obj.inheritanceRelation();
obj.doubleinheritanceRelation();
//Delay before calling message (we are delaying in separate thread to not freeze GUI completely)
Thread.sleep(5000);
//Wait 5 seconds before showing dialog
//Show the GUI - since GUI interaction from new Thread using invokeLater
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, "Done");
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
});
El código anterior agrega un retraso antes de mostrar un mensaje, mientras que tampoco congela la GUI.
Respondido el 12 de Septiembre de 13 a las 13:09
0
Mirando el código de AbstractButton
, JComponent
y RepaintManager
, concluyo que setEnabled()
publica un nuevo evento en la cola de eventos, para mostrar el botón desactivado.
Por lo tanto, mirando su código, suceden los siguientes eventos, como usted describe:
EventQueue:
Event1: {
setEnabled(false) // queues Event2
showMessageDialog(null, "Done")
},
Event2: {
repaint() // to display the disabled button
}
El código correspondiente se proporciona a continuación:
ResumenBotón
public void setEnabled(boolean b) {
// ...
super.setEnabled(b);
// ...
}
JComponent
public void setEnabled(boolean enabled) {
// ...
if (enabled != oldEnabled) {
repaint();
}
}
public void repaint(long tm, int x, int y, int width, int height) {
RepaintManager.currentManager(this).addDirtyRegion(this, x, y, width, height);
}
Administrador de Repintado
public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
{
// ...
addDirtyRegion0(c, x, y, w, h);
}
private void addDirtyRegion0(Container c, int x, int y, int w, int h) {
// ...
// Queue a Runnable to invoke paintDirtyRegions and
// validateInvalidComponents.
scheduleProcessingRunnable();
}
Si desea que el botón se muestre como deshabilitado antes de que muestra el cuadro de diálogo, la solución, como señaló @vikingsteve, es usar SwingUtilities.invokeLater()
.
extract.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
button1.setEnabled(false);
button2.setEnabled(false);
obj.showData();
obj.extractClassesPackagesImports();
obj.inheritanceRelation();
obj.doubleinheritanceRelation();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JOptionPane.showMessageDialog(null, "Done");
}
});
}
});
Respondido el 11 de Septiembre de 13 a las 14:09
Tenga en cuenta que mostrar el cuadro de diálogo usando SwingUtilities.invokeLater no ayudará. La operación de larga duración probablemente obj.extractClassesPackagesImports(); Entonces, aunque las primeras 2 líneas de código deshabilitan el botón, esto no se mostrará en la GUI hasta que se ejecute la última línea (JOptionPane.showMessageDialog(null, "Done");). JOptionPane ejecutará el bucle de eventos de la GUI (por lo que no es necesario invocar más tarde), por lo que los botones se actualizarán cuando se muestre JOptionPane. El OP probablemente quiera ver los botones deshabilitados justo después de llamar a setEnabled (falso). - nuestros
@nos De hecho, las operaciones en obj
puede tomar un tiempo, por lo que diría que probablemente deberían ejecutarse en otro subproceso, llamando a un método que muestra el cuadro de diálogo en el EDT cuando haya terminado. - afsantos
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas java swing actionlistener or haz tu propia pregunta.
cuál es tu error, no puedo entender lo que quieres lograr. Considere hacer un SSCCE - nachokk
Entiendo que los botones están deshabilitados cuando se muestra un cuadro de mensaje, no cuando se hace clic en el botón. pero no se que es
Extract
aquí (el OP debería mostrar más código). por cierto, el nombre de esta variable debe comenzar con una letra minúscula, como los otros nombres de variables. - Arnaud DenoyelleParece que no está permitiendo que el subproceso de la GUI se actualice antes de mostrar el cuadro de diálogo. No estoy seguro de cuál es la mejor manera de "rendir" y permitir que swing actualice la interfaz gráfica de usuario, tal vez
invokeLater
- ¿alguien sabe? - vikingsteve@Arnaud Denoyelle Teniendo en cuenta la pregunta, parece que Extract es un objeto Jbutton. Estoy actualizando la pregunta para agregar esta información. - Menelaos
no relacionado: aprenda las convenciones de nomenclatura de Java y respételas. - kleopatra