绘制应用程序:使用AffineTransform拖动自由形式的线条(路径)

时间:2013-11-17 10:00:33

标签: java swing graphics2d translate affinetransform

如何使用AffineTransform拖动自由格式线(路径)?

我在Java中制作类似Paint的应用程序,其中一个要求是能够将绘制的自由形状拖动到用于绘图的JPanel上的新位置。我现在一直试图让AffineTransform这样做一天,它现在做的是选择所需的行(存储为Path2D)并拖动它确实移动。但是,一旦没有选择行,该行将返回其原始位置。此外,当我再次选择它时,会立即显示在新位置(如果这有意义);这可能是被翻译的坐标系,但我不确定...... 任何帮助将非常感谢!也许有一种更简单的方法可以做到这一点。 PS我还注意到,当移动任何绘制的线条时,除了最后绘制的线条之外,在移动的线条之前绘制的所有线条都与它一起移动。 这是代码:

public class DrawPanel extends JPanel {
public double translateX=0;
public double translateY=0;
public int lastOffsetX;
public int lastOffsetY;

class Line {
    public Point start;
    public Point end;
    public Color color;
    public Path2D path;
}

ArrayList<Line> lines = new ArrayList<Line>();
ArrayList<Path2D> paths = new ArrayList<Path2D>();
    boolean moveMode = false;

    Path2D selectedLine;
    int xDistance;
    int yDistance;


    public DrawPanel() {
            setBackground(Color.WHITE);
            setFocusable(true);
            requestFocusInWindow();

            this.addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseDragged(MouseEvent e) {
                    //System.out.println(resizeMode);
                        if (moveMode) {
                            if (selectedLine!=null) {
                                int newX = e.getX() - lastOffsetX;
                            int newY = e.getY() - lastOffsetY;
                            lastOffsetX += newX;
                            lastOffsetY += newY;
                            translateX += newX;
                        translateY += newY;
                                    repaint();
                            }
                        } else {

                                Path2D p = paths.get(paths.size() - 1);
                                p.lineTo(e.getX(), e.getY());
                                    repaint();
                        }
                }

                @Override
                public void mouseMoved(MouseEvent e) {
                        super.mouseMoved(e);
                        if (resizeMode) {
                                selectedLine = null;
                                for (Path2D l : paths) {
                                    if (l.contains(e.getPoint())) {
                                        selectedLine = l;
                                    } 
                                    }

                                repaint();
                        }
                }
        });

        this.addMouseListener(new MouseAdapter() {
                @Override
                public void mousePressed(MouseEvent e) {
                        super.mousePressed(e);
                        if (!moveMode) {
                                Line l = new Line(e.getPoint());
                                l.path = new Path2D.Double();
                                l.path.moveTo(e.getX(), e.getY());
                                lines.add(l);
                                paths.add(l.path);
                        } else {
                                lastOffsetX = e.getX();
                            lastOffsetY = e.getY();
                        }
                        }

                }

                @Override
                public void mouseReleased(MouseEvent e) {
                        super.mouseReleased(e);
                        if (!resizeMode) {
                            if (selectedLine == null) {
                                Line l = lines.get(lines.size() - 1);
                                l.end = e.getPoint();
                                l.path.lineTo(e.getX(), e.getY());
                                Path2D p = paths.get(paths.size() - 1);
                                p.lineTo(e.getX(), e.getY());
                                repaint();
                            } 
                        } else {

                            for (int j=0; j<paths.size();j++) {
                             if (selectedLine!=null && selectedLine.equals(paths.get(j))) {
                                 paths.set(j, selectedLine);
                             }
                            }

                            repaint();
                        }
                }

                });
    }

        private void setKeyBindings() {
            ActionMap actionMap = getActionMap();
            int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
            InputMap inputMap = getInputMap(condition );
            String ctrl = "VK_CONTROL";
            String ctrl_rel = "control_released";
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK, false), ctrl);
            inputMap.put(KeyStroke.getKeyStroke(("released CONTROL")), ctrl_rel);

            actionMap.put(ctrl, new KeyAction(ctrl));
            actionMap.put(ctrl_rel, new KeyAction(ctrl_rel));
    }
        private class KeyAction extends AbstractAction {
            public KeyAction(String actionCommand) {
               putValue(ACTION_COMMAND_KEY, actionCommand);
            }

            @Override
            public void actionPerformed(ActionEvent actionEvt) {
               if(actionEvt.getActionCommand() == "VK_CONTROL") {
                   moveMode = true;
               }
               else if(actionEvt.getActionCommand() == "control_released") {
                   moveMode = false;
                   repaint();
               }

            }
         }

    @Override
    protected void paintComponent(Graphics g) {
         super.paintComponent(g);
         Graphics2D g2d = (Graphics2D)g;
         g2d.setColor(Color.BLACK);
         g2d.setStroke(new BasicStroke(10.0f));
         g2d.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );

         if (moveMode) {
                    for (int j=0; j<paths.size();j++) {
                         Path2D path = paths.get(j);
                         if (selectedLine!=null && selectedLine.equals(path)) {
                             AffineTransform at = new AffineTransform();
                             at.translate(translateX, translateY);
                             g2d.transform(at);
                             g2d.setColor(Color.RED);
                             g2d.draw(path);
                             g2d.setColor(Color.BLACK);
                             continue;

                         }  
                             g2d.draw(path);
                             g2d.setColor(Color.BLACK);

                     }
         } else {
                for (int i =0; i < paths.size();i++) {
                Path2D path = paths.get(i);
                 g2d.draw(path); // outline
                 }
         }
    }

编辑以包含分辨率:所以最后我做的是将所有路径的坐标(我从PathIterator获得)保存到ArrayList,创建了一个新的空路径,将以前路径的坐标从ArrayList添加到新路径(通过moveTo,lineTo),并将新路径附加到所有绘制路径的ArrayList。

1 个答案:

答案 0 :(得分:3)

如您所知,AffineTransform改变了所有后续绘图的图形上下文坐标系。

在引用的示例here中,每个形状都是类Node的一个实例。每个Node都包含selected属性,允许独立选择形状。该值确定updatePosition()mouseDragged()调用时的效果。 updatePosition()的实施只是更新每个选定节点的坐标,但您也可以使用createTransformedShape()的{​​{1}}。