java中的绘图问题

java中的绘图问题,java,draw,paint,repaint,Java,Draw,Paint,Repaint,我是一个java新手,我需要实现一个绘画应用程序,我有点被困在乞讨中,我设法在一个JPanel上画线,我把它添加到一个JFrame中,但是画的每一条线都会重置整个绘图,在绘图区域中只保留最后画的一条线。我希望我能让自己明白,以下是他的代码: class Shapes extends JFrame { public JFrame mf = new JFrame("Paint"); DrawArea da = new DrawArea(); JToggleButt

我是一个java新手,我需要实现一个绘画应用程序,我有点被困在乞讨中,我设法在一个JPanel上画线,我把它添加到一个JFrame中,但是画的每一条线都会重置整个绘图,在绘图区域中只保留最后画的一条线。我希望我能让自己明白,以下是他的代码:

class Shapes extends JFrame {

    public JFrame mf = new JFrame("Paint");
    DrawArea da = new DrawArea();

        JToggleButton lineButton = new JToggleButton(new ImageIcon("line.gif"));
        JToggleButton brushButton = new JToggleButton();
        JToggleButton pencilButton = new JToggleButton();
        JToggleButton eraserButton = new JToggleButton(new ImageIcon("eraser_icon.png"));
        JToggleButton rectangleButton = new JToggleButton();
        JToggleButton ovalButton = new JToggleButton();

    Shapes() {


        da.setBounds(120, 50, 500, 350);
        da.setBackground(Color.YELLOW);
        mf.setSize(700, 500);
        mf.setLayout(null);

        lineButton.setBounds(0, 50, 40, 40);
        brushButton.setBounds(40, 50, 40, 40);
        eraserButton.setBounds(0, 90, 40, 40);
        pencilButton.setBounds(40, 90, 40, 40);
        rectangleButton.setBounds(0, 130, 40, 40);
        ovalButton.setBounds(40, 130, 40, 40);

        mf.setBackground(Color.red);
        mf.add(lineButton);
        mf.add(brushButton);
        mf.add(pencilButton);
        mf.add(eraserButton);
        mf.add(rectangleButton);
        mf.add(ovalButton);
        mf.add(da);
        mf.show();
        mf.addWindowListener(new WindowAdapter() {

            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        mf.addMouseListener(new MouseAdapter() {

            public void mouseClicked(MouseEvent e) {
                System.out.println("x:" + e.getX() + "y:" + e.getY() + "\n" + "x2:" + e.getXOnScreen() + "y2:" + e.getYOnScreen());
            }
        });
        eraserButton.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e)
            {
            eraserButton.setSelectedIcon(new ImageIcon("eraser_icon_selected.png"));
        }
        });
        lineButton.addMouseListener(new MouseAdapter() {
        public void mouseClicked(MouseEvent e)
            {
              lineButton.setSelectedIcon(new ImageIcon("line_selected.png"));
        }
        });
        da.addMouseListener(new MouseAdapter() {

            public void mousePressed(MouseEvent e) {
                da.setXvalue(e.getX());
                da.setYvalue(e.getY());



            }

            public void mouseReleased(MouseEvent e) {

                da.setX2value(e.getX());
                da.setY2value(e.getY());
                da.repaint();
            }
        });
        da.addMouseMotionListener(new MouseAdapter() {

            public void mouseDragged(MouseEvent e) {
                da.repaint();
                da.setX2value(e.getX());
                da.setY2value(e.getY());

            }
        });

    }
}



public class DrawArea extends JPanel {
    int x1value,y1value,x2value,y2value;

    public int getX2value() {
        return x2value;
    }

    public void setX2value(int x2value) {
        this.x2value = x2value;
    }

    public int getY2value() {
        return y2value;
    }

    public void setY2value(int y2value) {
        this.y2value = y2value;
    }
    public JPanel dra=new JPanel();

    public int getXvalue() {
        return x1value;
    }

    public void setXvalue(int xvalue) {
        this.x1value = xvalue;
    }

    public int getYvalue() {
        return y1value;
    }

    public void setYvalue(int yvalue) {
        this.y1value = yvalue;
    }

    public void paint(Graphics g)
    {
      super.paint(g);
      g.setColor(Color.red);
      g.drawLine(getXvalue(),getYvalue(),getX2value(),getY2value());

}
}

    class Paint extends JPanel

{ 

    public static void main(String args[])
            {
               Shapes s=new Shapes();

            }

}

覆盖,而不是。读这个。当需要重新绘制面板时,您可以调用该面板(panels)方法。

只要窗口管理器认为该区域“未刷新”,就会调用Paint。如果你现在这样做,你每次都会画最后一条线

正确的方法是在内存中创建一个
BufferedImage
,并利用它。然后,在绘制方法中,将
buffereImage
滴到曲面上。这也使得滚动和缩放非常容易


每当执行此操作时,请使曲面无效,以便窗口管理器将为您调用绘制方法。

您只存储了一行,每次都将覆盖它,因此在重新绘制组件时,旧的一行将被擦除,新的一行将被重新绘制

paintComponent
等的期望是,您的实现将在每次调用时绘制希望显示的每个图形元素


与其存储
x1
y1
x2
y2
,不如创建一个
LineSegment
类或类似类来存储这些值。然后,在绘制时,为存储的每个
LineSegment
对象调用
g.drawLine()
(可能在
ArrayList
或类似文件中)。然后,重新绘制组件时,屏幕上会显示所有线段。

请参阅以获取两种解决方案。示例绘制矩形,但线条的概念相同。

有点离题,但我有几分钟不舒服,因为我使用了update()而不是repaint()。我建议所有使用SWING的人花些时间检查哪些方法应该作为线程安全的方法处理,哪些方法必须在EDT(事件调度程序线程)上,以确保不会出现意外错误。

此外,如果你想在你的应用程序中有一个撤销/重做系统,在开始时要仔细考虑。。。 如果是这样,那么您希望允许撤销多少步骤。如果你想允许这个功能,你就不能只画而忘记上次画的东西。 此外,存储到目前为止所绘制的所有图像也不会节省内存。我不是专家,也不是说这是最佳实践,但我会这样做:

我会列出两份清单

  • 其中一个将存储应用的绘图动作
  • 另一个将包含撤消的绘图操作
  • 绘图操作将是一个接口,某些类将为每种特定类型的绘图操作(LineDrawAction、CirceDrawAction…)实现它

    当你画一条新线或任何你想清空撤销的动作列表并将其添加到应用的动作列表中时。当有人撤消最后一个操作时,我只会从应用列表中删除最后一个绘图操作,并将其添加到撤消列表中(等等)。根据您是否希望在列表达到此x限制时仅允许撤消最后一个x操作,我将从列表或队列中删除第一个绘图操作,并最终绘制到图片-这意味着永久绘图,无法撤消


    我希望它清晰而有用,即使不是对你问题的直接回答。

    这是一个有用的改变,但这不是他的问题的原因。谢谢你,我还需要实现铅笔和画笔工具,+geom图形,这样会有所帮助。谢谢