Jframe does not update until function of button finish

Asked

Viewed 450 times

0

When I click the button it calls a method, and until this method finishes the Jframe does not update

the program is in the image below

Programa

private void jButtonBuscarActionPerformed(java.awt.event.ActionEvent evt) {                                              
     jTextArea.setText("");
     AtualizeStats("Buscando Dispositivos");
     if (bioSignals.SearchDevice())
     {
         jButtonIniciar.setEnabled(true);
     }
 } 

the method that really takes is what is inside the if condition, but what comes before should basically appear instantaneously, even because the method Atualizestats("Searching Devices") only changes the text of the black box and printa in the console:

public void AtualizeStats(String stats)
{
    System.out.println(stats);
    jTextArea.append(stats + "\n");
}

what happens is that on the console appears "Searching Devices" instantly but Jframe waits until everything that is in the System button is executed

  • And it’s all right, it’s all the same thread... There must be something to force the UI update. If this type of thing is not recurrent, you can use something like this.

  • Young man, after AtualizeStats("Buscando Dispositivos"); try to do jTextArea.revalidate() or repaint()

  • neither worked, remains the same

  • what I find more strange is that until the state of the button gets locked, it remains clicked until finished running

  • On the site there are examples of use of swingworker here,

1 answer

2


To be able to perform tasks without locking the graphical interface, you need to use the class SwingWorker, because it was designed to parallelize the time-consuming tasks of EDT, which is the thread that manages the functioning of the graphical interface in swing.

Within this class, you will delegate the task to the method doInBackground(), that runs in a separate pool, so that the screen keeps running while the task runs. It is also possible to display progress with the classes publish() and process(), and display some termination warning through the class done().

I will not go into the details of each method because it is not the purpose of the answer, but I will leave some links for study at the end. An example of the use of SwingWorker, similar to what you are doing, there are comments on relevant excerpts:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.List;

public class SwingWorkeSimpleExample extends JFrame {

    private static final long serialVersionUID = 1L;
    private JPanel contentPane;
    private JPanel northPanel;
    private JButton btnSearch;
    private JScrollPane scrollPane;
    private JTextArea textArea;
    private JProgressBar progressBar;

    public static void main(String[] args) {
        EventQueue.invokeLater(SwingWorkeSimpleExample::new);
    }

    public SwingWorkeSimpleExample() {
        setTitle("SwingWorker Test");
        initComponents();
        pack();
        setLocationRelativeTo(null);
        setVisible(true);
    }

    private void initComponents() {

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(350, 300));
        this.contentPane = new JPanel();
        this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        this.contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(this.contentPane);

        this.northPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
        this.contentPane.add(this.northPanel, BorderLayout.NORTH);

        this.btnSearch = new JButton("Search...");
        this.btnSearch.addActionListener(new ActionWorker());
        this.northPanel.add(this.btnSearch);

        this.textArea = new JTextArea();
        this.textArea.setBackground(Color.BLACK);
        this.textArea.setForeground(Color.WHITE);

        this.scrollPane = new JScrollPane(this.textArea);
        this.scrollPane.setBorder(new EmptyBorder(2, 0, 2, 0));
        this.contentPane.add(this.scrollPane, BorderLayout.CENTER);

        this.progressBar = new JProgressBar(0, 10);
        this.contentPane.add(this.progressBar, BorderLayout.SOUTH);
    }

    private void textAreaAppend(String str) {
        this.textArea.append(str + System.lineSeparator());
    }

    class ActionWorker implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

            SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {

                @Override
                protected Void doInBackground() throws Exception {
                    //aqui tudo ocorrerá em paralelo a gui
                    //desativo o botão, adiciono uma mensagem inicial
                    btnSearch.setEnabled(false);
                    textAreaAppend("Searching...");
                    //laço que alimenta a barra de progresso apenas para exemplo
                    for (int i = 0; i < progressBar.getMaximum(); i++) {

                        if (i > 0 && i % 4 == 0)
                            textAreaAppend("Wait...");
                        Thread.sleep(500);
                        //esse metodo "publica" atualizações da tarefa
                        //para a que a barra de progresso seja alimentada
                        //conforme o incremento do laço
                        publish(i);
                    }

                    textAreaAppend("Done!");
                    return null;
                }

                @Override
                protected void process(List<Integer> chunks) {
                    //este métodor recebe o que foi "publicado"
                    // no doInBackground para que possamos atualizar
                    //o progresso na tela
                    progressBar.setValue(chunks.stream().reduce(Integer::sum).orElse(0));
                }

                @Override
                protected void done() {
                    //entrará aqui quando terminar a tarefa, ou
                    //ocorrer alguma exceção
                    progressBar.setValue(0);
                    btnSearch.setEnabled(true);
                }
            };
            worker.execute();
        }
    }
}

Running:

inserir a descrição da imagem aqui


  • Thank you very much, it worked very well

Browser other questions tagged

You are not signed in. Login or sign up in order to post.