Перекраска в Swing JComponent после интервала - PullRequest
3 голосов
/ 21 сентября 2011

Мне был назначен проект, в котором я должен сделать аналоговые часы, используя объект GregorianCalendar в Java.Сначала нам сказали, чтобы часы работали так, чтобы они показывали правильное время при каждом запуске.Затем нам сказали перерисовывать часы на каждую секунду, когда они работают.Я сделал объект таймера и подумал, что могу добавить ActionListener и перерисовывать его каждый раз, когда вызывается actionPerformed, но перерисовка, очевидно, не может быть использована таким образом.Вот мой код:

    import javax.swing.*;
    import java.awt.event.*;
    import java.awt.geom.*;
    import java.awt.*;
    import java.util.Calendar;
    import java.util.GregorianCalendar;
    import java.util.Date;
    import javax.swing.Timer;
    import java.lang.Math;    

    public class SwingClock {

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                MyFrame frame = new MyFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                ActionListener listener = new TimePrinter();
                Timer t = new Timer(1000, listener);
                GregorianCalendar calendar = new GregorianCalendar();
                t.start();
                frame.setVisible(true);
            }
        });
    }
}

    class TimePrinter implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            //I'd like to repaint here every second, but I can't
        }
    }

    class MyFrame extends JFrame
    {
        public MyFrame()
        {
            setTitle("Swing Clock");
            setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);

            MyComponent component = new MyComponent();
            add(component);
        }

        public static final int DEFAULT_WIDTH = 500;
        public static final int DEFAULT_HEIGHT = 500;
    }

    class MyComponent extends JComponent
    {
        public void paint(Graphics g)
        {
            Graphics2D g2 = (Graphics2D)g;
            int leftX = 50, topY = 50, width = 300, height = 300;
            Rectangle2D rect = new Rectangle2D.Double(leftX, topY, width, height);

            Ellipse2D clockFace = new Ellipse2D.Double();
            clockFace.setFrame(rect);
            g2.draw(clockFace);

            double centerX = clockFace.getCenterX();
            double centerY = clockFace.getCenterY();
            GregorianCalendar calendar = new GregorianCalendar();
            int hour = calendar.get(Calendar.HOUR_OF_DAY);

            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);

            double minusMinute = (90 - (minute*6))*(Math.PI/180);           
            double minuteCosine = Math.cos(minusMinute);
            double minuteSine = Math.sin(minusMinute);

            double minusSecond = (90 - (second*6))*(Math.PI/180);
            double secondCosine = Math.cos(minusSecond);
            double secondSine = Math.sin(minusSecond);

            double hourTheta = (90-(hour+(minute/60)*30))*(Math.PI/180);
            g2.draw(new Line2D.Double(centerX,centerY,centerX+50*(Math.cos(hourTheta)),
                    centerY - 50*(Math.sin(hourTheta))));   
            g2.draw(new Line2D.Double(centerX,centerY,centerX+150*(minuteCosine),centerY-150*(minuteSine)));
        g2.draw(new Line2D.Double(centerX, centerY, centerX+100*secondCosine, 
                    centerY-100*(secondSine)));
        }
    }

Есть идеи, как это обойти?Может я ошибаюсь?

Ответы [ 3 ]

5 голосов
/ 21 сентября 2011

«Программы Swing должны переопределять paintComponent() вместо переопределения paint()», хотя, как вы увидите, это вовсе не обязательно. Во-вторых, вы правы в использовании javax.swing.Timer. В-третьих, почему бы вам не облегчить себе задачу и не использовать вместо него экземпляр JLabel для отображения времени?

2 голосов
/ 22 сентября 2011
  1. MyComponent должен быть определен как переменная класса в вашем классе MyFrame

  2. Таймер должен быть создан и запущен в вашем классе MyFrame.

  3. ActionListener для Timer должен вызвать перерисовку для вашей переменной MyComponent.

  4. Ваш класс MyComponent должен расширять JPanel, тогда вы можете просто вызвать super.paintComponent () в качестве первого оператора, чтобы очистить панель перед рисованием часов в новом времени.

0 голосов
/ 22 сентября 2011

Вы просто переопределяете конструктор Listener:

class TimePrinter implements ActionListener

{
    private MyFrame frame;
    TimePrinter(MyFrame frame){
        this.frame=frame;
    }
    public void actionPerformed(ActionEvent event)
    {
        frame.repaint();
    }
}


MyFrame frame = new MyFrame();
ActionListener listener = new TimePrinter(frame);
...