简体   繁体   中英

How do I create JLabel and JRadioButton depending upon user input?

I am trying to make a column of components that holds a JLabel and two JRadioButtons with the label text depending on input from the user. It would look something like this:

JLabel和JRadioButtons的组件

for(int i=0;i<col;i++){
    secondInterfaceLayout.setHorizontalGroup(
    secondInterfaceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(secondInterfaceLayout.createSequentialGroup()
        .addContainerGap()
        .addComponent(labels[i])
        .addGap(180, 180, 180)
        .addGroup(secondInterfaceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(benefitLabel, PREFERRED_SIZE, 42, PREFERRED_SIZE)
            .addGroup(secondInterfaceLayout.createSequentialGroup()
                .addGap(10, 10, 10)
                .addComponent(benefitButton[i])))
        .addGap(68, 68, 68)
        .addGroup(secondInterfaceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(lossButton[i])
            .addComponent(lossLabel))
        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);

   secondInterfaceLayout.setVerticalGroup(
    secondInterfaceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    .addGroup(secondInterfaceLayout.createSequentialGroup()
        .addGap(14, 14, 14)
        .addGroup(secondInterfaceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(benefitLabel)
            .addComponent(lossLabel))
        .addPreferredGap(UNRELATED)
        .addGroup(secondInterfaceLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
            .addComponent(lossButton[i], TRAILING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE)
            .addComponent(labels[i])
            .addComponent(benefitButton[i], TRAILING, DEFAULT_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
        .addContainerGap(DEFAULT_SIZE, Short.MAX_VALUE))
);

So riffing on what Andrew Thompson said, you could display and change your criteria within a JTable since you appear to be wanting to create and display tabular data, data that can change as the program is running and under control by the user. Doing this though presents certain challenges since benefit vs loss appears to be complementary properties, meaning if one is true, the other must be false, and this would most easily be represented by a single boolean, but then how to wire the JTable and its model so that it displays both properties if a row of data contains a single boolean, and how to allow the user to change these properties, and then display the change in both columns?

So before creating a table model, I first created a class, MyCriterion, to represent a single row of data. It has two fields, a name String and a beneficial boolean. Again if beneficial is true, then the JTable's "Benefit" column should display a check mark and the "Loss" column should be empty, and visa versa. The class:

public class MyCriterion {
    private String name;
    private boolean beneficial;

    public MyCriterion(String name) {
        this(name, false);
    }

    public MyCriterion(String name, boolean beneficial) {
        this.name = name;
        this.beneficial = beneficial;
    }

    public String getName() {
        return name;
    }

    public boolean isBeneficial() {
        return beneficial;
    }

    public void setBeneficial(boolean beneficial) {
        this.beneficial = beneficial;
    }

    @Override
    public String toString() {
        return "MyCriterion [name=" + name + ", beneficial=" + beneficial + "]";
    }

}

Next, the table model, since it's much easier to extend DefaultTableModel than it is to extend AbstractTableModel, that's what I decided to do, but again, giving it 3 columns, the last two dependent on the state of a single boolan, the beneficial field of MyCriterion. I "hard-coded" the column headers:

public static final String[] COLUMN_NAMES = { "Type of Criteria", "Benefit", "Loss" };

and passed them into the super's constructor that takes an array for the headers and an int for the number of rows, and that initial row count is of course 0 :

public CriteriaTableModel() {
    super(COLUMN_NAMES, 0);
}

The getColumnClass(int columnIndex) should return String.class if the columnIndex is 0, otherwise it will return a Boolean.class , and doing this will make the JTable display the last two column values as JCheckBoxes. This isn't quite as clean as displaying them as JRadioButtons, but it's simple and it works.

I gave the model a public void addCriterion(MyCriterion myCriterion) method to make it simple to add a row. It adds a MyCriterion value into the super's model into the 0th column:

public void addCriterion(MyCriterion myCriterion) {
    super.addRow(new MyCriterion[] {myCriterion});
}

This means that the actual "nucleus" of this table model, which is held by the super, is actually a model with one column, one that holds MyCriterion objects, and so I'll have to override the setValue(...) and getValueAt(...) methods to translate this single column of data into 3 columns of display:

@Override
public void setValueAt(Object aValue, int row, int column) {
    MyCriterion myCriterion = (MyCriterion) super.getValueAt(row, 0);
    boolean boolValue = (boolean) aValue;
    switch (column) {
    case 1:
        myCriterion.setBeneficial(boolValue);
        break;
    case 2:
        myCriterion.setBeneficial(!boolValue);

    default:
        break;
    }
    super.setValueAt(myCriterion, row, 0);
    fireTableRowsUpdated(row, row);
}  

@Override
public Object getValueAt(int row, int column) {
    MyCriterion myCriterion = (MyCriterion) super.getValueAt(row, 0);
    switch (column) {
    case 0:
        return myCriterion.getName();
    case 1:
        return myCriterion.isBeneficial();
    case 2:
        return !myCriterion.isBeneficial();

    default:
        String text = "Invalid column: " + column;
        throw new IllegalArgumentException(text);
    }
}

public MyCriterion getValueAt(int row) {
    return (MyCriterion) super.getValueAt(row, 0);
}

My whole table model class:

GUI的示例图像

import java.util.ArrayList;
import java.util.List;
import javax.swing.table.DefaultTableModel;

public @SuppressWarnings("serial")
class CriteriaTableModel extends DefaultTableModel {
    public static final String[] COLUMN_NAMES = { "Type of Criteria", "Benefit", "Loss" };

    public CriteriaTableModel() {
        super(COLUMN_NAMES, 0);
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
        case 0:
            return String.class;
        default:
            return Boolean.class;
        }
    }

    public void addCriterion(MyCriterion myCriterion) {
        super.addRow(new MyCriterion[] {myCriterion});
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        MyCriterion myCriterion = (MyCriterion) super.getValueAt(row, 0);
        boolean boolValue = (boolean) aValue;
        switch (column) {
        case 1:
            myCriterion.setBeneficial(boolValue);
            break;
        case 2:
            myCriterion.setBeneficial(!boolValue);

        default:
            break;
        }
        super.setValueAt(myCriterion, row, 0);
        fireTableRowsUpdated(row, row);
    }

    @Override
    public boolean isCellEditable(int row, int column) {
        return column > 0;
    }

    @Override
    public Object getValueAt(int row, int column) {
        MyCriterion myCriterion = (MyCriterion) super.getValueAt(row, 0);
        switch (column) {
        case 0:
            return myCriterion.getName();
        case 1:
            return myCriterion.isBeneficial();
        case 2:
            return !myCriterion.isBeneficial();

        default:
            String text = "Invalid column: " + column;
            throw new IllegalArgumentException(text);
        }
    }

    public MyCriterion getValueAt(int row) {
        return (MyCriterion) super.getValueAt(row, 0);
    }

    public List<MyCriterion> getCriteria() {
        List<MyCriterion> criteriaList = new ArrayList<>();
        for (int i = 0; i < getRowCount(); i++) {
            criteriaList.add(getValueAt(i));
        }
        return criteriaList;
    }

}

Finally the GUI to display this all, and to have buttons that allow addition and removal of rows from the JTable:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class CriteriaList extends JPanel {
    private CriteriaTableModel myModel = new CriteriaTableModel();
    private JTable criteriaTable = new JTable(myModel);
    private JTextField criterionNameField = new JTextField(10);
    private JCheckBox beneficialCB = new JCheckBox("Beneficial");

    public CriteriaList() {
        criteriaTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        myModel.addCriterion(new MyCriterion("Foo", true));
        myModel.addCriterion(new MyCriterion("Bar", false));

        JPanel bottomPanel = new JPanel();
        bottomPanel.add(new JLabel("Criterion:"));
        bottomPanel.add(criterionNameField);
        bottomPanel.add(beneficialCB);
        bottomPanel.add(new JButton(new AddCriterion("Add")));
        bottomPanel.add(new JButton(new RemoveCriterion("Remove")));
        bottomPanel.add(new JButton(new DisplayCriterion("Display")));

        setLayout(new BorderLayout());
        add(new JScrollPane(criteriaTable));
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    private class RemoveCriterion extends AbstractAction {
        public RemoveCriterion(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            int row = criteriaTable.getSelectedRow();
            if (row >= 0) {
                myModel.removeRow(row);
            }
        }
    }

    private class DisplayCriterion extends AbstractAction {
        public DisplayCriterion(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            for (MyCriterion criterion : myModel.getCriteria()) {
                System.out.println(criterion);
            }
        }
    }

    private class AddCriterion extends AbstractAction {
        public AddCriterion(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            String name = criterionNameField.getText();

            boolean beneficial = beneficialCB.isSelected();
            MyCriterion myCriterion = new MyCriterion(name, beneficial);
            myModel.addCriterion(myCriterion);

            criterionNameField.selectAll();
            criterionNameField.requestFocusInWindow();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui() {
        CriteriaList mainPanel = new CriteriaList();
        JFrame frame = new JFrame("Criteria List");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM