我正在尝试为RGBike POV构建用户界面:
 http://www.instructables.com/id/RGBike-POV-Open-project/
该程序将以网格形式显示自行车车轮。用户可以点击
到单个正方形上并更改其颜色。
我想用Java构建这个applet。我一直坚持以正确的方式画轮子。
我需要每个矩形都有一种数组,以便以后导出颜色。
最好的办法是画一张圆桌。绘制每个形状
使用graphics2D将每个对象作为一个对象也是一个想法。但是那会
大约有860个单一形状,每次通过paint()对其进行更新都太多了。

Spoke POV已经为其项目完成了这样的用户界面:
 http://www.ladyada.net/make/spokepov/software.html
但是只有旧的python脚本是开源的。

最佳答案

非常感谢我以前曾经生成过“ segment”形状;)



基本上,这会分别生成每个片段(将某些片段时髦地转换为真实空间),并维护形状的缓存,可以检查形状是否为鼠标是否落在该范围内。

这是相当低效的,但我认为您可以理解。

还应该指出的是,我没有打扰后备缓冲区。并不是说它可以使用一个,我只是没有它就逃脱了...

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);
        }
    }
}

关于java - Graphics2D圆 table ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14617849/

10-11 04:37