【问题标题】:Java Challenge on Permitting the User to Draw A Line关于允许用户画线的 Java 挑战
【发布时间】:2012-12-14 20:06:45
【问题描述】:

java draw line as the mouse is moved 中已经提到了我的问题,但是,正如之前提出这个问题的程序员所说,我在本书中还没有深入到涵盖 JPanel、JFrames 和 Points 的程度。

回答这个问题肯定会帮助大多数初学者更好地理解图形类和绘图,这是一个通常复杂的过程,尤其是对于初学者。

根据我使用的文本(因为我正在自学Java),这是如何使用Java画线的示例:

/*
 * LineTest
 * Demonstrates drawing lines
 */
import java.awt.*;
public class LineTest extends Canvas {
public LineTest() {
super();
setSize(300, 200);
setBackground(Color.white);
}
public static void main(String args[]) {
LineTest lt = new LineTest();
GUIFrame frame = new GUIFrame("Line Test");
frame.add(lt);
frame.pack();
frame.setVisible(true);
}
public void paint(Graphics g) {
g.drawLine(10, 10, 50, 100);
g.setColor(Color.blue);
g.drawLine(60, 110, 275, 50);
g.setColor(Color.red);
g.drawLine(50, 50, 300, 200);
}
}

规格为:

创建一个应用程序,允许您通过单击初始 点并将鼠标拖动到第二个点。该应用程序应 重新绘制,以便您可以看到线条的大小和位置随着您的变化而变化 正在拖动鼠标。释放鼠标按钮时,该行是 绘制。

如您所见,运行此程序不会由用户创建任何绘图。我相信由于第 21 行遇到此错误:g.drawLine(x, y, x2, y2); 不正确,因为这是定义线条绘制的语句。

非常感谢任何帮助。预先感谢您在此问题上的所有时间和合作。

我回答问题的代码是:

import java.awt.*;
import java.awt.event.*;

public class LineDrawer extends Canvas
                        implements MouseListener, MouseMotionListener {
int x, y, x2, y2;

public LineDrawer() {
    super();
    setSize(300, 200);
    setBackground(Color.white);
}
public void mouseClicked(MouseEvent me) {
                int x = me.getX();
                int y = me.getY();
                int x2 = me.getX();
                int y2 = me.getY();

    }
public void paint(Graphics g) {
            g.drawLine(x, y, x2, y2);
            g.setColor(Color.blue);
    }


    public void mousePressed(MouseEvent me) {
        repaint();
    }

    public void mouseDragged(MouseEvent me) {
    }
    public void mouseExited(MouseEvent me) {
    }
    public void mouseEntered(MouseEvent me) {
    }


    public void mouseReleased(MouseEvent me) {
    }
    public void mouseMoved(MouseEvent me) {
    }

    public static void main(String args[]) {
        LineDrawer ld = new LineDrawer();
        GUIFrame frame = new GUIFrame("Line Drawer");
        frame.add(ld);
        frame.pack();
        frame.setVisible(true);
    }

}

P.S.:我一直犹豫寻求帮助,因为我担心其他程序员会用我还没有学过的方法来回答。

【问题讨论】:

  • “我一直犹豫是否要寻求帮助,因为我担心其他程序员会用我还没有学过的方法来回答。”这也是我的原因之一认为 SO 很棒 - 总是有新事物!如果你不想这样,也许你来错地方了。
  • 1) public class LineDrawer extends Canvas 这是第三个千年。使用 Swing(JPanel 并覆盖 paintComponent(Graphics))。 2) 对代码块使用一致且符合逻辑的缩进。代码的缩进是为了帮助人们理解程序流程。 3) 组件可能会覆盖首选大小,但不应setSize(300, 200);
  • @AndrewThompson JPanel 有一个缺点。它不支持三重缓冲(虽然不需要)
  • "问题是:" 不,这是一个规范,而不是一个问题。您的具体问题是什么

标签: java graphics drawing awt mouseevent


【解决方案1】:
int x1, y1, x2, y2;

public void mousePressed(MouseEvent e){
    x1 = e.getX();
    y1 = e.getY();
}

public void mouseDragged(MouseEvent e){
    x2 = e.getX();
    y2 = e.getY();
    // Now Paint the line
    repaint();
}

希望对你有帮助。

【讨论】:

    【解决方案2】:

    开始吧

    public void mouseClicked(MouseEvent me) {
        int x = me.getX();
        int y = me.getY();
        int x2 = me.getX();
        int y2 = me.getY();
    }
    

    你之前已经声明了xyx2y2,但是在这个方法中,你已经用新的减速覆盖了这些减速,这意味着之前声明的变量将不会被使用并且事件参数将被忽略。

    mouseClickedmousePressedmouseReleased 事件之后触发,这意味着这实际上是用户释放鼠标按钮的时间。

    Extreme Coder 指出 MouseClicked 仅在同时按下和释放鼠标按钮时触发,即不涉及拖动 - 它仍然不是正确的使用方法,但澄清是不错

    你应该做的是……

    mousePressed 上存储xy 的点击位置,在mouseReleased 上存储x2y2 的位置。

    mouseDragged 事件中,您应该更新x2y2 的值并调用repaint

    public void mousePressed(MouseEvent me) {
        // Mouse is down, but hasn't yet being released...
        x = me.getX();
        y = me.getY();
        // We need to "override" any previous values...
        x2 = x;
        y2 = y;
        repaint();
    }
    
    public void mouseDragged(MouseEvent me) {
        x2 = me.getX();
        y2 = me.getY();
        repaint();
    }
    
    public void mouseReleased(MouseEvent me) {
        // Here I would store the points so I could re-draw each new line...
    }
    

    与其使用xyx2y2,不如使用两个数组,即

    private int[] startPoint;
    private int[] endPoint;
    

    然后你可以做类似...

    public void mousePressed(MouseEvent me) {
        // Mouse is down, but hasn't yet being released...
        startPoint = new int[2];
        startPoint[0] = me.getX();
        startPoint[1] = me.getY();
        endPoint = startPoint;
        repaint();
    }
    public void mouseDragged(MouseEvent me) {
        endPoint = new int[2];
        endPoint[0] = me.getX();
        endPoint[1] = me.getY();
        repaint();
    }
    

    现在我更喜欢 paintComponent 而不是 JComponent,但我现在会坚持你的例子..

    public void paint(Graphics g) {
        super.paint(g); // This is super important...
        if (startPoint != null && endPoint != null && startPoint.length == 2 && endPoint.length == 2) {
            g.drawLine(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
        }
    }
    

    附加

    这有点令人担忧...

    public void paint(Graphics g) {
        g.drawLine(x, y, x2, y2);
        g.setColor(Color.blue);
    }
    

    操作顺序非常重要。在绘制线条之后设置颜色对您的绘制操作没有影响(但可能会影响您之后发生的绘制操作)。

    另外,您必须致电super.paint(g) - 这非常重要...

    示例

    一个“基本”示例,使用int[] 数组进行点存储...

    public class BasicLineDraw {
    
        public static void main(String[] args) {
            new BasicLineDraw();
        }
    
        public BasicLineDraw() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new DrawLinePane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class DrawLinePane extends JPanel {
    
            private int[] startPoint;
            private int[] endPoint;
            private List<int[][]> lines;
    
            public DrawLinePane() {
    
                lines = new ArrayList<int[][]>(25);
    
                MouseAdapter handler = new MouseAdapter() {
                    @Override
                    public void mousePressed(MouseEvent e) {
                        startPoint = new int[]{e.getX(), e.getY()};
                        endPoint = startPoint;
                        repaint();
                    }
    
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        endPoint = new int[]{e.getX(), e.getY()};
                        repaint();
                    }
    
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        if (startPoint != null && endPoint != null && startPoint.length == 2 && endPoint.length == 2) {
                            lines.add(new int[][]{startPoint, endPoint});
                        }
                        startPoint = null;
                        endPoint = null;
                        repaint();
                    }
                };
    
                addMouseListener(handler);
                addMouseMotionListener(handler);
    
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                Graphics2D g2d = (Graphics2D) g.create();
                if (startPoint != null && endPoint != null && startPoint.length == 2 && endPoint.length == 2) {
    
                    g2d.setColor(Color.RED);
                    g2d.drawLine(startPoint[0], startPoint[1], endPoint[0], endPoint[1]);
    
                }
    
                g2d.setColor(Color.BLUE);
                for (int[][] line : lines) {
                    g2d.drawLine(line[0][0], line[0][1], line[1][0], line[1][1]);
                }
    
                g2d.dispose();
    
            }
        }
    }
    

    还有一个更高级的例子,使用Point和Java的2D Graphics API

    public class LineDrawer {
    
        public static void main(String[] args) {
            new LineDrawer();
        }
    
        public LineDrawer() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (Exception ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new DrawLinePane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class DrawLinePane extends JPanel {
    
            private Point anchor;
            private Point lead;
    
            private List<Line2D> lines;
    
            public DrawLinePane() {
    
                lines = new ArrayList<Line2D>(25);
    
                MouseAdapter handler = new MouseAdapter() {
    
                    @Override
                    public void mousePressed(MouseEvent e) {
                        lead = null;
                        anchor = e.getPoint();
                        repaint();
                    }
    
                    @Override
                    public void mouseDragged(MouseEvent e) {
                        lead = e.getPoint();
                        repaint();
                    }
    
                    @Override
                    public void mouseReleased(MouseEvent e) {
                        if (lead != null && anchor != null && !anchor.equals(lead)) {
                            lines.add(new Line2D.Float(anchor, lead));
                        }
                        repaint();
                    }
    
                };
    
                addMouseListener(handler);
                addMouseMotionListener(handler);
    
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g); 
    
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setColor(Color.RED);
                if (lead != null && anchor != null) {
    
                    Composite composite = g2d.getComposite();
                    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.25f));
                    g2d.draw(new Line2D.Float(anchor, lead));
                    g2d.setComposite(composite);
    
                }
    
                for (Line2D line : lines) {
                    g2d.draw(line);
                }
    
                g2d.dispose();
    
            }
    
        }
    
    }
    

    【讨论】:

    • MouseClicked 仅在同时按下和释放鼠标按钮时触发,即不涉及拖动。 mousePressedmouseReleased 事件应该同时发生。
    • @ExtremeCoders 哇,学到了一些新东西:D - 仍然 - 不是正确的使用方法;)
    猜你喜欢
    • 2012-12-15
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多