1

私はJavaでコンパスに取り組んでいます。最初に、コンパスのUIプロトタイプを作成し、その実用的なSSCCEを作成しました。ここで、パネルをクリックすると、針が約15度異なる別の方向に向けられます。これはコードです:

public class TestFrame extends JFrame {

    public TestFrame() {
        initComponents();
    }

    public void initComponents() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocation(new Point((int) (Toolkit.getDefaultToolkit().getScreenSize().width / 2) - 400, (int) (Toolkit.getDefaultToolkit().getScreenSize().height / 2) - 250));
        setSize(500, 500);
        setVisible(true);
        CompassPanel c = new CompassPanel();
        add(c, BorderLayout.CENTER);

    }

    public class CompassPanel extends JPanel {
        Image bufImage;
        Graphics bufG;
        private int circleX, circleY, circleRadius;
        private int[] xPoints, yPoints;
        private double rotationAngle = Math.toRadians(0);

        public CompassPanel() {
            setVisible(true);

            addMouseListener(new MouseListener() {
                @Override
                public void mouseReleased(MouseEvent e) {
                }

                @Override
                public void mousePressed(MouseEvent e) {
                }

                @Override
                public void mouseExited(MouseEvent e) {
                }

                @Override
                public void mouseEntered(MouseEvent e) {
                }

                @Override
                public void mouseClicked(MouseEvent e) {
                    rotationAngle = rotationAngle + Math.toRadians(15);
                    repaint();
                }
            });

        }

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            circleRadius = (int) (getWidth() * 0.7);
            circleX = 50;
            circleY = 50;

            g2d.setColor(Color.BLACK);
            for (int angle = 0; angle <= 360; angle += 5) {
                double sin = Math.sin(Math.toRadians(angle));
                double cos = Math.cos(Math.toRadians(angle));
                int x1 = (int) ((circleX + circleRadius / 2) - cos  * (circleRadius * 0.37) - sin * (circleRadius * 0.37));
                int y1 = (int) ((circleY + circleRadius / 2) + sin  * (circleRadius * 0.37) - cos * (circleRadius * 0.37));
                g2d.setColor(Color.BLACK);
                g2d.drawLine(x1, y1, (circleX + circleRadius / 2), (circleY + circleRadius / 2));
            }

            g2d.setFont(new Font("Arial", Font.BOLD, 11));
            g2d.drawString("WEST", circleX - 45, circleY + circleRadius / 2 + 4);
            g2d.drawString("EAST", circleX + circleRadius + 13, circleY + circleRadius / 2 + 4);
            g2d.drawString("NORTH", circleX + circleRadius / 2 - 14, circleY - 15);
            g2d.drawString("SOUTH", circleX + circleRadius / 2 - 14, circleY + circleRadius + 25);
            g2d.setColor(Color.WHITE);
            g2d.fillOval(circleX, circleY, circleRadius, circleRadius);
            g2d.setColor(Color.BLACK);
            g2d.drawOval(circleX, circleY, circleRadius, circleRadius);

            xPoints = new int[] { (int) (circleX + circleRadius / 2),
                    (int) (circleX + circleRadius * 0.25),
                    (int) (circleX + circleRadius / 2),
                    (int) (circleX + circleRadius * 0.75) };

            yPoints = new int[] { (int) (circleY + 30),
                    (int) (circleY + circleRadius * 0.85),
                    (int) (circleY + circleRadius * 0.6),
                    (int) (circleY + circleRadius * 0.85) };

            Polygon fillPoly = new Polygon(xPoints, yPoints, 4);
            Polygon outerPoly = new Polygon(xPoints, yPoints, 4);

            int rotationX = circleX + (circleRadius / 2);
            int rotationY = circleX + (circleRadius / 2);

            g2d.setColor(Color.green);
            g2d.fillOval(rotationX, rotationY, 5, 5);

            AffineTransform a = g2d.getTransform().getRotateInstance(rotationAngle, rotationX, rotationY);
            g2d.setTransform(a);

            g2d.setColor(Color.RED);
            g2d.fillPolygon(fillPoly);

            g2d.setColor(Color.black);
            g2d.draw(outerPoly);
        }

        @Override
        public void update(Graphics g) {
            int w = this.getSize().width;
            int h = this.getSize().height;

            if (bufImage == null) {
                bufImage = this.createImage(w, h);
                bufG = bufImage.getGraphics();
            }

            bufG.setColor(this.getBackground());
            bufG.fillRect(0, 0, w, h);
            bufG.setColor(this.getForeground());

            paint(bufG);
            g.drawImage(bufImage, 0, 0, this);
        }

        public void setRotationAngle(int angle) {
            rotationAngle = angle;
        }
    }

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

このパネルをアプリケーションに実装すると、SSCCEのように針が描画されません。それは少し高く描かれ、位置の左側にあるはずです。パネルをクリックして針を回転させると、回転がうまく機能し、針が属する場所にペイントされます。

このようなパネルをアプリケーションに追加します。SensorPanelはJPanelにありTabbedPaneます。

public JPanel createSensorPanel(){
    sensorPanel = new JPanel(new MigLayout("fill, insets 3"));
    CompassPanel compassPanel = new CompassPanel();
    sensorPanel.add(compassPanel, "wrap");
    return sensorPanel;
}

PolygonSSCCEで針が引かれた位置に針が引かれないのはなぜですか?

編集:

これが問題の写真です。写真

4

1 に答える 1

2

画像で何が起こっているかをよく見ると、アフィン変換が問題になっています。

ここに画像の説明を入力してください

アフィン変換は、現在の子コンポーネントではなく、最上位の親に関連しているように見えます(java Affine Transformの正しい順序を参照)。

迅速で汚い解決策は、親が翻訳されるときに矢印を翻訳することです(この回答に基づいて)

AffineTransform a = g2d.getTransform().
    getRotateInstance(rotationAngle, rotationX, rotationY)
    .translate(parent.getX(), parent.getY()) // use instance of real parent instead
    .translate(tabpane.getX(), tabpane.getY()); // use instance of JTabbedPane instead

しかし、はるかに便利なのは、このような一般的な解決策です。

于 2013-01-03T21:16:34.003 に答える