2015-09-04 30 views
0
改變

我的程序應該允許用戶輸入的第一六個數字矩陣的文本字段中,然後點擊應用按鈕,使用.transform方法與改變Path2D參數是六個輸入的數字。我的問題是,無論何時輸入內容並點擊應用,轉換都會與原來的方式截然不同,並且原始箭頭也會保留。麻煩與得到Path2D.Double與.transform

這真是奇怪的,我不知道哪裏出了問題的來源。一切都應該在仿射變換中找到合適的位置,但是變革出現了所有錯誤。

這是它應該是什麼樣子: enter image description here

這是它看起來像我: enter image description here

我會把下面的完整代碼,這樣你可以自己運行它,看看你可能會弄清楚。謝謝!

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

} 
+0

你變換順序的參數是不是你希望它是什麼任。請注意,當您將1放在頂行的第2和第3個JTextField中時,會發生什麼情況,其他地方是0。 –

回答

4

部分您的問題似乎是你的AffineTransform參數的順序。您可能會認爲您的JTextFields與2x3矩陣的格式相同,但它們不是。添加邊框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")); 

和:

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

,你會看到的東西都不怎麼在你承擔的順序。相反,添加您的JTextfields,以便它們匹配矩陣順序:

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

這會改進您的發現。

喜歡的東西:

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

} 

我也用一個隊列作爲一個堆棧來保持施加變換,讓他們成爲未完成,以便在復位。

+0

是的,這工作完美!非常感謝你的幫助!從來沒有意識到矩陣元素錯誤的順序大聲笑 – user2872777

2

每次調用paintComponent時,它創建的arrow一個新實例,扔掉你可能以前應用的任何轉變。

相反,一旦創建形狀和使用相同的實例您的轉化與作畫。

您還可以考慮使用替代createTransformedShape,因爲這將返回原路徑的轉化實例,而連續複利改造

+0

見我試圖createTransformedShape,但它似乎並沒有做任何事情,無論是輸入我補充。另外你是什麼意思,通過使用相同的實例?我認爲這就是我將它作爲一個公共變量,並專門使用它的變換功能。此外,我不能刪除repaint(),因爲除了原始箭頭之外沒有任何東西會被繪製,就像createTransformedShape一樣。 – user2872777

+0

CreateTransformedShape返回變換後的形狀,這是偉大的,如果不想改造基本形狀。在drawArrow方法中,您將創建該形狀的新實例,該實例會忽略每次繪製該組件時可能應用的任何先前的轉換。相反,只在想要創建形狀的新實例時調用drawArrow,而在所有其他情況下,應該使用實例變量 – MadProgrammer

+0

另外,請記住,每次在路徑上調用transform時,都會將新變換合併到路徑當前變換 – MadProgrammer