如何在java gui中将一个圆圈分成60个部分

时间:2016-01-31 17:17:23

标签: java swing user-interface geometry

我想要一个像时钟的二手一样工作但我有一个文本字段而不是时钟句柄的圆圈。例如,当时钟的二手为30时,文本字段位于最低点圆圈的位置和它的文本是30.但我不能将圆圈分成60个部分。请帮助我编辑我的代码。 我必须提到我正在使用Timer类。 这些是我的代码:

with Page(url) as page:

}

2 个答案:

答案 0 :(得分:3)

Swing是一个单线程环境,因任何原因阻塞EDT(如Thread.sleep的长时间循环)将阻止UI更新。 Swing也不是线程,并且永远不应该在EDT的上下文之外对UI进行更新

考虑到这一点,在Timer的每个刻度线上,你试图移动手柄时循环60次约30次,但手柄出现的唯一位置是它所在的最后位置。当actionPerformed方法退出时。

有关详细信息,请参阅Concurrency in Swing

您应该做的只是根据您在呼叫时的要求/需求将手柄放在当前位置

我一直在看你的计算......

handle.setBounds((int)(202 + 100 * Math.cos(angle)),
                 (int)(119 + 100 * Math.sin(angle)), 23, 26);

根据我的记忆,要根据角度找到圆上的点,你需要使用......

x = xOffset + Math.cos(radians) * radius;
y = yOffset - Math.sin(radians) * radius;

所以,有两件事要指出,但最重要的是Math.cosMath.sin期望值以弧度为单位,而不是度数

您还应该避免使用null布局,像素完美布局是现代ui设计中的错觉。影响组件个体大小的因素太多,您无法控制。 Swing旨在与布局管理器一起工作,放弃这些将导致问题和问题的结束,您将花费越来越多的时间来纠正。

你也应该避免以这种方式使用组件,而是考虑使用自定义绘画处理....

Simple Clock

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestClock {

    public static void main(String[] args) {
        new TestClock();
    }

    public TestClock() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new ClockPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    protected class ClockPane extends JPanel {

        public ClockPane() {
            Timer timer = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(false);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected Point getPointTo(float angle) {

            int x = Math.round(getWidth() / 2);
            int y = Math.round(getHeight() / 2);

            double rads = Math.toRadians(angle);
            // This is an arbitrary amount, you will need to correct for this
            // I'm working of a width of 200 pixels, so that makes the radius
            // 100...
            int radius = 100;

            // Calculate the outter point of the line
            int xPosy = Math.round((float) (x + Math.cos(rads) * radius));
            int yPosy = Math.round((float) (y - Math.sin(rads) * radius));

            return new Point(xPosy, yPosy);

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            g2d.setColor(Color.RED);

            Calendar cal = Calendar.getInstance();
            int seconds = cal.get(Calendar.SECOND);
            float angle = -(360f * (seconds / 60f));
            angle += 90; // Correct for 0 being out to the right instead of up

            Point p = getPointTo(angle);

            int x = getWidth() / 2;
            int y = getHeight() / 2;

            g2d.drawLine(x, y, p.x, p.y);

            FontMetrics fm = g2d.getFontMetrics();
            String text = Integer.toString(seconds);
            g2d.drawString(text, getWidth() - fm.stringWidth(text), getHeight() - fm.getHeight() + fm.getAscent());

            g2d.dispose();
        }
    }
}

有关详细信息,请查看Painting in AWT and SwingPerforming Custom Painting2D Graphics

答案 1 :(得分:0)

感谢您的指导非常有帮助,我已经解决了这个问题(通过删除for循环):

public void actionPerformed(ActionEvent arg0) {
            int intSecond = Integer.parseInt(handle.getText()) + 1;
            if (intSecond <= 60) {
                second = Integer.toString(intSecond);
                handle.setBounds(
                        (int) (Math.cos(intSecond * Math.PI / 30 - Math.PI
                                / 2) * 100 + 202),
                        (int) (Math.sin(intSecond * Math.PI / 30 - Math.PI
                                / 2) * 100 + 119), 17, 20);

                handle.setText(second);
            } else {
                timer.stop();
            }

        }

    });