【问题标题】:JFrame pane won't let another button to be clicked when re-opening itJFrame窗格在重新打开时不会让另一个按钮被单击
【发布时间】:2015-04-16 20:14:42
【问题描述】:

所以我遇到了这个问题,我需要一位乘客只选择一个座位。第一次运行的时候没问题。然而,在第二次、第三次、第四次等......时间它加载但用户无法选择另一个选择。有任何想法吗?

import java.awt.event.*;
import java.awt.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import java.lang.reflect.Constructor;

public class APlaneSeats {

JFrame frame = new JFrame("Flight");
JPanel panel = new JPanel();
int rows = 8;
int columns = 2;
public static void main(String[] args) {
    new APlaneSeats();
}

public APlaneSeats() {
    EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                panel.setLayout(new GridLayout(rows, columns));
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                Seatings();
                frame.add(panel);
                frame.setSize(250,150);

                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });
}

public void Seatings(){


    JPanel lSeats= loadSeats();

    if(lSeats == null){
        for (int row = 0; row < rows; row++) {
            String[] rowChar = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
            for (int column = 1; column < columns + 1; column++) {

                final JToggleButton button = new JToggleButton(rowChar[row] + column);
                button.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent actionEvent) {
                            AbstractButton abstractButton = (AbstractButton) actionEvent.getSource();
                            boolean selected = abstractButton.getModel().isSelected();
                            if (selected) {
                                // System.out.println(selected);
                                button.setText("Booked");
                            } else {
                                button.setText(" ");
                            }

                            //JPanel bComp = (JPanel)SwingUtilities.getWindowAncestor(button).getComponent(0) ;
                            //JButton[] buttonArray = Arrays.copyOf(bComp, bComp.length, JButton[].class);
                            saveSeats(panel);

                            SwingUtilities.getWindowAncestor(button).dispose();
                        }
                    });
                panel.add(button);

            }
        }
        panel.setSize(250,150);
    }
    else{
        panel = lSeats;

        for (int row = 0; row < rows; row++) {
            String[] rowChar = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
            for (int column = 1; column < columns + 1; column++) {

                final JToggleButton button = new JToggleButton(rowChar[row] + column);
                button.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent actionEvent) {
                            AbstractButton abstractButton = (AbstractButton) actionEvent.getSource();
                            boolean selected = abstractButton.getModel().isSelected();
                            if (selected) {
                                // System.out.println(selected);
                                button.setText("Booked");
                            } else {
                                button.setText(" ");
                            }

                            //JPanel bComp = (JPanel)SwingUtilities.getWindowAncestor(button).getComponent(0) ;
                            //JButton[] buttonArray = Arrays.copyOf(bComp, bComp.length, JButton[].class);
                            saveSeats(panel);

                            SwingUtilities.getWindowAncestor(button).dispose();
                            panel.add(button);
                        }
                    });

            }
        }

    }

}

private JPanel loadSeats(){
    ObjectInputStream inputFile;
    try{ //To locate and open the file
        inputFile = new ObjectInputStream(new BufferedInputStream(new FileInputStream("seats.rsy")));
    }catch(FileNotFoundException fnf){
        return null;
    }catch(IOException io){
        JOptionPane.showMessageDialog(null,"An error was encountered. \n\n"+io.toString(),"Error", JOptionPane.ERROR_MESSAGE);
        return null;
    }

    try{
        JPanel loadedObject = (JPanel)inputFile.readObject(); //Loads the contents of the file.
        inputFile.close(); //Closes the stream
        return loadedObject;
    }catch(IOException io){
        JOptionPane.showMessageDialog(null,"An error was encountered. \n\n"+io.toString(),"Error", JOptionPane.ERROR_MESSAGE);
        return null;
    }catch(ClassNotFoundException cnf){
        JOptionPane.showMessageDialog(null,"An error was encountered. \n\n"+cnf.toString(),"Error", JOptionPane.ERROR_MESSAGE);
        return null;
    }
}

private void saveSeats(JPanel sSeats){
    try{ 
        ObjectOutputStream outputFile = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("seats.rsy"))); //Opens the ObjectOutputStream and a FileOutputStream (whcih is used to write to files).
        outputFile.writeObject(sSeats); //Writes the object into the file
        outputFile.flush();     //Flushes any data from the buffer to the file
        outputFile.close();     //Closes the stream since the output is done
    }catch(IOException io){
        JOptionPane.showMessageDialog(null,"An error was encountered. \n\n"+io.toString(),"Error", JOptionPane.ERROR_MESSAGE);
    }
}
}

【问题讨论】:

    标签: java swing button jframe bluej


    【解决方案1】:

    UI 组件的序列化是坏主意。看来,当您反序列化 JPanel 时,ActionListeners 没有被重新注册。

    此外,当您从文件加载对象时,您不应该重新构建 JToggleButtons,您应该直接添加到屏幕

        if (lSeats == null) {
            //...
        } else {
            frame.remove(panel);
            panel = lSeats;
            frame.add(panel);
        }
    

    因为它带有您之前创建的所有按钮。问题是,ActionListeners 似乎不是序列化数据的一部分

    更好的选择是序列化数据,可能使用 JAXB 或 Properties 文件或纯文本。这将数据从视图中分离出来,并且更易于管理......

    例如...

    import java.awt.EventQueue;
    import java.awt.GridLayout;
    import java.awt.event.ActionEvent;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    import javax.swing.AbstractAction;
    import javax.swing.JFrame;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JToggleButton;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    
    public class APlaneSeats {
    
        JFrame frame = new JFrame("Flight");
        JPanel panel = new JPanel();
        int rows = 8;
        int columns = 2;
    
        private Map<String, Boolean> bookings;
    
        public static void main(String[] args) {
            new APlaneSeats();
        }
    
        public APlaneSeats() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
    
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                        ex.printStackTrace();
                    }
    
                    panel.setLayout(new GridLayout(rows, columns));
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    Seatings();
                    frame.add(panel);
                    frame.setSize(250, 150);
    
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
    
                }
            });
        }
    
        public void Seatings() {
    
            bookings = loadSeats();
    
            for (String key : bookings.keySet()) {
    
                JToggleButton button = new JToggleButton(new BookingAction(key, bookings.get(key)));
                panel.add(button);
    
            }
    
        }
    
        private Map<String, Boolean> loadSeats() {
            bookings = new HashMap<>(rows * columns);
            String[] rowChar = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
            for (int row = 0; row < rows; row++) {
                for (int column = 1; column < columns + 1; column++) {
                    bookings.put(rowChar[row] + column, false);
                }
            }
            File seats = new File("Seats.properties");
            if (seats.exists()) {
                Properties p = new Properties();
                try (InputStream is = new FileInputStream(seats)) {
                    p.load(is);
                    for (Object key : p.keySet()) {
                        bookings.put(key.toString(), Boolean.parseBoolean(p.getProperty(key.toString())));
                    }
                } catch (IOException exp) {
                    exp.printStackTrace();
                    JOptionPane.showMessageDialog(null, "An error was encountered. \n\n" + exp.toString(), "Error", JOptionPane.ERROR_MESSAGE);
                }
            }
            return bookings;
        }
    
        private void saveSeats() {
            Properties p = new Properties();
            for (String key : bookings.keySet()) {
                p.put(key, bookings.get(key).toString());
            }
            try (OutputStream os = new FileOutputStream("Seats.properties")) {
                p.store(os, "Bookings");
            } catch (IOException exp) {
                exp.printStackTrace();
                JOptionPane.showMessageDialog(null, "An error was encountered. \n\n" + exp.toString(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        }
    
        protected void setBooked(String name) {
    
            bookings.put(name, true);
            saveSeats();
            frame.dispose();
    
        }
    
        public class BookingAction extends AbstractAction {
    
            public BookingAction(String name, boolean booked) {
                super(booked ? "Booked" : name);
                putValue(SELECTED_KEY, booked);
                setEnabled(!booked);
            }
    
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
    
                setBooked((String) getValue(NAME));
    
            }
    
        }
    }
    

    【讨论】:

    • 我知道为什么但它不会运行:/
    • 整个东西在蓝色j上试一试
    • 哪个版本?你的还是我的?
    【解决方案2】:

    您需要将第二次添加的按钮移出监听器:

            SwingUtilities.getWindowAncestor(button).dispose();
            panel.add(button);
        }
    });
    

    应该是这样的:

            SwingUtilities.getWindowAncestor(button).dispose();
        }
    });
    panel.add(button);
    

    【讨论】:

    • 你已经把代码移到了方法之外,这意味着它不会再编译了
    • @MadProgrammer }); 是监听器方法的结尾,所以它会编译得很好。
    • @MadProgrammer 是的,感谢您的提示:D
    • 答案@Salah:很好,但现在我注意到我无法在第三次、第四次、第五次尝试等时输入新选择...
    • 不,你可以,但你的问题是你在每个选择上添加按钮,这会复制按钮。
    猜你喜欢
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 2019-04-12
    • 2013-07-12
    • 2013-03-19
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    相关资源
    最近更新 更多