代码之家  ›  专栏  ›  技术社区  ›  frillybob

JList未在单独窗格中更新(Swing、Java)

  •  0
  • frillybob  · 技术社区  · 9 年前

    在名为“密码库”的第一个选项卡上,我有一个JList,其中包含存储密码的“网站”列表。在第二个选项卡上,我有一个添加“密码”功能。当我添加密码时,JList仅在窗格中更新。当我切换回另一个选项卡“密码保险库”时,它尚未更新。当我重新启动该程序时,它已被更新。我使用字段,所以这不是局部变量的问题。

    public final class PasswordManagerView1 extends JFrame
        implements PasswordManagerView, ListSelectionListener {
    /**
     * JList.
     */
    private JList<String> list;
    
    /**
     * JButtons.
     */
    private JButton enter, unlock, reset, buttonAddEnter;
    
    /**
     * Controller.
     */
    private PasswordManagerController controller;
    
    /**
     * Dimensions.
     */
    private Dimension maxSize;
    
    /**
     * JTabbedPanes.
     */
    private JTabbedPane tabbedPane;
    
    /**
     * JTextField.
     */
    private JTextField passwordDisplay, textField;
    
    /**
     * PasswordField.
     */
    private JPasswordField passwordField, resetField, passwordFieldadd;
    
    /**
     * Useful Constants.
     */
    private static final int MAX_SIZE_HORI = 800, MAX_SIZE_VERTI = 400,
            EMPTY_BORDER_SIZE = 5;
    
    /**
     * Constructor.
     */
    public PasswordManagerView1() {
        super("Password Manager");
        JTabbedPane tabbedPane = new JTabbedPane();
        //Initial JPanel creation
        tabbedPane.setBorder(
                new EmptyBorder(PasswordManagerView1.EMPTY_BORDER_SIZE,
                        PasswordManagerView1.EMPTY_BORDER_SIZE,
                        PasswordManagerView1.EMPTY_BORDER_SIZE,
                        PasswordManagerView1.EMPTY_BORDER_SIZE));
        this.maxSize = new Dimension(PasswordManagerView1.MAX_SIZE_HORI,
                PasswordManagerView1.MAX_SIZE_VERTI);
        tabbedPane.setPreferredSize(this.maxSize);
        this.getContentPane().add(tabbedPane);
    
        //Initial JTabbedPane creation
    
        //Tab creation
        JComponent panel1 = this.makePasswordVault();
        ImageIcon icon = new ImageIcon("lock-icon.png");
        tabbedPane.addTab("Password Vault", icon, panel1,
                "View the passwords in the vault");
        JComponent panel3 = this.makeAddPanel("Add Password");
        tabbedPane.addTab("Add Password", icon, panel3,
                "Add passwords to the vault");
        //JComponent panel2 = this.makeAddPanel("ALSO ADDS");
        //tabbedPane.addTab("Delete Password", icon, panel2,
        //        "Deletes a password from the vault");
    
        JComponent panel4 = this.makeInfoPanel();
        tabbedPane.addTab("Info", icon, panel4,
                "View settings and program info");
        //Pack up
        this.setResizable(false);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
    
    @Override
    public JComponent makeAddPanel(String text) {
        JPanel panel = new JPanel();
        panel.setLayout(null);
        //Creation of string array of with stores
        String[] listContentC = this.getStore();
    
        this.list = new JList<>(listContentC);
        this.list.setBounds(0, 0, 233, 360);
        JScrollPane pane = new JScrollPane(this.list);
        pane.setBounds(0, 0, 233, 360);
        panel.add(pane);
        JLabel labelAdd = new JLabel("Add Password");
        labelAdd.setHorizontalAlignment(SwingConstants.CENTER);
        labelAdd.setFont(new Font("Times New Roman", Font.PLAIN, 24));
        labelAdd.setBounds(427, 38, 163, 31);
        panel.add(labelAdd);
    
        this.passwordFieldadd = new JPasswordField();
        this.passwordFieldadd.setBounds(536, 100, 116, 22);
        panel.add(this.passwordFieldadd);
    
        this.textField = new JTextField();
        this.textField.setBounds(375, 100, 116, 22);
        panel.add(this.textField);
    
        JLabel lblWebsite = new JLabel("Website");
        lblWebsite.setHorizontalAlignment(SwingConstants.CENTER);
        lblWebsite.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        lblWebsite.setBounds(401, 126, 56, 16);
        panel.add(lblWebsite);
    
        JLabel lblPassword = new JLabel("Password");
        lblPassword.setHorizontalAlignment(SwingConstants.CENTER);
        lblPassword.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        lblPassword.setBounds(566, 126, 56, 16);
        panel.add(lblPassword);
    
        this.buttonAddEnter = new JButton("Enter");
        this.buttonAddEnter.setBounds(465, 161, 97, 25);
        panel.add(this.buttonAddEnter);
        this.buttonAddEnter.addActionListener(this);
        return panel;
    }
    
    @Override
    public JComponent makeInfoPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(1, 1));
        StringBuilder toPrint = new StringBuilder();
        SimpleReader in = new SimpleReader1L("data/Notice.txt");
        while (!in.atEOS()) {
            toPrint.append(in.nextLine() + "\n");
        }
        String toPrintString = toPrint.toString();
        JTextArea noticeText = new JTextArea(toPrintString);
        noticeText.setEditable(false);
        JScrollPane noticeTextScroll = new JScrollPane(noticeText);
        panel.add(noticeTextScroll);
        in.close();
        return panel;
    
    }
    
    @Override
    public JComponent makePasswordVault() {
        JPanel panel = new JPanel();
        panel.setLayout(null);
        /*
         * Ask for help on this.
         *
         * I would have liked to create the listContentC by passing nothing into
         * the controller and then the controller using the model to extract the
         * data from a text file. However, my array was always initialized to
         * something null and caused a runtime error.
         *
         *
         */
    
        //Creation of string array of with stores
        String[] listContentC = this.getStore();
    
        //GUI setup of list
        this.list = new JList<>(listContentC);
        this.list.setLayoutOrientation(JList.VERTICAL);
        this.list.addListSelectionListener(this);
        JScrollPane pane = new JScrollPane(this.list);
        pane.setBounds(0, 0, 233, 360);
        panel.add(pane);
    
        //The label creation (for instructions)
        JLabel labelA = new JLabel("the store and press enter!");
        labelA.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        labelA.setBounds(294, 70, 157, 31);
        panel.add(labelA);
        JLabel labelB = new JLabel("To view a password, click on");
        labelB.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        labelB.setBounds(284, 54, 163, 31);
        panel.add(labelB);
    
        //Enter button creation
        this.enter = new JButton("Enter");
        this.enter.setBounds(303, 128, 116, 25);
        panel.add(this.enter);
        this.enter.setEnabled(false);
        this.enter.addActionListener(this);
    
        //Password Display field creation
        this.passwordDisplay = new JTextField();
        this.passwordDisplay.setBackground(Color.WHITE);
        this.passwordDisplay.setEditable(false);
        this.passwordDisplay
                .setFont(new Font("Times New Roman", Font.PLAIN, 13));
        this.passwordDisplay.setHorizontalAlignment(SwingConstants.CENTER);
        this.passwordDisplay.setText("");
        this.passwordDisplay.setBounds(303, 247, 116, 22);
        panel.add(this.passwordDisplay);
        this.passwordDisplay.setColumns(10);
    
        //Password Label creation
        JLabel passwordLabel = new JLabel("Password:");
        passwordLabel.setHorizontalAlignment(SwingConstants.CENTER);
        passwordLabel.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        passwordLabel.setBounds(336, 218, 56, 16);
        panel.add(passwordLabel);
    
        //Master password notice
        JLabel mastPass = new JLabel("Enter master password to unlock vault:");
        mastPass.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        mastPass.setBounds(532, 54, 218, 31);
        panel.add(mastPass);
    
        //Password Field
        this.passwordField = new JPasswordField();
        this.passwordField.setBounds(532, 128, 116, 24);
        panel.add(this.passwordField);
    
        //Unlock button
        this.unlock = new JButton("Unlock");
        this.unlock.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        this.unlock.setBounds(660, 127, 97, 25);
        panel.add(this.unlock);
        this.unlock.addActionListener(this);
    
        //New setup label
        JLabel labelC = new JLabel("Reset/Set up new master pass:");
        labelC.setHorizontalAlignment(SwingConstants.CENTER);
        labelC.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        labelC.setBounds(532, 217, 218, 16);
        panel.add(labelC);
    
        //New setup label
        JLabel defaultLabel = new JLabel("Default Password = \"password\"");
        defaultLabel.setHorizontalAlignment(SwingConstants.CENTER);
        defaultLabel.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        defaultLabel.setBounds(560, 77, 171, 16);
        panel.add(defaultLabel);
    
        this.resetField = new JPasswordField();
        this.resetField.setBounds(532, 246, 116, 24);
        panel.add(this.resetField);
    
        this.reset = new JButton("Update");
        this.reset.setFont(new Font("Times New Roman", Font.PLAIN, 13));
        this.reset.setBounds(660, 245, 97, 25);
        this.reset.setEnabled(false);
        panel.add(this.reset);
        this.reset.addActionListener(this);
        return panel;
    }
    
    @Override
    public String[] getStore() {
    
        int storeCount = 0;
        SimpleReader in = new SimpleReader1L("data/store.txt");
        while (!in.atEOS()) {
            storeCount++;
            in.nextLine();
        }
        in.close();
        String[] listContentC = new String[storeCount];
        SimpleReader in2 = new SimpleReader1L("data/store.txt");
        for (int i = 0; i < storeCount; i++) {
            listContentC[i] = in2.nextLine();
        }
        in2.close();
        return listContentC;
    }
    
    @Override
    public void registerObserver(PasswordManagerController controller) {
        this.controller = controller;
    }
    
    @Override
    public void updateEnterButtonVaultTab(boolean result) {
        this.enter.setEnabled(result);
    }
    
    @Override
    public void actionPerformed(ActionEvent event) {
        //Wait cursor
        this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    
        //What button was pressed
        Object source = event.getSource();
        if (source == this.enter) {
            int index = this.list.getSelectedIndex();
            System.out.println(index);
            if (this.list.getSelectedIndex() != -1) {
                this.controller.processEnterEvent(this.list.getSelectedValue());
            }
        } else if (source == this.unlock) {
            this.controller
                    .processUnlockEvent(this.passwordField.getPassword());
        } else if (source == this.reset) {
            this.controller.processResetEvent(this.resetField.getPassword());
        } else if (source == this.buttonAddEnter) {
            this.controller.processAddEvent(this.textField.getText(),
                    this.passwordFieldadd.getPassword());
            //needs done in model
            this.updateListModel();
        }
        this.setCursor(Cursor.getDefaultCursor());
    }
    
    @Override
    public void updateListModel() {
        //MOVE TO THE MODEL
        String[] temp = this.getStore();
        DefaultListModel<String> temp2 = new DefaultListModel<>();
        for (int i = 0; i < temp.length; i++) {
            temp2.addElement(temp[i]);
        }
        this.list.setModel(temp2);
    }
    
    @Override
    public JTabbedPane getTabbedPane() {
        return this.tabbedPane;
    }
    
    @Override
    public void setTabbedPane(JTabbedPane tabbedPane) {
        this.tabbedPane = tabbedPane;
    }
    
    @Override
    public void updatePasswordField() {
        this.passwordField.setText("");
    }
    
    @Override
    public void updateResetPasswordDisplay() {
        this.resetField.setText("");
    }
    
    @Override
    public void displayWrongPass() {
        JOptionPane.showMessageDialog(this, "Wrong password entered!");
    
    }
    
    @Override
    public void displayUpdatedPass() {
        JOptionPane.showMessageDialog(this, "Master password updated!");
    }
    
    @Override
    public void updateResetButton(boolean result) {
        this.reset.setEnabled(result);
    }
    
    @Override
    public void updatePasswordDisplay(char[] password) {
        StringBuilder passwordCreation = new StringBuilder();
        for (int i = 0; i < password.length; i++) {
            passwordCreation.append(password[i]);
        }
        this.passwordDisplay.setText(passwordCreation.toString());
    
    }
    
    @Override
    public JComponent makeTextPanel(String text) {
        // TODO Auto-generated method stub
        return null;
    }
    
    @Override
    public void valueChanged(ListSelectionEvent arg0) {
    
    }
    
    }
    
    3 回复  |  直到 9 年前
        1
  •  4
  •   FredK    9 年前

    构造函数调用makePasswordPanel(),其中包含以下行:

       this.list = new JList<>(listContentC);
    

    然后构造函数调用makeAddPanel(),该函数具有以下行:

    这list=新的JList<>(列表内容C);
    

    因此,现在您已经放弃了第一个列表的句柄,并将其替换为对新列表的引用。然后在updateListModel中,更改此的模型。列表(这是makeAddPanel列表)。无法同时更新密码面板的模型,因为您已经放弃了对该面板的引用。

        2
  •  1
  •   Community Mohan Dere    8 年前

    同样,要显示多个JList,所有的JList都显示相同的内容,那么所有的Jlist都应该共享相同的模型。如果您这样做,那么对一个JList所做的更改将反映在所有其他JList中,因为这些更改实际上并不是对JList本身所做的(它只显示模型的内容),而是对共享模型所做的。为了理解这一点,您需要阅读MVC或Model-View-Controller设计模式,因为Swing组件使用 变种 这一点。

    例如,请参阅下面的代码,其中我创建了3个JPanel,每个JPanel都有自己的JList,但它们都共享相同的内容 DefaultListModel<String> 注意,我有三个JPanel都是从一个父类扩展而来的,该父类实际上包含JList并在其构造函数中接受模型。然后,如果我在一个JPanel中添加列表项或在另一个JPpanel中删除列表项,它们都会显示在3个JPanels的所有列表中。还可以查看我是如何最小化代码,使其接近编译、运行和显示问题或解决方案所需的最小值的 minimal code example program 或MCVE:

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import java.awt.event.KeyEvent;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class PanelsWithSharedList extends JPanel {
        private static final int PREF_W = 400;
        private static final int PREF_H = 250;
        private JTabbedPane tabbedPane = new JTabbedPane();
        private DefaultListModel<String> listModel = new DefaultListModel<>();
    
        public PanelsWithSharedList() {
            for (int i = 0; i < 10; i++) {
                listModel.addElement("List element " + (i + 1));
            }
    
            setLayout(new BorderLayout());
            add(tabbedPane);
            tabbedPane.add("Panel 1", new ListShowingPanel1(listModel));
            tabbedPane.add("Panel 2", new ListShowingPanel2(listModel));
            tabbedPane.add("Panel 3", new ListShowingPanel3(listModel));
        }
    
        @Override
        public Dimension getPreferredSize() {
            Dimension superSz = super.getPreferredSize();
            if (isPreferredSizeSet()) {
                return superSz;
            }
            int prefW = Math.max(superSz.width, PREF_W);
            int prefH = Math.max(superSz.height, PREF_H);
            return new Dimension(prefW, prefH);
        }
    
        private static void createAndShowGui() {
            PanelsWithSharedList mainPanel = new PanelsWithSharedList();
    
            JFrame frame = new JFrame("Panels With Shared List");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    
    @SuppressWarnings("serial")
    abstract class AbstractListShowingPanel extends JPanel {
        private JList<String> list;
    
        public AbstractListShowingPanel(DefaultListModel<String> listModel) {
            list = new JList<>(listModel);
            list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        }
    
        public JList<String> getList() {
            return list;
        }
    
        public DefaultListModel<String> getModel() {
            return (DefaultListModel<String>) list.getModel();
        }
    }
    
    @SuppressWarnings("serial")
    class ListShowingPanel1 extends AbstractListShowingPanel {
        private JTextField textField = new JTextField(10);
    
        public ListShowingPanel1(DefaultListModel<String> listModel) {
            super(listModel);
            add(new JScrollPane(getList()));
            add(new JLabel("Text to add:"));
    
            Action action = new AddTextAction();
            textField.setAction(action);
            add(textField);
            add(new JButton(action));
    
        }
    
        private class AddTextAction extends AbstractAction {
            public AddTextAction() {
                super("Add Text");
                putValue(MNEMONIC_KEY, KeyEvent.VK_A);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                getModel().addElement(textField.getText());
                textField.selectAll();
            }
        }
    
    }
    
    @SuppressWarnings("serial")
    class ListShowingPanel2 extends AbstractListShowingPanel {
        public ListShowingPanel2(DefaultListModel<String> listModel) {
            super(listModel);
            add(new JScrollPane(getList()));
            add(new JButton(new DeleteItemAction()));
        }
    
        private class DeleteItemAction extends AbstractAction {
            public DeleteItemAction() {
                super("Delete Selected Item");
                putValue(MNEMONIC_KEY, KeyEvent.VK_D);
            }
    
            public void actionPerformed(ActionEvent e) {
                JList<String> list = getList();
                String selection = list.getSelectedValue();
                if (selection != null) {
                    getModel().removeElement(selection);
                }
            }
        }
    }
    
    @SuppressWarnings("serial")
    class ListShowingPanel3 extends AbstractListShowingPanel {
        public ListShowingPanel3(DefaultListModel<String> listModel) {
            super(listModel);
            setLayout(new BorderLayout());
            add(new JScrollPane(getList()));
        }
    }
    
        3
  •  0
  •   Jorge_B    9 年前

    仅从学术角度来看,我建议将图形元素和底层数据模型之间的这种关系实现为观察者模式( https://en.wikipedia.org/wiki/Observer_pattern ). 当您开始使用5或6个GUI元素来响应同一共享数据结构中的更改时,您向我们展示的方法可能很快就会变得令人困惑和难以维护。