Graphics2D的圆形表 [英] Graphics2D circular table

查看:334
本文介绍了Graphics2D的圆形表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想建立一个用户界面的RGBike POV:
  http://www.instructables.com/id/RGBike-POV-Open-项目/
该方案将在网格的形式显示一个自行车轮。用户可以点击
到单一的广场和改变这些颜色。
我想建立该applet在java中。我被困在以正确的方式绘制车轮。
我需要有一种每个矩形阵列,以色彩后出口。
最好的事情是制定一种圆形表。绘制每个形状
用的Graphics2D让每个作为单个对象将是一个想法,太。但是,这将
大约860单的形状,有点太多由油漆每次更新它们()。

I'm trying to build a User Interface for the RGBike POV: http://www.instructables.com/id/RGBike-POV-Open-project/ The program will display a bike wheel in form of a grid. The user can click onto the single squares and changes the colour of these. I want to build this applet in java. I'm stuck at drawing the wheel in the right way. I need to have a sort of array of every rectangle, to export the colour later. The best thing would be to draw a sort of circular table. Drawing each shape With graphics2D to have each as a single object would be an idea, too. But that would be around 860 single shapes, little bit too much to update them every time by paint().

说着POV做过这样的用户界面,为他们的项目已经:
  http://www.ladyada.net/make/spokepov/software.html
但是,只有他们的老python脚本是开源的。
 感谢您的帮助家伙!

Spoke POV has done such a user Interface for their project already: http://www.ladyada.net/make/spokepov/software.html But only their old python script is open source. Thanks for your help Guys!

推荐答案

很感激,我有previously产生了过去段形;)

Be VERY grateful that I have previously generate a "segment" shape in the past ;)

这基本上是单独生成每个段(做一些时髦的翻译转化为现实的空间),并保持它可以检查,看看是否鼠标落在那里范围内形状的缓存。

This basically generates each segment individually (does some funky translation into real space) and maintains a cache of shapes which can be checked to see if the mouse falls within there bounds.

这是相当低效的,但我觉得你的想法。

This is rather inefficient, but I think you get the idea.

我还应该注意的是,我没有后备缓冲器麻烦。并不是说,它可以使用一个,我刚才离开了,没有它...

I should also be noted, that I didn't bother with a backing buffer. Not to say it could use one, I just got away without it...

public class TestSpoke {

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

    public TestSpoke() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public static class TestPane extends JPanel {

        public static final int CIRCLE_COUNT = 16;
        public static final int SEGMENT_COUNT = 80;
        private Map<Integer, List<Shape>> mapWheel;
        private Map<Point, Color> mapColors;

        public TestPane() {
            mapColors = new HashMap<>(CIRCLE_COUNT * SEGMENT_COUNT);
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {

                    Map<Integer, List<Shape>> mapWheel = getWheel();

                    for (Integer circle : mapWheel.keySet()) {
                        List<Shape> segments = mapWheel.get(circle);
                        for (int index = 0; index < segments.size(); index++) {
                            Shape segment = segments.get(index);
                            if (segment.contains(e.getPoint())) {
                                mapColors.put(new Point(circle, index), Color.RED);
                                repaint();
                                break;
                            }
                        }
                    }
                }
            });
        }

        @Override
        public void invalidate() {
            mapWheel = null;
            super.invalidate();
        }

        protected float getRadius() {
            return Math.min(getWidth(), getHeight());
        }

        /**
         * This builds a wheel (if required) made of segments.
         * @return 
         */
        protected Map<Integer, List<Shape>> getWheel() {
            if (mapWheel == null) {
                mapWheel = new HashMap<>(CIRCLE_COUNT);

                // The current radius
                float radius = getRadius();
                // The radius of each individual circle...
                float circleRadius = radius / CIRCLE_COUNT;
                // The range of each segment
                float extent = 360f / SEGMENT_COUNT;
                for (int circle = 0; circle < CIRCLE_COUNT; circle++) {
                    float startAngle = 0;
                    List<Shape> segments = new ArrayList<>(SEGMENT_COUNT);
                    mapWheel.put(circle, segments);

                    // Calculate the "translation" to place each segement in the
                    // center of the screen
                    float innerRadius = circleRadius * circle;
                    float x = (getWidth() - innerRadius) / 2;
                    float y = (getHeight() - innerRadius) / 2;
                    for (int seg = 0; seg < SEGMENT_COUNT; seg++) {
                        // Generate a Segment shape
                        Segment segment = new Segment(circleRadius * circle, circleRadius, startAngle, extent);
                        startAngle += extent;

                        // We translate the segment to the screen space
                        // This will make it faster to paint and check for mouse clicks
                        PathIterator pi = segment.getPathIterator(AffineTransform.getTranslateInstance(x, y));
                        Path2D path = new Path2D.Float();
                        path.append(pi, true);
                        segments.add(path);
                    }
                }
            }

            return mapWheel;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            Graphics2D g2d = (Graphics2D) g.create();

            Map<Integer, List<Shape>> mapWheel = getWheel();
            for (Integer circle : mapWheel.keySet()) {

                List<Shape> segments = mapWheel.get(circle);
                for (int index = 0; index < segments.size(); index++) {
                    Shape segment = segments.get(index);

                    Color color = mapColors.get(new Point(circle, index));
                    if (color != null) {
                        g2d.setColor(color);
                        g2d.fill(segment);
                    }
                    g2d.setColor(Color.BLACK);
                    g2d.draw(segment);
                }
            }

            g2d.dispose();

        }

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

    public static class Segment extends Path2D.Float {

        public Segment(float radius, float thickness, float extent) {
            this(radius, thickness, 0f, extent);
        }

        public Segment(float radius, float thickness, float startAngle, float extent) {
            // Basically, we want to draw the outter edge from a to b angle,
            // draw the connecting line from the outter to the inner,
            // draw the inner from b to a angel and
            // draw the connecting line from the inner to out the outter

            // We want to span about 30 degrees, with a small gap...
            // I want the gap to be a factor of the radius

            Arc2D.Float outter = new Arc2D.Float(0, 0, radius, radius, startAngle, extent, Arc2D.OPEN);
            Arc2D.Float inner = new Arc2D.Float(thickness / 2f, thickness / 2f, radius - thickness, radius - thickness, startAngle + extent, -extent, Arc2D.OPEN);

            append(outter, true);

            float angel = startAngle + extent;
            Point2D p1 = getPointOnEdge(angel, radius);
            Point2D p2 = getPointOnEdge(angel, radius - thickness);
            // We need to adjust in for the change in the radius
            p2.setLocation(p2.getX() + (thickness / 2f), p2.getY() + (thickness / 2f));
            lineTo(p2.getX(), p2.getY());

            append(inner, true);

            angel = startAngle;
            p1 = getPointOnEdge(angel, radius);
            p2 = getPointOnEdge(angel, radius - thickness);
            p2.setLocation(p2.getX() + (thickness / 2f), p2.getY() + (thickness / 2f));
            lineTo(p1.getX(), p1.getY());

            closePath();
        }

        public Point2D getPointOnEdge(float angel, float radius) {
            angel -= 90;

            float x = radius / 2f;
            float y = radius / 2f;

            double rads = Math.toRadians((angel + 90));

            // This determins the length of tick as calculate from the center of
            // the circle.  The original code from which this derived allowed
            // for a varible length line from the center of the cirlce, we
            // actually want the opposite, so we calculate the outter limit first
            float fullLength = (radius / 2f);

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

            return new Point2D.Float(xPosy, yPosy);
        }
    }
}

这篇关于Graphics2D的圆形表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆