简体   繁体   English

Java Swing重绘GUI

[英]Java swing repaint GUI

I am trying to implement an undo / redo functionality in my line drawing/moving/deleting program. 我正在尝试在画线/移动/删除程序中实现撤消/重做功能。 I am currently saving each line as a list of points and storing all the lines in a list. 我目前将每条线保存为点列表,并将所有线存储在列表中。 After every drawing/moving/deleting operation I will add the new list of lines to my buffer and increment the bufferIterator(counter) to be the last element of the buffer at every mouseReleased action. 每次绘制/移动/删除操作之后,我都会将新的行列表添加到缓冲区中,并在每次mouseReleased操作时将bufferIterator(counter)递增为缓冲区的最后一个元素。 When I press ESC I am trying to make the current lines variable the previous list of lines and repaint, but the repaint part is not working. 当我按ESC时,我试图使当前行变为先前的行列表并重新绘制,但是重新绘制部分不起作用。 Does anyone have any idea what I am doing wrong ? 有人知道我在做什么错吗?

The code is here: 代码在这里:

    public class Kimp {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Kimp!");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800, 600);
        frame.setLocationRelativeTo(null);
        frame.add(new CanvasPanel());
        frame.setVisible(true);
    }
}

class CanvasPanel extends JPanel {
    private List<List<List<Point>>> buffer = new LinkedList<List<List<Point>>>();
    private List<List<Point>> lines = new LinkedList<List<Point>>();
    private List<Point> points = new LinkedList<Point>();
    public boolean ctrlPressed;
    public int bufferIterator = 0;
    public int pressedX = -999;
    public int pressedY = -999;
    public int differenceX;
    public int differenceY;
    public List<Point> pressedLine = new LinkedList<Point>();
    public List<Point> movedLine = new LinkedList<Point>();
    public Color lineColor = Color.BLUE;

    public CanvasPanel() {
        this.setFocusable(true);
        this.requestFocusInWindow();
        addKeyListener(keyAdapter);
        addMouseListener(mouseAdapter);
        addMouseMotionListener(mouseAdapter);
    }

    @Override
    public void paintComponent(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;
        g2.setColor(Color.WHITE);
        g2.setStroke(new BasicStroke(3));
        g2.fillRect(0, 0, getWidth(), getHeight());

        for (List<Point> line : lines) {
            drawLine(line, g2);
        }
        drawLine(points, g2);
    }

    private void drawLine(List<Point> points, Graphics2D g2) {
        if (points.size() < 2) return;

        if (ctrlPressed) {
            int lineS = points.size();
            int lineP = pressedLine.size();
            //Set the color to RED, if the line is being moved.
            if (lineS == lineP) {
                boolean first = comparePoints(points.get(0), pressedLine.get(0));
                boolean second = comparePoints(points.get(lineS - 1), pressedLine.get(lineP - 1));
                boolean third = comparePoints(points.get(lineS / 2), pressedLine.get(lineP / 2));
                if (first && second && third) {
                    lineColor = Color.RED;
                }
            } else {
                lineColor = Color.BLUE;
            }
        } else {
            lineColor = Color.BLUE;
        }

        Point p1 = points.get(0);

        for (int i=1, n=points.size(); i<n; i++) {
            Point p2 = points.get(i);

            g2.setColor(lineColor);
            g2.drawLine(p1.x, p1.y, p2.x, p2.y);

            p1 = p2;
        }
    }

    private KeyAdapter keyAdapter = new KeyAdapter() {

        @Override
        public void keyPressed(KeyEvent ke) {
            if(ke.getKeyCode() == ke.VK_ESCAPE) {
                System.out.println("ESC PRESSED");

                if (bufferIterator != 0) {
                    System.out.println("UNDOING!");
                    //UNDO
                    lines = new LinkedList<List<Point>>();
                    int index = bufferIterator - 1;
                    if (index >= 0) {
                        lines = buffer.get(index);
                    }
                    repaint();

                } else {
                    int reply = JOptionPane.showConfirmDialog(null, "Do you want to exit?",
                            "Exit", JOptionPane.YES_NO_OPTION);
                    if (reply == JOptionPane.YES_OPTION) {
                        System.exit(0);
                    }
                }
            } else if(ke.getKeyCode() == ke.VK_CONTROL) {
                 ctrlPressed = true;  
            } else if (ke.getKeyCode() == ke.VK_SPACE) {
                System.out.println("REDOING");
                //REDO
            }
         } 

       @Override
       public void keyReleased(KeyEvent ke) {
           if(ke.getKeyCode() == ke.VK_CONTROL) {
               ctrlPressed = false;
           } 
       }
    };

    private MouseAdapter mouseAdapter = new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {


            if (ctrlPressed) {
                if (e.isMetaDown()) {
                    Point pointPressed = e.getPoint();
                    for (int j=0, m=lines.size(); j<m; j++) {
                        List<Point> line = lines.get(j);
                        for (int i=0, n=line.size(); i<n; i++) {
                            Point pt = line.get(i);
                            //This is, to allow a small margin of missing, but still only take 1 point.
                            if (pointPressed.x - pt.x <= 1 && pointPressed.y - pt.y <= 1) {
                                //Only the first point will be "the point clicked".
                                if (pressedX == -999 && pressedY == -999) {
                                    pressedX = pt.x;
                                    pressedY = pt.y;
                                    pressedLine = line;
                                }
                            }
                        }
                    }
                    for (int x = 0, r = lines.size(); x < r; x++) {
                        int lenA = lines.get(x).size();
                        int lenB = pressedLine.size();
                        if (lenA == lenB) {
                            boolean first = comparePoints(lines.get(x).get(0), pressedLine.get(0));
                            boolean second = comparePoints(lines.get(x).get(lenA - 1), pressedLine.get(lenB - 1));
                            boolean third = comparePoints(lines.get(x).get(lenA / 2), pressedLine.get(lenB / 2));

                            if (first && second && third) {
                                lines.remove(x);
                                buffer.add(lines);
                                repaint();
                                break;
                            }
                        }
                    }
                } else {
                    Point pointPressed = e.getPoint();
                    for (int j=0, m=lines.size(); j<m; j++) {
                        List<Point> line = lines.get(j);
                        for (int i=0, n=line.size(); i<n; i++) {
                            Point pt = line.get(i);
                            //This is, to allow a small margin of missing, but still only take 1 point.
                            if (pointPressed.x - pt.x <= 1 && pointPressed.y - pt.y <= 1) {
                                //Only the first point will be "the point clicked".
                                if (pressedX == -999 && pressedY == -999) {
                                    pressedX = pt.x;
                                    pressedY = pt.y;
                                    pressedLine = line;
                                }
                            }
                        }
                    }
                }

            } else {
                points.add(e.getPoint());
                repaint();
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {

            Point pointDragged = e.getPoint();
            if (ctrlPressed) {
                differenceX = pointDragged.x - pressedX;
                differenceY = pointDragged.y - pressedY;

                //Create the moved line
                for (Point p : pressedLine) {
                    movedLine.add(new Point(p.x + differenceX , p.y + differenceY));
                }

                for (int i=0, n=lines.size(); i<n; i++) {
                    int lineS = lines.get(i).size();
                    int lineP = pressedLine.size();
                    //Choose 3 points in order to not go through all of them
                    boolean first = comparePoints(lines.get(i).get(0), pressedLine.get(0));
                    boolean second = comparePoints(lines.get(i).get(lineS - 1), pressedLine.get(lineP - 1));
                    boolean third = comparePoints(lines.get(i).get(lineS / 2), pressedLine.get(lineP / 2));
                    if (first && second && third) {
                        lines.set(i, movedLine);
                        pressedX = pressedX + differenceX;
                        pressedY = pressedY + differenceY;
                        pressedLine = movedLine;
                        movedLine = new LinkedList<Point>();
                        repaint();
                        break;
                    }
                }

            } else {
                points.add(pointDragged);
                repaint();
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {

            if (points.size() > 1) {
                lines.add(points);
                points = new LinkedList<Point>();
            }
            //Add the current canvas to buffer
            buffer.add(lines);

            System.out.println("Buffer size:");
            System.out.println(buffer.size() );
            System.out.println(buffer.get(buffer.size() - 1));
            bufferIterator = buffer.size() - 1;

            pressedX = -999;
            pressedY = -999;

        }
    };

    public boolean comparePoints (Point p1, Point p2) {
        if (p1.x == p2.x && p1.y == p2.y) {
            return true;
        }
        return false;
    }
}

The issue is that you are not adding new objects to the buffer. 问题是您没有将新对象添加到缓冲区。 Each time it is a reference to the same List. 每次它都是对同一列表的引用。 So when you get the list at the correct index out of the buffer you get the same list as any other index. 因此,当您从缓冲区之外的正确索引处获得列表时,您将获得与任何其他索引相同的列表。

To fix this create a copy of the lines list to add to the buffer instead of adding lines each time. 要解决此问题,请创建行列表的副本以添加到缓冲区中,而不是每次都添加行。

Something like: 就像是:

 buffer.add(lines);
 lines = new LinkedList<List<Point>(lines);

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

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