0

For some reason, my ClockComponent object does not show up when I add it to a JPanel object. It DOES show up when I add it to a JFrame object but not a JPanel object... I don't understand why and I've looked it up before posting this question here but to no avail. Is there any way to make my ClockComponent object which inherits from JComponent to show up on a JPanel? Thank you so much for your help in advance.

Here's my ClockViewer class which won't display a clock when run:

            import javax.swing.JFrame;
            import javax.swing.JPanel;

            public class ClockViewer
            {
                public static void main(String[] args)
                {
                    JFrame frame = new JFrame();
                    frame.setTitle("Clock viewer");
                    frame.setSize(500, 500);
                    JPanel panel = new JPanel();

                    ClockComponent comps = new ClockComponent(7, 40);

                    panel.add(comps);
                    frame.add(panel);

                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setVisible(true);
                }
            }

And here's my ClockComponent class for reference:

            import java.awt.Graphics;
            import java.awt.Graphics2D;
            import java.awt.geom.Ellipse2D;
            import java.awt.geom.Line2D;

            import javax.swing.JComponent;

            public class ClockComponent extends JComponent
            {
                final int CENTER = 150;
                final double HOUR_HAND_LENGTH = 20;
                final double MINUTE_HAND_LENGTH = 40;

                private Line2D.Double hourHand;
                private Line2D.Double minuteHand;

                public ClockComponent(double hour, double minute)
                {
                    hourHand = new Line2D.Double(CENTER, CENTER, 
                            CENTER, CENTER - HOUR_HAND_LENGTH);
                    minuteHand = new Line2D.Double(CENTER, CENTER, 
                            CENTER, CENTER - MINUTE_HAND_LENGTH);

                    final int HOURS_ON_CLOCK = 12;
                    final int MINUTES_IN_HOUR = 60;
                    final double HOURS_TO_RADIANS = 2 * Math.PI / HOURS_ON_CLOCK;
                    final double MINUTES_TO_RADIANS = 2 * Math.PI / MINUTES_IN_HOUR;

                    hourHand.setLine(CENTER, CENTER, CENTER + HOUR_HAND_LENGTH * 
                            Math.sin((hour + minute / MINUTES_IN_HOUR) * HOURS_TO_RADIANS), 
                            CENTER - HOUR_HAND_LENGTH * 
                            Math.cos((hour + minute / MINUTES_IN_HOUR) * HOURS_TO_RADIANS));
                    minuteHand.setLine(CENTER, CENTER,
                            CENTER + MINUTE_HAND_LENGTH * Math.sin(minute * MINUTES_TO_RADIANS),
                            CENTER - MINUTE_HAND_LENGTH * Math.cos(minute * MINUTES_TO_RADIANS));
                }

                public void paintComponent(Graphics g)
                {
                    final int DIAMETER = 100;
                    final int POS_X_Y = CENTER - DIAMETER / 2;

                    Graphics2D g2 = (Graphics2D) g;

                    Ellipse2D.Double clockFace = 
                            new Ellipse2D.Double(POS_X_Y, POS_X_Y, DIAMETER, DIAMETER);

                    g2.draw(clockFace);
                    g2.draw(hourHand);
                    g2.draw(minuteHand);
                }
            }
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user1800967
  • 953
  • 1
  • 6
  • 11

2 Answers2

3

In the panel, you could use a layout that makes the clock component fill the full area of the panel, such as GridLayout:

JPanel panel = new JPanel(new GridLayout(1, 0));

The default FlowLayout for the panel will not expand any of the child components.

Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • That certainly works... Thank you. Still, I wonder why it doesn't work without the GridLayout object in the explicit parameter... – user1800967 Nov 06 '12 at 00:17
  • Note also, in the case of a single component `new JPanel(new GridLayout(1, 0));` could be abbreviated to `new JPanel(new GridLayout());`. See [this answer](http://stackoverflow.com/a/7181197/418556) for e.g. – Andrew Thompson Nov 06 '12 at 00:22
2

ClockComponent should set or override the preferred size. Many prefer to override it if the component is not resizable. This example just sets it.

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class ClockComponent extends JComponent
{
    final int CENTER = 150;
    final double HOUR_HAND_LENGTH = 20;
    final double MINUTE_HAND_LENGTH = 40;

    private Line2D.Double hourHand;
    private Line2D.Double minuteHand;

    public ClockComponent(double hour, double minute)
    {
        setPreferredSize(new Dimension(300,300));
        hourHand = new Line2D.Double(CENTER, CENTER, 
                CENTER, CENTER - HOUR_HAND_LENGTH);
        minuteHand = new Line2D.Double(CENTER, CENTER, 
                CENTER, CENTER - MINUTE_HAND_LENGTH);

        final int HOURS_ON_CLOCK = 12;
        final int MINUTES_IN_HOUR = 60;
        final double HOURS_TO_RADIANS = 2 * Math.PI / HOURS_ON_CLOCK;
        final double MINUTES_TO_RADIANS = 2 * Math.PI / MINUTES_IN_HOUR;

        hourHand.setLine(CENTER, CENTER, CENTER + HOUR_HAND_LENGTH * 
                Math.sin((hour + minute / MINUTES_IN_HOUR) * HOURS_TO_RADIANS), 
                CENTER - HOUR_HAND_LENGTH * 
                Math.cos((hour + minute / MINUTES_IN_HOUR) * HOURS_TO_RADIANS));
        minuteHand.setLine(CENTER, CENTER,
                CENTER + MINUTE_HAND_LENGTH * Math.sin(minute * MINUTES_TO_RADIANS),
                CENTER - MINUTE_HAND_LENGTH * Math.cos(minute * MINUTES_TO_RADIANS));
    }

    public void paintComponent(Graphics g)
    {
        final int DIAMETER = 100;
        final int POS_X_Y = CENTER - DIAMETER / 2;

        Graphics2D g2 = (Graphics2D) g;

        Ellipse2D.Double clockFace = 
                new Ellipse2D.Double(POS_X_Y, POS_X_Y, DIAMETER, DIAMETER);

        g2.draw(clockFace);
        g2.draw(hourHand);
        g2.draw(minuteHand);
    }

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();
        frame.setTitle("Clock viewer");
        // bad practice
        //frame.setSize(500, 500);
        JPanel panel = new JPanel();

        ClockComponent comps = new ClockComponent(7, 40);

        panel.add(comps);
        frame.add(panel);
        // Good practice.
        frame.pack();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433