保存Java GUI状态

时间:2018-05-06 04:21:14

标签: java

我很擅长用Java创建GUI,所以我不确定这是否容易或难以做到。我正在创建一个随机名称选择器,用户输入名称然后随机选择一些。我试图让它保存应用程序关闭后输入的名称,然后在重新打开时放回。我不确定最好的方法;我已经浏览了一下并阅读了一些关于序列化的内容,但它并没有多大意义。这是我目前为止来自NetBeans的代码。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.DefaultListModel;
import sun.applet.Main;
import sun.audio.*;
public class NameChooser extends javax.swing.JFrame {

private ArrayList <Integer> integers;
private Integer index;
private DefaultListModel dlm;

    /**
     * Creates new form NameChooser
     */
    public NameChooser() 
    {
        initComponents();
        integers = new ArrayList <Integer>();
        dlm = new DefaultListModel();

    }
public Integer generateNum()
    {
       int pings = 0;
       do
       {
           pings = 0;
           int temp = (int)(Math.random() * dlm.getSize());
           index = new Integer(temp);
           for (int k = 0; k < integers.size(); k++)
           {
               if ((integers.get(k).compareTo(index)) == 0)
               {
                    pings++;
               }      
           }

       }   
       while (pings != 0); 
       return index;
    }
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
    private void initComponents() {

        selectButton = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        names = new javax.swing.JList<>();
        nameField = new javax.swing.JTextField();
        resetButton = new javax.swing.JButton();
        removeButton = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        selectButton.setFont(new java.awt.Font("Dialog", 1, 18)); // NOI18N
        selectButton.setText("Choose Name");
        selectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                selectButtonActionPerformed(evt);
            }
        });

        names.setFixedCellHeight(30);
        names.setFixedCellWidth(200);
        names.setLayoutOrientation(javax.swing.JList.VERTICAL_WRAP);
        jScrollPane2.setViewportView(names);

        nameField.setText("Enter Name Here");
        nameField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                nameFieldActionPerformed(evt);
            }
        });

        resetButton.setText("Reset");
        resetButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                resetButtonActionPerformed(evt);
            }
        });

        removeButton.setText("Remove");
        removeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeButtonActionPerformed(evt);
            }
        });
        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(layout.createSequentialGroup()
                        .addGap(349, 349, 349)
                        .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 197, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(resetButton))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addGap(23, 23, 23)
                                .addComponent(removeButton)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                            .addGroup(layout.createSequentialGroup()
                                .addContainerGap()
                                .addComponent(nameField, javax.swing.GroupLayout.DEFAULT_SIZE, 117, Short.MAX_VALUE)
                                .addGap(18, 18, 18)))
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 589, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addGap(64, 64, 64))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(119, 119, 119)
                .addComponent(nameField, javax.swing.GroupLayout.PREFERRED_SIZE, 28, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(26, 26, 26)
                .addComponent(removeButton)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addComponent(selectButton, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(26, 26, 26))
            .addGroup(layout.createSequentialGroup()
                .addContainerGap(84, Short.MAX_VALUE)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 418, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(resetButton)
                .addGap(40, 40, 40))
        );

        pack();
    }// </editor-fold>                        



    private void selectButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
            integers.add(generateNum());
            if (integers.size() <= dlm.getSize())
            {


            int [] indexes = new int [integers.size()];
            for (int i = 0; i < indexes.length; i++)
            {
                indexes[i] = integers.get(i).intValue();
            }
            try {
         // Open an audio input stream.
         File soundFile = new File("C:\\Users\\Oskar\\Desktop\\sound.wav");
         AudioInputStream audioIn = AudioSystem.getAudioInputStream(soundFile);
         // Get a sound clip resource.
         Clip clip = AudioSystem.getClip();
         // Open audio clip and load samples from the audio input stream.
         clip.open(audioIn);
         clip.start();
      } catch (UnsupportedAudioFileException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (LineUnavailableException e) {
         e.printStackTrace();
      }
            //playSound();

            names.setSelectedIndices(indexes);
            }
    }                                            


    private void resetButtonActionPerformed(java.awt.event.ActionEvent evt) {                                            
        integers.clear();
        int[]indexes = new int[0];
        names.setSelectedIndices(indexes);
    }                                           

    private void nameFieldActionPerformed(java.awt.event.ActionEvent evt) {                                          
       //Add Name
       int size = nameField.getDocument().getLength();
       if (size <= 0)
           return;
       dlm.addElement(nameField.getText());
       nameField.setText("");
       names.setModel(dlm);
    }                                         

    private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
        if (names.getSelectedIndex() != -1)
        {
            dlm.remove(names.getSelectedIndex());
        }

    }                                            

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(NameChooser.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(NameChooser.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(NameChooser.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NameChooser.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NameChooser().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify                     
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTextField nameField;
    private javax.swing.JList<String> names;
    private javax.swing.JButton removeButton;
    private javax.swing.JButton resetButton;
    private javax.swing.JButton selectButton;
    // End of variables declaration                   
}

我可以创建一个包含输入名称的数组或arraylist,以某种方式将其保存到文件中,然后在运行程序时加载该文件以导入名称吗?或者可能只是保存jList的状态?任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:2)

无法序列化Java GUI的状态,因为许多GUI对象不可序列化。

JList类声明为Serializable,因此您可以将其序列化。 (这取决于列表中元素的类型。它们也必须是可序列化的。)

理论上可以编写将遍历GUI数据结构的代码,将需要保存的状态提取到可序列化的数据结构中,然后对其进行序列化。然后你需要代码来做相反的事情;即从已保存的状态重建/重新填充GUI。 (但我怀疑你最好以不同的方式处理这个问题;例如使用使用属性文件或类似方法实现的自定义“首选项”机制。)

但是,您的目标是在GUI中保留您正在显示和更新的数据,最好在“模型”级别执行此操作。根据模型的性质和处理数据的要求,还有其他对象序列化的替代方案:

  • 效率更高,
  • 更具伸缩性,
  • 更能抵抗数据丢失;例如当应用程序崩溃时,
  • 更能够应对应用程序的 evolution
  • 可以从Java外部访问。

答案 1 :(得分:0)

如果您愿意,可以使用数据库来维持您的状态。但似乎只是为了保持数据库的微小成本是昂贵的。

而是将它们保存在平面文件.txt文件中,并定义自己的分隔符。

例如:

  1. 将每条记录插入新行。
  2. 记录中的每个值都由管道|分隔。
  3. 文件数据样本:

    First Name | Second Name | Anything  
    First Name 2 | Second Name 2 | Anything else
    

    然后,一旦您的应用程序加载,请检查此文件是否存在,然后阅读此文件。您需要创建一个了解文件语法的解析器。然后根据这些数据(如果有的话)填充GUI  如果您的应用程序需要,请更新文件

    另一种方法是创建一个java类&#34; State&#34; (普通POJO)然后将其序列化并将其保存在您的文件中。当应用程序加载时,然后反序列化它并在您的应用程序中使用。 问题是:

    1. 序列化和反序列化并存储文件的开销
    2. 确保在对象升级时,您需要维护旧字段(遗留),否则您的反序列化将无法工作(序列化/反序列化的常见问题)。
    3. Google主题围绕此更多详情。

答案 2 :(得分:0)

看看java.util.prefs.Preferences。当您的应用关闭时,您可以执行类似...

的操作
public void savePreferences() {
    Preferences preferences = Preferences.userNodeForPackage(NameChooser.class);
    preferences.put("names", "name1, name2, name3");
}

您必须从JList中提取名称并将其转换为逗号分隔的字符串(使用StringBuilder)。您应该可以使用JList.getModel获取它。然后当你的应用加载......

public void loadPreferences() {
    Preferences preferences = Preferences.userNodeForPackage(NameChooser.class);
    namesAsString = preferences.get("names", null);
}

String.split namesAsString并将其重新打包回JList。合理?你有一个NullPointerException因为我打赌你只是复制粘贴代码。这是一个更简单的例子:

package example;

import java.util.Date;
import java.util.prefs.Preferences;

public class Example {
    public static void main(String[] args) {
        Preferences pref = Preferences.userNodeForPackage(Example.class);
        String namesAsString = pref.get("names", "empty");
        // on first run, this will be empty because you have not saved anything yet
        // on succeeding runs, you should see something like:
        // Names in preferences: name1Mon May 07 07:15:46 BST 2018, name2Mon May 07 07:15:46 BST 2018
        System.out.println("Names in preferences: " + namesAsString);

        // simulating new name every time this is run, hence the date
        String name1 = "name1" + new Date();
        String name2 = "name2" + new Date();
        pref.put("names", name1 + ", " + name2);
    }
}