Search code examples
javaswingtimer

Swing window doesn't return value after x time


I'm trying to do a call simulator in Swing and for some reason the window won't budge.

My goal is to open a seperate window that returns true or false if a button is pressed or another has been pressed. The user should have 15 seconds to do something, otherwise it returns false and performs an action.

When it returns, it should finish it's execution. This function is called by another function part of main.

However, due to my lack of experience and idiocy, it doesn't work. Instead, it opens a window (blank) that never closes by itself when it should...

Here's the code:

public static boolean callWindow(Telephone src, Telephone dst) {

        Timer t1 = new Timer(15000, e-> {
            DateTime date = new DateTime();
            Call c = new Call(date, src.getTelephone(), dst.getTelephone(), 0);
            dst.addLostCall(c);
        });

        //Janela para atender
        JFrame window = new JFrame();
        window.setTitle("Incoming Call");

        JLabel telephones = new JLabel();
        telephones.setText("From: " + src.getTelephone() + "    To: " + dst.getTelephone() );

        JButton answerCall = new JButton("Answer");
        JButton denyCall = new JButton("Decline");

        JLabel status = new JLabel();
        answerCall.addActionListener( e -> status.setText("answer") );
        denyCall.addActionListener( e -> status.setText("no answer") );

        answerCall.setBackground(Color.GREEN);
        denyCall.setBackground(Color.RED);

        JPanel callInfo = new JPanel();
        callInfo.add(telephones);

        JPanel callOptions = new JPanel();
        callOptions.add(answerCall);
        callOptions.add(denyCall);

        Container container = window.getContentPane();
        container.add(callInfo, BorderLayout.NORTH);
        container.add(callOptions);

        window.setSize(350,120);
        window.setVisible(true);

        t1.start();
        while (t1.isRunning()) {
            if (status.getText().equals("answer")) return true;
            if (status.getText().equals("no answer")) return false;
        }

        return false;

    }

I would appreciate to know how this could work and how to despaghettify this horrible code.


Solution

  • I used a JDialog to demonstrate how to close a window after 15 seconds.

    Here's the GUI JFrame I created.

    GUI JFrame

    Here's the JDialog I created

    GUI JDialog

    The JDialog will dispose after 15 seconds. The isAnswered method will return true if the call was answered or false if the call was declined, the JDialog was closed by left-clicking on the X, or when the 15 seconds runs out.

    Here's the complete runnable code.

    import java.awt.BorderLayout;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.BorderFactory;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    import javax.swing.Timer;
    
    public class JDialogTimedGUI implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new JDialogTimedGUI());
        }
        
        private JFrame frame;
    
        @Override
        public void run() {
            frame = new JFrame("JDialog Timed GUI");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.add(createMainPanel(), BorderLayout.CENTER);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
        
        private JPanel createMainPanel() {
            JPanel panel = new JPanel(new BorderLayout());
            panel.setBorder(BorderFactory.createEmptyBorder(
                    75, 100, 75, 100));
            panel.setPreferredSize(new Dimension(400, 200));
    
            JButton button = new JButton("Open JDialog");
            button.addActionListener(new ButtonListener());
            panel.add(button);
    
            return panel;
        }
        
        public class ButtonListener implements ActionListener {
    
            @Override
            public void actionPerformed(ActionEvent event) {
                IncomingCall ic = new IncomingCall(frame, "Incoming Call", 
                        "555-1212", "555-2323");
                System.out.println("Incoming call: " + ic.isAnswered());
            }
    
        }
        
        public class IncomingCall extends JDialog {
            
            private static final long serialVersionUID = 1L;
            
            private boolean answered;
            
            private Timer timer;
    
            public IncomingCall(JFrame frame, String title, 
                    String sourcePhone, String destinationPhone) {
                super(frame, true);
                this.answered = false;
                
                setDefaultCloseOperation(DISPOSE_ON_CLOSE);
                setTitle(title);
    
                add(createMainPanel(frame, sourcePhone, destinationPhone));
                pack();
                setLocationRelativeTo(frame);
                
                timer = new Timer(15000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent event) {
                        setVisible(false);
                        dispose();
                        timer.stop();
                    }
                });
                timer.start();
                
                setVisible(true);
            }
            
            private JPanel createMainPanel(JFrame frame, 
                    String sourcePhone, String destinationPhone) {
                JPanel panel = new JPanel(new BorderLayout(5, 5));
                panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
                
                String s = "From: " + sourcePhone + "    To: " + destinationPhone;
                JLabel telephones = new JLabel(s);
                panel.add(telephones, BorderLayout.BEFORE_FIRST_LINE);
                
                JPanel callOptions = new JPanel();
                
                CallButtonListener listener = new CallButtonListener(this);
                
                JButton answerCall = new JButton("Answer");
                answerCall.addActionListener(listener);
                answerCall.setBackground(Color.GREEN);
                callOptions.add(answerCall);
                
                JButton denyCall = new JButton("Decline");
                denyCall.addActionListener(listener);
                denyCall.setBackground(Color.RED);
                callOptions.add(denyCall);
                
                panel.add(callOptions, BorderLayout.CENTER);
                
                return panel;
            }
    
            public void setAnswered(boolean answered) {
                this.answered = answered;
            }
    
            public boolean isAnswered() {
                return answered;
            }
            
        }
        
        public class CallButtonListener implements ActionListener {
            
            private IncomingCall incomingCall;
    
            public CallButtonListener(IncomingCall incomingCall) {
                this.incomingCall = incomingCall;
            }
    
            @Override
            public void actionPerformed(ActionEvent event) {
                JButton button = (JButton) event.getSource();
                if (button.getText().equals("Answer")) {
                    incomingCall.setAnswered(true);
                } else {
                    incomingCall.setAnswered(false);
                }
                incomingCall.dispose();
            }
            
        }
    
    }