#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2010
    Posts
    16
    Rep Power
    0

    Designing A GUI Clock


    I have to make a clock with various hands that ticks as the seconds go by. Here is my code:

    Code:
    package assignment07;
    
    import java.awt.BorderLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Line2D;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JTextField;
    import javax.swing.JLabel;
    import javax.swing.Timer;
    
    
    public class Problem2 {
    	private JFrame frame = new JFrame("Problem 2");
    	private Ellipse2D.Double ellipse;
    	private Line2D.Double hourHand;
    	private Line2D.Double minHand;
    	private Line2D.Double secHand;
    	private JTextField hours = new JTextField();
    	private JTextField minutes = new JTextField();
    	private JTextField seconds = new JTextField();
    	private JButton drawButton = new JButton("Draw"); 
    	private JLabel area = new JLabel();
    	private int sec;
    	private int min;
    	private int hour;
    
    	public Problem2() {
    		frame.add(new InputPane().createInputPane(hours, 
    				minutes, seconds, drawButton),
    				BorderLayout.PAGE_START);
    		ActionListener listener = new DrawListener();
    		drawButton.addActionListener(listener);
    		hours.addActionListener(listener);
    		minutes.addActionListener(listener);
    		seconds.addActionListener(listener);
    		frame.add(new DrawingArea(this));
    		frame.add(area, BorderLayout.PAGE_END);
    		frame.setSize(600,400);
    		frame.setLocationRelativeTo(null);
    		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    		frame.addWindowListener(new WindowCloser());
    		frame.setVisible(true);
    	}
    
    	public Ellipse2D getEllipse() {
    		return ellipse;
    	}
    
    	public Line2D getHourLine() {
    		return hourHand;
    	}
    
    	public Line2D getMinLine() {
    		return minHand;
    	}
    	public Line2D getSecHand() {
    		return secHand;
    	}
    	public int getSec() {
    		return sec;
    	}
    	public void setSec(int sec) {
    		this.sec = sec;
    	}
    	public int getMin() {
    		return min;
    	}
    	public int getHour() {
    		return hour;
    	}
    
    
    	public static void main(String[] args) {
    		javax.swing.SwingUtilities.invokeLater(new Runnable() {
    			public void run() {
    				new Problem2(); 
    			}
    		});
    	}
    
    	private class WindowCloser extends WindowAdapter {
    		public void windowClosing(WindowEvent evt) {
    			int result = JOptionPane.showConfirmDialog(frame, 
    					"Are you sure you wish to exit?",
    							"Confirmation Dialog",
    							JOptionPane.YES_NO_OPTION);
    			if(result == JOptionPane.YES_NO_OPTION) {
    				System.exit(0);
    			}
    		}
    	}
    
    	public class DrawListener implements ActionListener {
    		public void actionPerformed(ActionEvent evt) { 
    			ellipse = new Ellipse2D.Double(50, 50, 300, 300);
    
    
    			try {
    				hour = (60*60) * Integer.parseInt(hours.getText().trim());
    			} catch (NumberFormatException ex) {
    				JOptionPane.showMessageDialog(frame, "Your hour value is badly formatted");
    			}
    
    			try {
    				min = (60) * Integer.parseInt(minutes.getText().trim());
    			} catch (NumberFormatException ex) {
    				JOptionPane.showMessageDialog(frame, "Your minutes value is badly formatted");
    			}
    
    			try {
    				sec = Integer.parseInt(seconds.getText().trim());
    			} catch (NumberFormatException ex) {
    				JOptionPane.showMessageDialog(frame, "Your seconds value is badly formatted");
    			}
    
    			double secs = 2*Math.PI*(sec%60)/60 - Math.PI/2;
    			secHand = new Line2D.Double(ellipse.getCenterX(), ellipse.getCenterY(), ellipse.getCenterX()+(ellipse.getWidth()/2)*Math.cos(secs), ellipse.getCenterY()+(ellipse.getWidth()/2)*Math.sin(secs));
    
    			double mins = 2*Math.PI*(min%(60*60))/(60*60) - Math.PI/2;
    			minHand = new Line2D.Double(ellipse.getCenterX(), ellipse.getCenterY(), ellipse.getCenterX()+(.9 * ellipse.getWidth()/2)*Math.cos(mins), ellipse.getCenterY()+(.9 * ellipse.getWidth()/2)*Math.sin(mins));
    
    			double hrs = 2*Math.PI*(hour%(12*60*60))/(12*60*60) - Math.PI/2;
    			hourHand = new Line2D.Double(ellipse.getCenterX(), ellipse.getCenterY(), ellipse.getCenterX()+(.6 * ellipse.getWidth()/2)*Math.cos(hrs), ellipse.getCenterY()+(.6 * ellipse.getWidth()/2)*Math.sin(hrs));
    
    			new Timer(1000, new TimerListener()).start();
    
    			frame.repaint(); // will call paintComponent of DrawingArea
    		}
    	}
    
    	class TimerListener implements ActionListener {
    
    		@Override
    		public void actionPerformed(ActionEvent arg0) {
    			sec += 1;
    			sec = sec%60;
    			System.out.println(sec);
    			frame.repaint();
    
    
    		}
    	}
    }
    There is also a DrawingArea Class which contains paintComponent which actually draws the clock. And there is InputPane class which control user input from the GUI. The user tell the clock what time to start at (indicates hours, minutes, seconds) and the clock is supposed to draw itself up on the screen and then as each second goes by its supposed to redraw itself. Much of the above code is from my professor.

    So I created TimerListener and a timer which you can find in the DrawListener. I know my timer is working because I made it output the current value of seconds to the console. What isn't working is the following:

    Code:
    class TimerListener implements ActionListener {
    
    		@Override
    		public void actionPerformed(ActionEvent arg0) {
    			sec += 1;
    			sec = sec%60;
    			System.out.println(sec);
    			frame.repaint();
    
    
    		}
    	}
    When I say frame.repaint(); like I did in the DrawListener the clock does not redraw. I am confused as to why it is not redrawing? Any help would be great. Sorry about the messiness of the code. I was going to make a cleaner version once I got it working.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jan 2004
    Posts
    485
    Rep Power
    106
    Please post your InputPane and DrawingArea classes
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2010
    Posts
    16
    Rep Power
    0
    Here you go! Thanks!

    Code:
    package assignment07;
    
    import java.awt.BasicStroke;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.geom.Ellipse2D;
    import java.awt.geom.Line2D;
    import javax.swing.JComponent;
    
    
    public class DrawingArea extends JComponent {
    	private Problem2 owner;
    
    
    
    	public DrawingArea(Problem2 owner) {
    		this.owner = owner;
    
    	}
    
    	public Problem2 getProblem2() {
    		return owner;
    	}
    	/**
    	 * 
    	 */
    	@Override
    	protected void paintComponent(Graphics g) {
    		super.paintComponent(g);
    		Graphics2D g2 = (Graphics2D) g;
    
    		g2.setStroke(new BasicStroke(2));
    
    
    		Ellipse2D temp = owner.getEllipse();
    		Line2D tempHourHand = owner.getHourLine();
    		Line2D tempMinHand = owner.getMinLine();
    		Line2D tempSecHand = owner.getSecHand();
    
    		if(temp != null && tempHourHand != null && tempMinHand != null && tempSecHand != null) {
    			g2.draw(temp);
    			g2.draw(tempSecHand);
    			g2.setStroke(new BasicStroke(3));
    			g2.draw(tempMinHand);
    			g2.setStroke(new BasicStroke(4));
    			g2.draw(tempHourHand);
    		}
    	}
    }
    Code:
    package assignment07;
    import java.awt.BorderLayout;
    import java.awt.GridLayout;
    
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    
    public class InputPane {
    
        public JPanel createInputPane(JTextField inputX, 
                JTextField inputY,
                JTextField inputSide, 
                JButton drawButton) {
            JPanel topPart = new JPanel();
            topPart.setLayout(new GridLayout(1,0));
            topPart.add(new JLabel("Hours: ", JLabel.RIGHT));
            topPart.add(inputX);
            topPart.add(new JLabel("Minutes: ", JLabel.RIGHT));
            topPart.add(inputY);
            topPart.add(new JLabel("Seconds: ", JLabel.RIGHT));
            topPart.add(inputSide);
            JPanel panel = new JPanel();
            panel.setLayout(new BorderLayout());
            panel.add(topPart);
            panel.add(drawButton, BorderLayout.PAGE_END);
            return panel;
        }
    }
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2010
    Posts
    16
    Rep Power
    0
    Never mind I figured it out. Thanks for the help.
  8. #5
  9. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2005
    Location
    Internet
    Posts
    7,625
    Rep Power
    6087
    Do tell.

    Comments on this post

    • sunvsunv agrees : Need to share the solution as well
    Chat Server Project & Tutorial | WiFi-remote-control sailboat (building) | Joke Thread
    “Rational thinkers deplore the excesses of democracy; it abuses the individual and elevates the mob. The death of Socrates was its finest fruit.”
    Use XXX in a comment to flag something that is bogus but works. Use FIXME to flag something that is bogus and broken. Use TODO to leave yourself reminders. Calling a program finished before all these points are checked off is lazy.
    -Partial Credit: Sun

    If I ask you to redescribe your problem, it's because when you describe issues in detail, you often get a *click* and you suddenly know the solutions.
    Ches Koblents

IMN logo majestic logo threadwatch logo seochat tools logo