Los botones no se deshabilitan en Java

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

preguntado el 11 de septiembre de 13 a las 14:09

cuál es tu error, no puedo entender lo que quieres lograr. Considere hacer un SSCCE -

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. -

Parece 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? -

@Arnaud Denoyelle Teniendo en cuenta la pregunta, parece que Extract es un objeto Jbutton. Estoy actualizando la pregunta para agregar esta información. -

no relacionado: aprenda las convenciones de nomenclatura de Java y respételas. -

3 Respuestas

¿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

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

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 or haz tu propia pregunta.