简体   繁体   English

将jlist的菜单项编组为XML并解组加载菜单项

[英]Marshal save menu item of jlist to XML and unmarshal load menu items

I have been doing research on here and have been searching for a solution to the problem. 我一直在这里进行研究,并一直在寻找解决问题的方法。 I am new to java so I don't know all of the syntax. 我是Java的新手,所以我不了解所有语法。 I am trying to get my code to transfer items from create methods for the save and load menu items. 我正在尝试获取我的代码,以便从保存和加载菜单项的create方法转移项。 The save event handler should call a method save() and save the list of parts in the right panel to an XML file. save事件处理程序应调用方法save()并将右侧面板中的零件列表保存到XML文件。 The load event handler should call a method load() and it should display the unmarshalled data in the right panel. 加载事件处理程序应调用方法load(),并应在右侧面板中显示未编组的数据。 I am not familiar with JAXB or XML whatsoever. 我对JAXB或XML都不熟悉。 I have tried to see if anyone else has done something similar but I cannot complete the code. 我试图看看是否有人做过类似的事情,但是我无法完成代码。 Can anyone help me out please? 有人可以帮我吗? Below is the entire code. 以下是整个代码。 I have found the solution to make it exit using event handlers, but I am stuck on marshalling and unmarshalling the save and load menu items. 我已经找到了使它使用事件处理程序退出的解决方案,但是我被困于编组和解组保存和加载菜单项。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

public class Window {

private final JFrame frame;

public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
        Window window = new Window();
        window.frame.setVisible(true);

    });
}

public Window() {
    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(null);

    initialize();
}

public void initialize() {
    //Creating the Panel for Menu Bar       
    JPanel panel = new JPanel();
    panel.setBounds(0, 0, 434, 23);
    frame.getContentPane().add(panel);
    panel.setLayout(new BorderLayout(0, 0));
    //Creating the Menu File Bar
    JMenuBar bar = new JMenuBar();
    panel.add(bar, BorderLayout.NORTH);
    JMenu file = new JMenu("File");
    JMenuItem load = new JMenuItem("Load");
    JMenuItem save = new JMenuItem("Save");
    JMenuItem exit = new JMenuItem("Exit");
    file.add(load);
    load.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent event) {


    }
    });
    file.add(save);
    save.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent event) {


    }
    });
    file.add(exit);
    exit.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent event) {
            System.exit(0);
    }
    });
    bar.add(file);

    //Populate Left List with part names    
    final DefaultListModel parts = new DefaultListModel();
    parts.addElement("Case");
    parts.addElement("Motherboard");
    parts.addElement("CPU");
    parts.addElement("GPU");
    parts.addElement("PSU");
    parts.addElement("RAM");
    parts.addElement("HDD");

    final JList leftList = new JList(parts);
    leftList.setBounds(10, 26, 142, 224);
    frame.getContentPane().add(leftList);

    //create right list 
    final DefaultListModel partSelected = new DefaultListModel();
    final JList rightList = new JList(partSelected);
    rightList.setBounds(282, 26, 142, 224);
    frame.getContentPane().add(rightList);

    //add event to the button to move items from left list to right list
    JButton btnNewButton = new JButton(">>");
    btnNewButton.addActionListener((ActionEvent arg0) -> {
        for (Object selectedValue : leftList.getSelectedValuesList()) {
            partSelected.addElement(selectedValue);
            parts.removeElement(selectedValue);
            int iSelected = leftList.getSelectedIndex();
            if (iSelected == -1) {
                return;
            }
        }
    });
    btnNewButton.setBounds(172, 86, 89, 23);
    frame.getContentPane().add(btnNewButton);

    //Remove Button     
    JButton remove = new JButton("<<");
    remove.addActionListener((ActionEvent arg0) -> {
        for (Object selectedValue : rightList.getSelectedValuesList()) {
            parts.addElement(selectedValue);
            partSelected.removeElement(selectedValue);
            int selected = rightList.getSelectedIndex();
            if (selected == -1) {
                return;
            }
        }
    });
    remove.setBounds(172, 140, 89, 23);
    frame.getContentPane().add(remove);
}
}

Okay, so you first need to understand that JAXB is meant for the serialization of Objects to and from XML (via the use of annotations). 好的,因此您首先需要了解JAXB是用于将对象与XML进行序列化(通过使用批注)的。

So, the first thing you need is some kind of object to serialize which contains your produces. 因此,您需要做的第一件事是对包含您的产品的对象进行序列化。 A ListModel would seem like a perfect choice, except, it's not setup for the task, it has no annotations by which JAXB can make decisions about what should be serialized or not ListModel似乎是一个完美的选择,除了它不是为任务设置的,它没有注释,JAXB可以通过该注释来决定应序列化或不序列化的内容

So, we need to create one... 因此,我们需要创建一个...

@XmlRootElement
public static class ProductListModel extends AbstractListModel<String> {

    private List<String> products;

    public ProductListModel() {
        products = new ArrayList<>(25);
    }

    @XmlElementWrapper
    public List<String> getProducts() {
        return products;
    }

    public void add(String product) {
        products.add(product);
        fireIntervalAdded(this, products.size() - 1, products.size() - 1);
    }

    public void remove(String product) {
        int index = products.indexOf(product);
        products.remove(product);
        fireIntervalAdded(this, index, index);
    }

    @Override
    public int getSize() {
        return products.size();
    }

    @Override
    public String getElementAt(int index) {
        return products.get(index);
    }
}

(Now, you could argue that something like ArrayList might be better, but I'd say that's extending the class for little or no gain and would probably account for a lot more work as you try and figure out how to serialize it's buffer) (现在,您可能会说像ArrayList之类的东西可能会更好,但我想说这是在扩展类而几乎没有收获,或者在尝试找出如何序列化其缓冲区时可能会占用更多的工作)

Next, we need access to the rightList outside of the initialize method, because your load and save methods will want this. 接下来,我们需要访问initialize方法外部的rightList ,因为您的loadsave方法将需要此方法。 We could use the ListModel , but when we load it, we need something to apply it to any way... 我们可以使用ListModel ,但是在加载它时,我们需要一些东西以任何方式将其应用...

//...
private JList rightList;

public void initialize() {
    //...
    final ProductListModel parts = new ProductListModel();
    parts.add("Case");
    parts.add("Motherboard");
    parts.add("CPU");
    parts.add("GPU");
    parts.add("PSU");
    parts.add("RAM");
    parts.add("HDD");

    leftList = new JList(parts);
    leftList.setBounds(10, 26, 142, 224);
    frame.getContentPane().add(leftList);

    //create right list 
    final ProductListModel partSelected = new ProductListModel();
    //JList rightList = new JList(partSelected);
    rightList = new JList(partSelected);

This also changes the use of DefaultListModel to ProductListModel . 这还将DefaultListModel的使用更改为ProductListModel Technically, this is only required for rightList , but since I've changed the add and remove method names of the ListModel (which will cause you a compiler error, so you will need to update those), it just makes life easier. 从技术上讲,这仅对于rightList是必需的,但是由于我已经更改了ListModeladdremove方法名称(这将导致您出现编译器错误,因此您需要更新这些名称),这只会使工作变得更轻松。

Now all we need are the save and load methods... 现在我们需要的只是saveload方法...

protected void save() {
    ProductListModel model = (ProductListModel) rightList.getModel();

    try {
        File file = new File("Products.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(ProductListModel.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        jaxbMarshaller.marshal(model, file);
        jaxbMarshaller.marshal(model, System.out);
    } catch (JAXBException exp) {
        exp.printStackTrace();
    }
}

protected void load() {
    try {
        File file = new File("Products.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(ProductListModel.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        ProductListModel model = (ProductListModel) jaxbUnmarshaller.unmarshal(file);
        rightList.setModel(model);
    } catch (JAXBException exp) {
        exp.printStackTrace();
    }
}

Which you need to call from the ActionListener s registered to your load and save JMenuItem s 您需要从注册到loadsave JMenuItemActionListener调用该方法

Take a look at JAXB hello world example (which I used to devise the solution) and Introduction to JAXB for more details. 看一下JAXB hello world示例 (我用来设计解决方案的示例 )和JAXB简介以获得更多详细信息。

You'll probably also want to have a look at How to Use Lists , How to Use Scroll Panes and Laying Out Components Within a Container to help improve your UI 您可能还想看看如何使用列表如何使用滚动窗格以及在容器中布置组件以帮助改善UI

Now, when you load the ProductList , you will need to figure out how to modify the leftList to remove the items which now appear in the right ;) 现在,当您加载ProductList ,您将需要弄清楚如何修改leftList以删除现在显示在右侧的项目;)

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

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