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

只谈情不闲聊 提交于 2020-01-05 08:23:12

问题


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. I am trying to get my code to transfer items from create methods for the save and load menu items. The save event handler should call a method save() and save the list of parts in the right panel to an XML file. The load event handler should call a method load() and it should display the unmarshalled data in the right panel. I am not familiar with JAXB or XML whatsoever. 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);
}
}

回答1:


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).

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

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)

Next, we need access to the rightList outside of the initialize method, because your load and save methods will want this. We could use the ListModel, but when we load it, we need something to apply it to any way...

//...
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. 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.

Now all we need are the save and load methods...

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 ActionListeners registered to your load and save JMenuItems

Take a look at JAXB hello world example (which I used to devise the solution) and Introduction to JAXB for more details.

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

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 ;)



来源:https://stackoverflow.com/questions/31579019/marshal-save-menu-item-of-jlist-to-xml-and-unmarshal-load-menu-items

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!