java - 如何在 JPanel 上保存图形的当前状态

标签 java swing serialization awt java-2d

<分区>

我有一个程序允许用户使用 Graphics 添加矩形和圆形到 JPanel。我想要做的是将当前 JPanel 的当前状态(即所有形状及其位置)保存到一个文件中,并能够加载该文件并恢复该状态。我有一个 Shapes 类,它扩展 JPanel 并完成所有绘图并使用 ArrayList 跟踪形状。

我可以简单地保存面板的状态吗?还是我必须将形状数据保存到文件中并在“打开”文件时重新绘制形状?

谁能指导我如何保存 JPanel 的当前状态并重新打开它?谢谢

public class UMLEditor {

    public static void main(String[] args) {

        JFrame frame = new UMLWindow();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(30, 30, 1000, 700);
        frame.getContentPane().setBackground(Color.white);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }
}

class UMLWindow extends JFrame {
    Shapes shapeList = new Shapes();

    public UMLWindow() {
        addMenus();
    }

    public void addMenus() {

        getContentPane().add(shapeList);

        JMenuBar menubar = new JMenuBar();
        JMenu file = new JMenu("File");
        JMenuItem openMenuItem = new JMenuItem("Open File");
        openMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                // Open saved state
        });

        JMenuItem saveMenuItem = new JMenuItem("Save");
        saveMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                // Save current state
            }
        });

        file.add(openMenuItem);
        file.add(saveMenuItem);

        JMenu shapes = new JMenu("Shapes");
        file.setMnemonic(KeyEvent.VK_F);

        JMenuItem rectangleMenuItem = new JMenuItem("New Rectangle");
        rectangleMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                shapeList.addSquare(100, 100);
            }
        });

        JMenuItem circleMenuItem = new JMenuItem("New Circle");
        circleMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                shapeList.addCircle(100, 100);
            }
        });

        shapes.add(rectangleMenuItem);
        shapes.add(circleMenuItem);

        menubar.add(file);
        menubar.add(shapes);

        setJMenuBar(menubar);

        setSize(300, 200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

}

// Shapes class, used to draw the shapes on the panel
// as well as implements the MouseListener for dragging
class Shapes extends JPanel {
    private static final long serialVersionUID = 1L;

    private List<Path2D> shapes = new ArrayList<Path2D>();
    int currentIndex;

    public Shapes() {
        MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
        addMouseListener(myMouseAdapter);
        addMouseMotionListener(myMouseAdapter);
    }

    public void addSquare(int width, int height) {
        Path2D rect2 = new Path2D.Double();
        rect2.append(new Rectangle(getWidth() / 2 - width / 2, getHeight() / 2
                - height / 2, width, height), true);

        shapes.add(rect2);
        repaint();

    }

    public void addCircle(int width, int height) {
        Path2D rect2 = new Path2D.Double();
        rect2.append(new Ellipse2D.Double(getWidth() / 2 - width / 2,
                getHeight() / 2 - height / 2, width, height), true);

        shapes.add(rect2);
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        this.setOpaque(true);
        this.setBackground(Color.WHITE);
        Graphics2D g2 = (Graphics2D) g;
        for (Path2D rect : shapes) {
            g2.draw(rect);
        }
    }

    class MyMouseAdapter extends MouseAdapter {
        private boolean pressed = false;
        private Point point;

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getButton() != MouseEvent.BUTTON1) {
                return;
            }
            for (int i = 0; i < shapes.size(); i++) {
                if (shapes.get(i) != null
                        && shapes.get(i).contains(e.getPoint())) {
                    currentIndex = i;
                    pressed = true;
                    this.point = e.getPoint();
                }
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (pressed) {
                int deltaX = e.getX() - point.x;
                int deltaY = e.getY() - point.y;
                shapes.get(currentIndex).transform(
                        AffineTransform.getTranslateInstance(deltaX, deltaY));
                point = e.getPoint();
                repaint();
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            pressed = false;
        }
    }
}

最佳答案

您可以在 addCircle 和 addSquare 中添加一行代码,将它们的 H 和 W(或形状本身的实例)存储在序列化数组(可以保存到 .dat 文件)中。然后读取 dat 文件中每个形状条目的文件和 shapes.add(tehShape) 并在需要时重新绘制。当我需要持久存储自定义 ListView 项目时,在 Android 应用程序上使用此方法。不漂亮,但一旦正确设置,它就像一个魅力。这样做的好处是您将在 dat 文件中保存相同的对象实例,缺点是它们不是人类可读的。

关于java - 如何在 JPanel 上保存图形的当前状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26089184/

相关文章:

c# - 使用 DataContractSerializer 序列化和反序列化多个对象

java - 如何使用 map 中的嵌入式集合填充对象?

java - 如何使用Android的Camera2 API

java - Gson发送epmty集合不为空

c++ - 在 C++ 中序列化一个类

java - 如何在InputDialog中等待所需的输入?

java - 在android中绘制圆圈并填充颜色而不使用canvas

java - 在 Jasmin 中实例化类

java - 如何重写 HashSet 的 getValueAt ?

java - 传递给组件的Java优雅访问属性,例如JComponent a&b使用字体1颜色2。动态访问1&2,并显示它们在a&b中使用