【问题标题】:Create new row containing JTextField, JComboBox and JButton on every single click在每次单击时创建包含 JTextField、JComboBox 和 JButton 的新行
【发布时间】:2018-09-26 15:04:41
【问题描述】:

我正在使用 Java GUI 创建一个 GPA 计算器。当点击“添加课程”按钮时,程序应该每次都为课程名称、学分和成绩添加一个文本字段。

我使用 HTML 和 Javascript 制作了同样的程序,这里是 https://nsuer.club/cgpa-calculator/

看截图:

我应该使用List 来存储文本字段吗?这是我在 Java GUI 上的第一个项目。

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                CgpaCalculator window = new CgpaCalculator();
                window.frmCgpaCalculator.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

/**
 * Create the application.
 */
public CgpaCalculator() {
    initialize();
}

/**
 * Initialize the contents of the frame.
 */
private void initialize() {
    frmCgpaCalculator = new JFrame();
    frmCgpaCalculator.getContentPane().setFont(new Font("Tahoma", Font.PLAIN, 17));
    frmCgpaCalculator.setTitle("CGPA Calculator");
    frmCgpaCalculator.setBounds(100, 100, 540, 683);
    frmCgpaCalculator.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frmCgpaCalculator.getContentPane().setLayout(null);

    textField = new JTextField();
    textField.setBounds(12, 140, 126, 29);
    frmCgpaCalculator.getContentPane().add(textField);
    textField.setColumns(10);

    textField_1 = new JTextField();
    textField_1.setBounds(12, 175, 126, 29);
    frmCgpaCalculator.getContentPane().add(textField_1);
    textField_1.setColumns(10);

    textField_2 = new JTextField();
    textField_2.setBounds(12, 210, 126, 29);
    frmCgpaCalculator.getContentPane().add(textField_2);
    textField_2.setColumns(10);

    textField_3 = new JTextField();
    textField_3.setBounds(12, 245, 126, 29);
    frmCgpaCalculator.getContentPane().add(textField_3);
    textField_3.setColumns(10);

    JLabel lblGrade = new JLabel("Course");
    lblGrade.setFont(new Font("Tahoma", Font.PLAIN, 15));
    lblGrade.setBounds(47, 99, 56, 16);
    frmCgpaCalculator.getContentPane().add(lblGrade);

    JComboBox comboBox = new JComboBox();
    comboBox.setToolTipText("0");
    comboBox.setModel(new DefaultComboBoxModel(new String[] {"3", "1", "2", "0", "1.5"}));
    comboBox.setBounds(181, 140, 75, 29);
    frmCgpaCalculator.getContentPane().add(comboBox);

    JLabel lblCredits = new JLabel("Credits");
    lblCredits.setFont(new Font("Tahoma", Font.PLAIN, 15));
    lblCredits.setBounds(192, 99, 56, 16);
    frmCgpaCalculator.getContentPane().add(lblCredits);

    JComboBox comboBox_4 = new JComboBox();
    comboBox_4.setModel(new DefaultComboBoxModel(new String[] {"A", "A-", "B+", "B", "B", "B-", "C+", "C", "D+", "D", "F"}));
    comboBox_4.setBounds(297, 140, 70, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_4);

    JComboBox comboBox_5 = new JComboBox();
    comboBox_5.setModel(new DefaultComboBoxModel(new String[] {"A", "A-", "B+", "B", "B", "B-", "C+", "C", "D+", "D", "F"}));
    comboBox_5.setBounds(297, 175, 70, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_5);

    JComboBox comboBox_6 = new JComboBox();
    comboBox_6.setModel(new DefaultComboBoxModel(new String[] {"A", "A-", "B+", "B", "B", "B-", "C+", "C", "D+", "D", "F"}));
    comboBox_6.setBounds(297, 210, 70, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_6);

    JComboBox comboBox_7 = new JComboBox();
    comboBox_7.setModel(new DefaultComboBoxModel(new String[] {"A", "A-", "B+", "B", "B", "B-", "C+", "C", "D+", "D", "F"}));
    comboBox_7.setBounds(297, 245, 70, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_7);

    JComboBox comboBox_1 = new JComboBox();
    comboBox_1.setModel(new DefaultComboBoxModel(new String[] {"3", "1", "2", "0", "1.5"}));
    comboBox_1.setToolTipText("0");
    comboBox_1.setBounds(181, 175, 75, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_1);

    JComboBox comboBox_2 = new JComboBox();
    comboBox_2.setModel(new DefaultComboBoxModel(new String[] {"3", "1", "2", "0", "1.5"}));
    comboBox_2.setToolTipText("0");
    comboBox_2.setBounds(181, 210, 75, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_2);

    JComboBox comboBox_3 = new JComboBox();
    comboBox_3.setModel(new DefaultComboBoxModel(new String[] {"3", "1", "2", "0", "1.5"}));
    comboBox_3.setToolTipText("0");
    comboBox_3.setBounds(181, 245, 75, 29);
    frmCgpaCalculator.getContentPane().add(comboBox_3);

    JLabel lblGrade_1 = new JLabel("Grade");
    lblGrade_1.setFont(new Font("Tahoma", Font.PLAIN, 15));
    lblGrade_1.setBounds(311, 99, 56, 16);
    frmCgpaCalculator.getContentPane().add(lblGrade_1);

    JButton btnNewButton = new JButton("Add Course");
    btnNewButton.setFont(new Font("Tahoma", Font.PLAIN, 15));
    btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            JOptionPane.showMessageDialog(frmCgpaCalculator.getComponent(0), "Hello World");
        }
    });

    JLabel lblCgpa = new JLabel("CGPA:");
    lblCgpa.setFont(new Font("Tahoma", Font.BOLD, 17));
    lblCgpa.setBounds(386, 13, 56, 16);
    frmCgpaCalculator.getContentPane().add(lblCgpa);

    JLabel label = new JLabel("0.0");
    label.setFont(new Font("Tahoma", Font.PLAIN, 17));
    label.setBounds(454, 13, 56, 16);
    frmCgpaCalculator.getContentPane().add(label);

    btnNewButton.setBounds(12, 299, 124, 25);
    frmCgpaCalculator.getContentPane().add(btnNewButton);

    JButton btnCalculate = new JButton("Calculate");
    btnCalculate.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            label.setText("3.2");
        }
    });
    btnCalculate.setFont(new Font("Tahoma", Font.PLAIN, 15));
    btnCalculate.setBounds(270, 300, 97, 25);
    frmCgpaCalculator.getContentPane().add(btnCalculate);
}

更新:

如果不需要,我添加了一个按钮来删除一行。如何连接到数组列表索引?

JButton btnX = new JButton("");
    btnX.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {

        }
    });
    btnX.setIcon(new ImageIcon(CgpaCalculator.class.getResource("/com/sun/javafx/scene/control/skin/modena/dialog-error.png")));
    btnX.setBackground(Color.RED);
    btnX.setForeground(Color.WHITE);
    btnX.setBounds(428, rowY, 30, 30);
    frmCgpaCalculator.getContentPane().add(btnX);

【问题讨论】:

    标签: java swing user-interface awt


    【解决方案1】:

    我将创建一个对象来保存每一行的 3 个元素,称为 CourseRow。并将这些CourseRow 对象存储在List 中。

    下面是这样重写的代码:

    public class Test {
    
        public static void main(String[] args) {
            CgpaCalculator window = new CgpaCalculator();
            window.getFrmCgpaCalculator().setVisible(true);
        }
    }
    
    class CgpaCalculator {
        private JFrame frmCgpaCalculator;
    
        private JPanel coursesPanel;
        private JScrollPane scrollPane;
    
        // Define some constants
        private int ROWS_Y_OFFEST = 0;
        private int ROW_HEIGHT = 35;
        private String[] credits = new String[] {"3", "1", "2", "0", "1.5"};
        private String[] grades = new String[] {"A", "A-", "B+", "B", "B", "B-", "C+", "C", "D+", "D", "F"};
    
        // This list holds all the row elements
        private List<CourseRow> courseRows = new ArrayList<>();
    
        // These 2 need to be class variable because we update them in the refresh method
        private JButton btnNewButton, btnCalculate;
    
        public CgpaCalculator() {
            initializeElements();
            refresh();
        }
    
        private void initializeElements() {
            frmCgpaCalculator = new JFrame();
            frmCgpaCalculator.getContentPane().setFont(new Font("Tahoma", Font.PLAIN, 17));
            frmCgpaCalculator.setTitle("CGPA Calculator");
            frmCgpaCalculator.setBounds(100, 100, 540, 683);
            frmCgpaCalculator.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            frmCgpaCalculator.getContentPane().setLayout(null);
    
            // CGPA RESULT
            JLabel lblCgpa = new JLabel("CGPA:");
            lblCgpa.setFont(new Font("Tahoma", Font.BOLD, 17));
            lblCgpa.setBounds(386, 13, 56, 16);
            frmCgpaCalculator.getContentPane().add(lblCgpa);
    
            JLabel label = new JLabel("0.0");
            label.setFont(new Font("Tahoma", Font.PLAIN, 17));
            label.setBounds(454, 13, 56, 16);
            frmCgpaCalculator.getContentPane().add(label);
    
            // HEADERS
            JLabel lblCourse = new JLabel("Course");
            lblCourse.setFont(new Font("Tahoma", Font.PLAIN, 15));
            lblCourse.setBounds(47, 99, 56, 16);
            frmCgpaCalculator.getContentPane().add(lblCourse);
    
            JLabel lblCredits = new JLabel("Credits");
            lblCredits.setFont(new Font("Tahoma", Font.PLAIN, 15));
            lblCredits.setBounds(192, 99, 56, 16);
            frmCgpaCalculator.getContentPane().add(lblCredits);
    
            JLabel lblGrade = new JLabel("Grade");
            lblGrade.setFont(new Font("Tahoma", Font.PLAIN, 15));
            lblGrade.setBounds(311, 99, 56, 16);
            frmCgpaCalculator.getContentPane().add(lblGrade);
    
    
            // Courses panel and scroll pane
            coursesPanel = new JPanel();
            coursesPanel.setLayout(null);
    
            scrollPane = new JScrollPane(coursesPanel);
            scrollPane.setBounds(40, 150, 480, 300);
            scrollPane.setPreferredSize(new Dimension(500, 300));
            scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            frmCgpaCalculator.getContentPane().add(scrollPane);
    
            // BUTTONS
            btnNewButton = new JButton("Add Course");
            btnNewButton.setFont(new Font("Tahoma", Font.PLAIN, 15));
            btnNewButton.setBounds(12, 500, 124, 25);
            btnNewButton.addActionListener(new ActionListener() {
                   @Override
                   public void actionPerformed(ActionEvent arg0) {
                       addCourseRow();
                   }
               }
            );
            frmCgpaCalculator.getContentPane().add(btnNewButton);
    
            btnCalculate = new JButton("Calculate");
            btnCalculate.setFont(new Font("Tahoma", Font.PLAIN, 15));
            btnCalculate.setBounds(270, 500, 97, 25);
            btnCalculate.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    label.setText("3.2");
                }
            });
            frmCgpaCalculator.getContentPane().add(btnCalculate);
    
    
            // Add 3 default rows
            addCourseRow();
            addCourseRow();
            addCourseRow();
        }
    
        // This method refreshes the view.
        // It takes the list of course rows and reposition them depending on their index in the list
        // This enabled to easily handle deleting rows in the middle
        private void refresh() {
    
            // Reposition all course rows
            int rowY = ROWS_Y_OFFEST;
            CourseRow courseRow;
            for(int rowIndex=0; rowIndex<courseRows.size(); rowIndex++) {
                courseRow = courseRows.get(rowIndex);
                rowY = ROWS_Y_OFFEST + rowIndex * ROW_HEIGHT;
    
                courseRow.getNameJTextField().setBounds(12, rowY, 126, 29);
                courseRow.getCreditsJComboBox().setBounds(181, rowY, 75, 29);
                courseRow.getGradeJComboBox().setBounds(297, rowY, 70, 29);
                courseRow.getDeleteJButton().setBounds(428, rowY, 30, 30);
            }
    
            // resize the course panel so the scroll pane knows if it needs to add the scroll bar
            // you need to use the setPreferredSize method
            coursesPanel.setPreferredSize(new Dimension(450, rowY + ROW_HEIGHT));
    
            // repaint the scroll pane
            scrollPane.invalidate();
            scrollPane.validate();
            scrollPane.repaint();
        }
    
        private void addCourseRow() {
            // Calculate the Y coordinate of the row
            long rowId = System.currentTimeMillis();
    
            // Create the 3 elements
            JTextField nameJTextField = new JTextField();
            nameJTextField.setColumns(10);
            coursesPanel.add(nameJTextField);
    
            JComboBox creditsJComboBox = new JComboBox();
            creditsJComboBox.setToolTipText("0");
            creditsJComboBox.setModel(new DefaultComboBoxModel(credits));
            coursesPanel.add(creditsJComboBox);
    
            JComboBox gradeJComboBox = new JComboBox();
            gradeJComboBox.setModel(new DefaultComboBoxModel(grades));
            coursesPanel.add(gradeJComboBox);
    
            JButton btnX = new JButton("");
            btnX.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    removeCourse(rowId);
                }
            });
            btnX.setIcon(new ImageIcon(CgpaCalculator.class.getResource("/com/sun/javafx/scene/control/skin/modena/dialog-error.png")));
            btnX.setBackground(Color.RED);
            btnX.setForeground(Color.WHITE);
            coursesPanel.add(btnX);
    
            // Add the row to the list
            CourseRow courseRow = new CourseRow();
            courseRow.setId(rowId);
            courseRow.setNameJTextField(nameJTextField);
            courseRow.setCreditsJComboBox(creditsJComboBox);
            courseRow.setGradeJComboBox(gradeJComboBox);
            courseRow.setDeleteJButton(btnX);
            courseRows.add(courseRow);
    
            refresh();
        }
    
        private void removeCourse(long rowId) {
            // find the course row by id
            Optional<CourseRow> rowOption = courseRows.stream().filter(r -> r.getId() == rowId).findFirst();
            if(rowOption.isPresent()) {
                CourseRow row = rowOption.get();
                // remove elements of this row from the JFrame
                coursesPanel.remove(row.getNameJTextField());
                coursesPanel.remove(row.getCreditsJComboBox());
                coursesPanel.remove(row.getGradeJComboBox());
                coursesPanel.remove(row.getDeleteJButton());
    
                // remove row from the list
                courseRows.remove(row);
            } else {
                System.out.println("Could not find row with id "+rowId);
            }
    
            refresh();
        }
    
    
    
        public JFrame getFrmCgpaCalculator() {
            return frmCgpaCalculator;
        }
    }
    
    class CourseRow {
        private long id;
        private JTextField nameJTextField;
        private JComboBox creditsJComboBox;
        private JComboBox gradeJComboBox;
        private JButton deleteJButton;
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public JTextField getNameJTextField() {
            return nameJTextField;
        }
    
        public void setNameJTextField(JTextField nameJTextField) {
            this.nameJTextField = nameJTextField;
        }
    
        public JComboBox getCreditsJComboBox() {
            return creditsJComboBox;
        }
    
        public void setCreditsJComboBox(JComboBox creditsJComboBox) {
            this.creditsJComboBox = creditsJComboBox;
        }
    
        public JComboBox getGradeJComboBox() {
            return gradeJComboBox;
        }
    
        public void setGradeJComboBox(JComboBox gradeJComboBox) {
            this.gradeJComboBox = gradeJComboBox;
        }
    
        public JButton getDeleteJButton() {
            return deleteJButton;
        }
    
        public void setDeleteJButton(JButton deleteJButton) {
            this.deleteJButton = deleteJButton;
        }
    }
    

    【讨论】:

    • 非常感谢,按我的要求完美运行。我希望 GUI 像 HTML 一样简单 :(
    • 也试过了,没用 label.setText(courseRows.get(0).getNameJTextField());
    • @Tahmid 欢迎 :) 玩一下,你会发现它并不难。
    • 我已经编辑了帖子,请您看看好吗?我想为每一行添加一个关闭按钮。
    • @Tahmid 我做了一些调整,现在有一个处理所有组件定位的refresh 方法。现在它都集中在那里,添加和删除行要容易得多。看看,应该可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    相关资源
    最近更新 更多