简体   繁体   English

无法获取Path2D.Double并使用.transform进行更改

[英]Trouble with getting Path2D.Double to change with .transform

My program is supposed to allow users to input the first six numbers of a matrix into text fields and then hit an apply button, changing the Path2D using the .transform method with the arguments being the six inputted numbers. 我的程序应该允许用户将矩阵的前六个数字输入到文本字段中,然后单击应用按钮,使用.transform方法更改Path2D,并将参数作为六个输入数字。 My problem is that whenever I type something in and hit apply, the transformation is extremely different than it should be and the original arrow remains behind as well. 我的问题是,每当我输入某些内容并单击应用时,转换与应该的转换都非常不同,并且原始箭头也保留在后面。

It's really bizarre and I have no clue where the problem is coming from. 这真的很奇怪,我不知道问题出在哪里。 Everything should be in the right spot with the Affine Transform, but the transformation is coming out all wrong. 借助仿射变换,一切都应该放在正确的位置,但是变换出了错。

This is what it should look like: 它应该是这样的: 在此处输入图片说明

This is what it looks like for me: 这对我来说是这样的: 在此处输入图片说明

I will put the full code below so you can run it yourself to see if you might be able to figure it out. 我将把完整的代码放在下面,以便您可以自己运行它,以查看是否可以找出答案。 Thank you! 谢谢!

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import javax.swing.event.*;

public class Project3 extends JPanel implements ActionListener {

    public static Project3 p = new Project3();
    Path2D.Double arrow = new Path2D.Double();
    public static JTextField
            num1 = new JTextField("1"), num2 = new JTextField("0"),
            num3 = new JTextField("0"), num4 = new JTextField("0"),
            num5 = new JTextField("1"), num6 = new JTextField("0");

    public Project3() {
        setBackground(Color.WHITE);
    }

    public Path2D.Double drawArrow() {
        arrow.setWindingRule(GeneralPath.WIND_EVEN_ODD);
        arrow.moveTo(0, 0);
        arrow.lineTo(0, -100); 
        arrow.moveTo(0, -200);
        arrow.lineTo(100, -100);
        arrow.lineTo(50, -100);
        arrow.lineTo(50, 100);
        arrow.quadTo(0, 0, -50, 100);
        arrow.lineTo(-50, -100);
        arrow.lineTo(-100, -100);
        arrow.lineTo(0, -200);
        arrow.closePath();
        return arrow;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(250, 250);
        GradientPaint gradient = new GradientPaint(0, 0, Color.LIGHT_GRAY, 15, 15, Color.BLACK, true);
        g2.setPaint(gradient);
        g2.setStroke(new BasicStroke(12, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
        g2.draw(drawArrow());
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Project 3");
        frame.setSize(500, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container cp = frame.getContentPane();
        cp.setLayout(new BorderLayout());

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        cp.add(panel, BorderLayout.CENTER);
        panel.add(p, BorderLayout.CENTER);
        panel = new JPanel();
        panel.setLayout(new GridLayout(0, 2));
        cp.add(panel, BorderLayout.SOUTH);

        JPanel textPanel = new JPanel();
        textPanel.setLayout(new GridLayout(2, 3));
        panel.add(textPanel);
        textPanel.add(num1);
        textPanel.add(num2);
        textPanel.add(num3);
        textPanel.add(num4);
        textPanel.add(num5);
        textPanel.add(num6);

        JPanel btPanel = new JPanel();
        btPanel.setLayout(new GridLayout(0, 1));
        panel.add(btPanel);
        JButton apply = new JButton("Apply");
        apply.addActionListener(p);
        btPanel.add(apply);
        JButton reset = new JButton("Reset");
        reset.addActionListener(p);
        btPanel.add(reset);

        frame.setVisible(true);

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        switch (command) {
            case "Apply":
                double args1 = Double.parseDouble(num1.getText());
                double args2 = Double.parseDouble(num2.getText());
                double args3 = Double.parseDouble(num3.getText());
                double args4 = Double.parseDouble(num4.getText());
                double args5 = Double.parseDouble(num5.getText());
                double args6 = Double.parseDouble(num6.getText());          
                arrow.transform(new AffineTransform(args1, args2, args3, args4, args5, args6));
                repaint();
                break;
            case "Reset":
                arrow.transform(new AffineTransform(1, 0, 0, 0, 1, 0));
                repaint();
                break;
        }
    }

}

Part of your problem seems to be the order of your AffineTransform parameters. 问题的一部分似乎是AffineTransform参数的顺序。 You may be assuming that your JTextFields are in the same form as the 2x3 matrix, but they're not. 您可能假设您的JTextField与2x3矩阵的格式相同,但事实并非如此。 Add borders to the JTextFields to see what I mean: 在JTextFields上添加边框以了解我的意思:

    num00.setBorder(BorderFactory.createTitledBorder("m00"));
    num10.setBorder(BorderFactory.createTitledBorder("m10"));
    num01.setBorder(BorderFactory.createTitledBorder("m01"));
    num11.setBorder(BorderFactory.createTitledBorder("m11"));
    num02.setBorder(BorderFactory.createTitledBorder("m02"));
    num12.setBorder(BorderFactory.createTitledBorder("m12"));

and: 和:

        double m00 = Double.parseDouble(num00.getText());
        double m10 = Double.parseDouble(num10.getText());
        double m01 = Double.parseDouble(num01.getText());
        double m11 = Double.parseDouble(num11.getText());
        double m02 = Double.parseDouble(num02.getText());
        double m12 = Double.parseDouble(num12.getText());
        AffineTransform transform = new AffineTransform(m00, m10, m01, m11,
                m02, m12); 

and you'll see how things are not in the order you are assuming. 然后您会看到事情与假设的顺序不符。 Instead, add your JTextfields so that they'll match the matrix order: 相反,添加您的JTextfields,使其与矩阵顺序匹配:

    textPanel.add(num00);
    textPanel.add(num10);
    textPanel.add(num02);
    textPanel.add(num01);
    textPanel.add(num11);
    textPanel.add(num12);

and this will improve your findings. 这将改善您的发现。

Something like: 就像是:

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Path2D;
import java.util.Deque;
import java.util.LinkedList;

import javax.swing.event.*;

public class Project3 extends JPanel implements ActionListener {

    public static Project3 p = new Project3();
    Path2D arrow; // !!
    public static
    JTextField 
    num00 = new JTextField("0"), 
    num10 = new JTextField("1"), 
    num01 = new JTextField("1"), 
    num11 = new JTextField("0"),            
    num02 = new JTextField("0"), 
    num12 = new JTextField("0");
    private static Deque<AffineTransform> atStack = new LinkedList<>(); 

    public Project3() {
        setBackground(Color.WHITE);
        arrow = drawArrow(); // !! create the arrow only once
    }

    public Path2D drawArrow() { // !!
        arrow = new Path2D.Double(); // !!
        arrow.setWindingRule(GeneralPath.WIND_EVEN_ODD);
        arrow.moveTo(0, 0);
        arrow.lineTo(0, -100);
        arrow.moveTo(0, -200);
        arrow.lineTo(100, -100);
        arrow.lineTo(50, -100);
        arrow.lineTo(50, 100);
        arrow.quadTo(0, 0, -50, 100);
        arrow.lineTo(-50, -100);
        arrow.lineTo(-100, -100);
        arrow.lineTo(0, -200);
        arrow.closePath();
        arrow.transform(AffineTransform.getTranslateInstance(250, 250)); // !! shift it here
        return arrow;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON); // !!
        // !! g2.translate(250, 250);  // translate the arrow, not Graphics
        GradientPaint gradient = new GradientPaint(0, 0, Color.LIGHT_GRAY, 15,
                15, Color.BLACK, true);
        g2.setPaint(gradient);
        g2.setStroke(new BasicStroke(12, BasicStroke.CAP_ROUND,
                BasicStroke.JOIN_MITER));
        // g2.draw(drawArrow()); // !!  don't re-create the arrow
        g2.draw(arrow);
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("Project 3");
        frame.setSize(500, 600);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container cp = frame.getContentPane();
        cp.setLayout(new BorderLayout());

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        cp.add(panel, BorderLayout.CENTER);
        panel.add(p, BorderLayout.CENTER);
        panel = new JPanel();
        panel.setLayout(new GridLayout(0, 2));
        cp.add(panel, BorderLayout.SOUTH);

        JPanel textPanel = new JPanel();
        textPanel.setLayout(new GridLayout(2, 3));
        panel.add(textPanel);
        num00.setBorder(BorderFactory.createTitledBorder("m00"));
        num10.setBorder(BorderFactory.createTitledBorder("m10"));
        num01.setBorder(BorderFactory.createTitledBorder("m01"));
        num11.setBorder(BorderFactory.createTitledBorder("m11"));
        num02.setBorder(BorderFactory.createTitledBorder("m02"));
        num12.setBorder(BorderFactory.createTitledBorder("m12"));

        textPanel.add(num00);
        textPanel.add(num10);
        textPanel.add(num02);
        textPanel.add(num01);
        textPanel.add(num11);
        textPanel.add(num12);

        JPanel btPanel = new JPanel();
        btPanel.setLayout(new GridLayout(0, 1));
        panel.add(btPanel);
        JButton apply = new JButton("Apply");
        apply.addActionListener(p);
        btPanel.add(apply);
        JButton reset = new JButton("Reset");
        reset.addActionListener(p);
        btPanel.add(reset);

        frame.setVisible(true);

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        switch (command) {
        case "Apply":
            double m00 = Double.parseDouble(num00.getText());
            double m10 = Double.parseDouble(num10.getText());
            double m01 = Double.parseDouble(num01.getText());
            double m11 = Double.parseDouble(num11.getText());
            double m02 = Double.parseDouble(num02.getText());
            double m12 = Double.parseDouble(num12.getText());
            AffineTransform transform = new AffineTransform(m00, m10, m01, m11,
                    m02, m12); 
            arrow.transform(transform);
            atStack.addFirst(transform); // save the transform
            repaint();
            break;
        case "Reset":
            // !! arrow.transform(new AffineTransform(1, 0, 0, 0, 1, 0));
            while (atStack.size() > 0) {
                AffineTransform at = atStack.removeFirst();

                // inverse fails if determinant is 0
                if (at.getDeterminant() == 0) {
                    return;
                }
                try {
                    arrow.transform(at.createInverse());
                } catch (NoninvertibleTransformException e1) {
                    e1.printStackTrace();
                }
            }
            repaint();
            break;
        }
    }

}

I also used a queue as a stack to hold applied Transforms, to allow them to be un-done in order when reset. 我还使用队列作为堆栈来保存应用的Transform,以使它们在重置时可以按顺序撤消。

Every time you call paintComponent , it creates a new instance of arrow , throwing away any transformation you might have applied previously. 每次调用paintComponent ,它都会创建一个arrow的新实例,从而丢弃您以前可能已应用的所有转换。

Instead, create the shape once and use the same instance your transformed to paint with. 而是一次创建形状,并使用转换后的同一实例进行绘制。

You might also consider using createTransformedShape instead, as this will return a transformed instance of the original path rather the continuously compounding the transformation 您可能还考虑使用createTransformedShape ,因为这将返回原始路径的变换后的实例,而不是不断地使变换复杂化

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM