2

I have a swing application. I'm trying show a loading glass pane while reading the data from the database. But the behavior is not what i was expecting.

public class Sample {
                    JFrame frame;
                    JPanel loadingPanel;
                    JLabel iconLabel;
                    JPanel glassPane;

                    private PropertyChangeSupport changeListeners = new PropertyChangeSupport(this);

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

                    public Sample () {
                        initialize();
                    }


                    private void initialize() {
                        frame = new JFrame();
                        frame.setBounds(100, 100, 450, 300);
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                        JPanel panel = new JPanel();
                        panel.setSize(new Dimension(500,500));
                        frame.getContentPane().add(panel);
                        panel.setLayout(null);

                        // ---------Select button--------------------------------
                        JButton btnSelect = new JButton("Select");
                        btnSelect.addActionListener(loadDataActionListner);
                        btnSelect.setBounds(132, 7, 137, 32);
                        btnSelect.setFocusPainted(false);
                        panel.add(btnSelect);


                        glassPane = new GlassPanel();
                        glassPane.setOpaque(false);
                        glassPane.setLayout(new GridBagLayout());
                        glassPane.add(new JLabel("loading... "));
                        frame.setGlassPane(glassPane);

                        ChangeListener listener = new ChangeListener(this);
                        changeListeners.addPropertyChangeListener(listener);
                    }

                    public void changeVisibility(boolean  visibility){
                       glassPane.setVisible(visibility);
                       frame.validate();
                       frame.repaint();
                    }


                    ActionListener loadDataActionListner = new ActionListener() {
                        public void actionPerformed(ActionEvent e) {
                          SwingUtilities.invokeLater(new Runnable() {
                          @Override
                          public void run() {
                            JFileChooser fileChooser = new JFileChooser();
                            fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
                            int result = fileChooser.showOpenDialog(frame);
                            if (result == JFileChooser.APPROVE_OPTION) {

                                changeListeners.firePropertyChange("visibility", false, true); //Line 01
                                Response response = DataManager.getInstance().loadData("myfile.txt");
                                changeListeners.firePropertyChange("visibility", true, false);

                            }
                           }
                          });

                        }
                    };
                }

        public class GlassPaneUpdateWorker extends SwingWorker<Object, Boolean> {

            private boolean visibility;
            private Sample sample;

            public GlassPaneUpdateWorker(Sample  sample) {
                this.sample = sample;
            }

            @Override
            protected Object doInBackground() throws Exception {
                publish(visibility);
                return null;
            }

            @Override
            protected void process(List<Boolean> chunks) {
                if (chunks != null && !chunks.isEmpty()) {
                    sample.changeVisibility(chunks.get(0));
                }
            }

            protected void changeVisibility(boolean visibility) {
                this.visibility = visibility;
            }

        }

        public class ChangeListener  implements PropertyChangeListener{

            private Sample sample;

            public ChangeListener(Sample sample) {
                this.sample =  sample;
            }

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                GlassPaneUpdateWorker glassPaneUpdater = new GlassPaneUpdateWorker(sample);
                glassPaneUpdater.changeVisibility((Boolean)evt.getNewValue());
                glassPaneUpdater.execute();
            }

        }

Loading glass panel appear after all the code block is executed in the actionPerformed method. How can i change this, so that UI is updated just after "Line 01" execution.?

aravindaM
  • 978
  • 8
  • 15
  • 1
    Avoid using `null` layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify – MadProgrammer Jul 13 '15 at 07:41
  • Take a look at [Concurrency in Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) and [Worker Threads and SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) – MadProgrammer Jul 13 '15 at 07:41
  • For [example](http://stackoverflow.com/questions/23125642/swingworker-in-another-swingworkers-done-method/23126410#23126410), [example](http://stackoverflow.com/questions/24835638/issues-with-swingworker-and-jprogressbar/24835935#24835935), [example](http://stackoverflow.com/questions/27629027/swing-progress-bar-updates-via-worker-to-eventdispatch-thread/27629291#27629291) – MadProgrammer Jul 13 '15 at 07:42
  • @MadProgrammer I change my code to use SwingWorker. But i still get the same result. What am i missing here? – aravindaM Jul 14 '15 at 02:47
  • I'm "guessing" you're still calling ` Response response = DataManager.getInstance().loadData("myfile.txt");` within the context of the EDT – MadProgrammer Jul 14 '15 at 02:51
  • @MadProgrammer Even with that no luck. However thank you for the directions. It helped a lot for understanding the Swing Threading model. – aravindaM Jul 14 '15 at 03:32
  • 1
    You are using SwingWorker incorrectly. You would like to put "Response response = DataManager.getInstance().loadData("myfile.txt");" inside doInBackground(). This way you would be able to run your DB operation in separate thread than the event-dispatch thread. – Rahul Winner Jul 16 '15 at 10:41
  • @RahulWinner Yah. It took sometime to figure out the correct way to use the SwingWorker. – aravindaM Jul 16 '15 at 16:04

1 Answers1

2

I was able to get this done by using the SwingWorker as follows, without any listeners.

ActionListener loadDataActionListner = new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
                    int result = fileChooser.showOpenDialog(frame);
                    if (result == JFileChooser.APPROVE_OPTION) {
                        SwingWorker<?, ?> worker = new SwingWorker<Void, Integer>() {
                            protected Void doInBackground() {
                                showLoadingPanel();
                                Response response = DataManager.getInstance().loadData("myfile.txt");
                                hideLoadingPanel();
                                //Do something..
                                return null;
                            }
                        };
                        worker.execute();

                    }
                }
            });

        }
    };
aravindaM
  • 978
  • 8
  • 15