Утилиты Java Swing

#java #swing

#java #swing

Вопрос:

Я хочу создать загрузочное сообщение, которое будет появляться на экране во время загрузки информации. Я вызову для него метод initLoadingPanel(), чтобы JFrame был виден. Моя проблема в том, как я могу ее закрыть?

Мой код приведен ниже.

 public class DataMigration extends JFrame{

    private JFrame frmDataMigration;

    private JFrame loader;

private JButton btnProcess;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    DataMigration window = new DataMigration();
                    window.frmDataMigration.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public DataMigration() {
        initialize();
    }

    private void initialize() {

        LoggerImp.startLog(CLASS_NAME, "initialize()");

        frmDataMigration = new JFrame();

btnProcess = new JButton("Load");
        btnProcess.setEnabled(false);
        btnProcess.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {

            SwingWorker <CSV, CSV> worker = new SwingWorker<CSV, CSV>() {

                @Override
                protected CSV doInBackground() throws Exception {
                    return FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText());
                }

                @Override
                protected void done() {
                    try {
                        csv = doInBackground();
                        generateTableList(csv.getCsvTitle(), stateController.getFieldNames());
                    } catch (ExecutionException ex) {
                        ex.printStackTrace();
                    } catch (Exception e){

                    }
                    loader.dispose();
                }

            };
            worker.execute();
        }
        });
     frmDataMigration.getContentPane().add(btnProcess);
}

   public void initLoadingPanel(){
     SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
             loader = new JFrame("Loading....");
             ImageIcon img = new ImageIcon("loader.gif");
             loader.add(new JLabel(" Loading...", img, JLabel.CENTER));

             loader.setAlwaysOnTop(true);
             loader.pack();
             loader.setSize( 448, 497);
             loader.setVisible(true);
             loader.setLocationRelativeTo(null);
         }
     });
}
  

Ответ №1:

Как правило, вам нужно только вызвать loader.dispose() or loader.setVisible(false) , тогда возникает вопрос о том, как вы загружаете свои ресурсы?

Вероятно, вам потребуется передать ссылку loader на эту часть вашего кода, чтобы, когда она будет завершена, вы могли избавиться от фрейма.

Поскольку рамка оформлена, пользователь может просто нажать кнопку «[x]» и закрыть окно, в то время как вы можете установить рамки defaultCloseOperation DO_NOTHING_ON_CLOSE , это все равно выглядит странно.

Вы могли бы удалить оформление фрейма с помощью JFrame#setUndecorated

Поскольку loader extends from JFrame по-прежнему позволяет пользователю взаимодействовать с родительским окном (если оно видно), лучшим решением может быть использование a JDialog вместо и сделать его модальным.

Вы также можете рассмотреть вопрос о том, как создать заставку для некоторых других идей

Обновлено

Вы затеняете свои переменные…

Сначала вы объявляете loader в качестве поля экземпляра DataMigration

 public class DataMigration extends JFrame{
    //...
    private JFrame loader;
  

Но затем повторно объявите его в run вашем методе Runnable ….

 SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        JFrame loader = new JFrame("Loading....");
  

Это означает, что поле экземпляра по-прежнему равно нулю, попробуйте…

 SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
        loader = new JFrame("Loading....");
  

вместо этого…

Также…

 public void actionPerformed(ActionEvent arg0) {
    initLoadingPanel();
    csv = FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText());
    generateTableList(csv.getCsvTitle(), stateController.getFieldNames());
    loader.dispose();
}
  

Не собирается делать то, что, по вашему мнению, должно … вам «может» повезти, и loader появится фрейм, но, скорее всего, этого не произойдет, потому что вы блокируете поток отправки событий.

Вместо этого вам следует рассмотреть возможность использования SwingWorker ….

 initLoadingPanel();
SwingWorker worker = new SwingWorker<CVS, CVS>() {

    @Override
    protected CVS doInBackground() throws Exception {
        return FileReaderCSVHelper.fileReader(dirName.getText(), fileName.getText());
    }

    @Override
    protected void done() {
        try {
            cvs = get();
            generateTableList(csv.getCsvTitle(), stateController.getFieldNames());
        } catch (ExecutionException ex) {
            ex.printStackTrace();
        }
        loader.dispose();
    }

};
worker.execute();
  

(Я не знаю, что это за тип cvs , поэтому я предполагаю…

Это гарантирует, что ваш пользовательский интерфейс будет оставаться отзывчивым во время загрузки данных…

Взгляните на параллелизм в Swing

Обновление с рабочим примером….

Пример

 import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;

public class DataMigration extends JFrame {

    private JFrame frmDataMigration;

    private JFrame loader;

    private JButton btnProcess;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    DataMigration window = new DataMigration();
                    window.frmDataMigration.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public DataMigration() {
        initialize();
    }

    private void initialize() {

        frmDataMigration = new JFrame();

        btnProcess = new JButton("Load");
        btnProcess.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                initLoadingPanel();
                SwingWorker worker = new SwingWorker() {

                    @Override
                    protected Object doInBackground() throws Exception {
                        Thread.sleep(5000);
                        return "This is a test value used to highlight the example";
                    }

                    @Override
                    protected void done() {
                        try {
                            get();
                        } catch (ExecutionException ex) {
                        } catch (InterruptedException ex) {
                        }
                        loader.dispose();
                        btnProcess.setEnabled(true);
                    }

                };
                worker.execute();
                btnProcess.setEnabled(false);
            }
        });
        frmDataMigration.getContentPane().add(btnProcess);
        frmDataMigration.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frmDataMigration.pack();
        frmDataMigration.setLocationRelativeTo(null);
    }

    public void initLoadingPanel() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                loader = new JFrame("Loading....");
                ImageIcon img = new ImageIcon("loader.gif");
                loader.add(new JLabel(" Loading...", img, JLabel.CENTER));

                loader.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
                loader.setAlwaysOnTop(true);
                loader.pack();
                loader.setSize(448, 497);
                loader.setVisible(true);
                loader.setLocationRelativeTo(null);
            }
        });

    }
}
  

Комментарии:

1. Я сталкиваюсь со следующей ошибкой при вызове исключения loader.dispose() в потоке «AWT-EventQueue-0» java.lang. Исключение NullPointerException

2. Это (предположительно) потому, что вы объявили loader в локальном контексте внутри run метода. Вместо JFrame loader = new JFrame("Loading...."); этого вы могли бы попробовать loader = new JFrame("Loading...."); , предполагая, что loader это объявлено как переменная экземпляра. Также обратите внимание, что вы также должны вызывать dispose в контексте EDT

3. Привет, я обновил свой код в соответствии с вашим предложением, но я все еще сталкиваюсь с ошибкой в строке loader.dispose()

4. Я сделал простой, доступный для выполнения пример (у меня нет вашего резюме, поэтому я его подделал)