Java - global, reusable loading dialog

后端 未结 2 1432
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-30 15:12

I\'m trying to implement a global loading dialog... I want to call some static function to show the dialog and some static function to close it. In the meanwhile I\'m doing

2条回答
  •  死守一世寂寞
    2020-11-30 15:31

    Swing uses a single thread model for it's event dispatching (including paint updates), as such, you should never, ever perform any long running or blocking operations within the Event Dispatching Thread (EDT).

    Swing is also not thread safe, meaning that you should never create or modify any UI component from outside the EDT.

    The basic concept of a global progress dialog is to provide a framework that is not depended on the work that needs to be performed, this separates the areas of responsibility, the progress dialog being responsible for displaying the progress and the worker/engine being responsible for doing the actual work.

    The simplest solution would be to use a SwingWorker. This provides mechanisms for executing long running tasks in a separate thread, state change and progress notification.

    enter image description here

    public class TestProgressDialog {
    
        public static void main(String[] args) {
            new TestProgressDialog();
        }
    
        public TestProgressDialog() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
    
                    SwingWorker worker = new SwingWorker() {
                        @Override
                        protected Object doInBackground() throws Exception {
                            for (int index = 0; index < 100; index++) {
                                Thread.sleep(50);
                                setProgress(index);
                            }
                            return null;
                        }
    
                    };
    
                    ProgressDialog.showProgress(null, worker);
    
                    System.exit(0);
    
                }
    
            });
        }
    
        public static class ProgressDialog extends JDialog {
    
            private JLabel message;
            private JLabel subMessage;
            private JProgressBar progressBar;
    
            public ProgressDialog(Component parent, SwingWorker worker) {
    
                super(parent == null ? null : SwingUtilities.getWindowAncestor(parent));
                setModal(true);
    
                ((JComponent)getContentPane()).setBorder(new EmptyBorder(8, 8, 8, 8));
    
                message = new JLabel("Doing important stuff");
                subMessage = new JLabel("Go make you're self a cup of coffee...");
                progressBar = new JProgressBar();
    
                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.insets = new Insets(2, 2, 2, 2);
                gbc.gridx = 0;
                gbc.gridy = 0;
                gbc.anchor = GridBagConstraints.WEST;
                add(message, gbc);
    
                gbc.gridy++;
                add(subMessage, gbc);
    
                gbc.gridy++;
                gbc.weightx = 1;
                gbc.fill = GridBagConstraints.HORIZONTAL;
                add(progressBar, gbc);
    
                pack();
    
                worker.addPropertyChangeListener(new PropertyChangeHandler());
                switch (worker.getState()) {
                    case PENDING:
                        worker.execute();
                        break;
                }
    
            }
    
            public static void showProgress(Component parent, SwingWorker worker) {
    
                ProgressDialog dialog = new ProgressDialog(parent, worker);
                dialog.setLocationRelativeTo(parent);
                dialog.setVisible(true);
    
            }
    
            public class PropertyChangeHandler implements PropertyChangeListener {
    
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (evt.getPropertyName().equals("state")) {
                        SwingWorker.StateValue state = (SwingWorker.StateValue) evt.getNewValue();
                        switch (state) {
                            case DONE:
                                dispose();
                                break;
                        }
                    } else if (evt.getPropertyName().equals("progress")) {
                        progressBar.setValue((int)evt.getNewValue());
                    }
                }
    
            }
    
        }
    
    }
    

提交回复
热议问题