我有2个JLists,其中我只想选择一个项目。我只使用复制错误所需的代码创建了一个单独的程序: 主类:
public class Main {
public static void main(String[] args) {
new Staff("John", "D", 123456);
new Staff("Bob", "X", 123455);
Staff.lookup("John","D").setActive(true);
Staff.lookup("Bob","X").setActive(true);
new Staff("Jerry","Smith",384938);
new Staff("Bob","Hope",834802);
new InstructorGUI(1);
}
}
员工班级:
import java.util.ArrayList;
import java.util.List;
public class Staff{
private String fName;
private String lName;
private int emtID;
public static List<Staff> staffIndex = new ArrayList<>();
public static ArrayList<Staff> activeStaffIndex = new ArrayList<>();
Staff(String fName, String lName, int NJEMS) {
this.fName = fName;
this.lName = lName;
staffIndex.add(this);
emtID = NJEMS;
}
//Getters
public int getEmtID() {
return emtID;
}
public String getFirstName() {return fName; }
public String getLastName() {return lName; }
@Override
public String toString() {
return String.format("%s, %s", lName, fName);
}
//Lookups
public static Staff lookup(String fName, String lName) {
for (Staff s : staffIndex) {
if (s.getFirstName().equalsIgnoreCase(fName) && s.getLastName().equalsIgnoreCase(lName)) {
return s;
}
}
return null;
}
//Setters
public void setEmtID(int NJEMS) {
emtID = NJEMS;
}
public void setFirstName(String s) {
fName = s;
}
public void setLastName(String s) {
lName = s;
}
//Removers
public static void removeStaff(Staff s) {
staffIndex.remove(s);
activeStaffIndex.remove(s);
}
//Utilities
public boolean isActive() {
if(activeStaffIndex.contains(this)) {
return true;
} else {
return false;
}
}
public void setActive(Boolean b) {
if (b) {
if (!activeStaffIndex.contains(this)) {
activeStaffIndex.add(this);
}
} else {
if (activeStaffIndex.contains(this)) {
activeStaffIndex.remove(this);
}
}
}
}
InstructorGUI类:
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashSet;
public class InstructorGUI extends JFrame {
private static HashSet<InstructorGUI> instructorGUIIndex = new HashSet<>();
private int identifier;
private JList<Object> listSelected, selectedInstructors, unSelectedInstructors;
public InstructorGUI(int id) {
super("Instructor Editor");
setSize(550, 250);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
identifier = id;
boolean b = false;
for (InstructorGUI i : instructorGUIIndex) {
if (i.getIdentifier() == 1) {
b = true;
}
}
if (b) {
InstructorGUI.lookup(1).dispose();
instructorGUIIndex.remove(InstructorGUI.lookup(1));
}
instructorGUIIndex.add(this);
JPanel container = new JPanel();
JPanel middle = new JPanel();
JPanel inputPanel = new JPanel();
JPanel topButtons = new JPanel();
JPanel left = new JPanel();
JPanel centerButtons = new JPanel();
JPanel right = new JPanel();
JPanel footer = new JPanel();
container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS));
middle.setLayout(new BoxLayout(middle, BoxLayout.X_AXIS));
inputPanel.setLayout(new FlowLayout());
topButtons.setLayout(new FlowLayout());
left.setLayout(new FlowLayout());
centerButtons.setLayout(new BoxLayout(centerButtons, BoxLayout.Y_AXIS));
right.setLayout(new FlowLayout());
footer.setLayout(new FlowLayout());
JLabel lNameLabel = new JLabel("Last");
JLabel fNameLabel = new JLabel("First");
JLabel emsIdLabel = new JLabel("EMS ID");
JTextField lNameField = new JTextField(10);
JTextField fNameField = new JTextField(10);
JTextField emsIdField = new JTextField(10);
selectedInstructors = new JList<>();
unSelectedInstructors = new JList<>();
JButton addInstructor = new JButton("Add");
JButton editInstructor = new JButton("Edit");
JButton removeInstructor = new JButton("Remove");
JButton selectInstructor = new JButton("<-");
JButton unSelectInstructor = new JButton("->");
JButton selectAllInstructors = new JButton("<<--");
JButton unSelectAllInstructors = new JButton("-->>");
inputPanel.add(lNameLabel);
inputPanel.add(lNameField);
inputPanel.add(fNameLabel);
inputPanel.add(fNameField);
inputPanel.add(emsIdLabel);
inputPanel.add(emsIdField);
topButtons.add(addInstructor);
topButtons.add(editInstructor);
topButtons.add(removeInstructor);
left.add(selectedInstructors);
centerButtons.add(selectAllInstructors);
centerButtons.add(selectInstructor);
centerButtons.add(unSelectInstructor);
centerButtons.add(unSelectAllInstructors);
right.add(unSelectedInstructors);
footer.add(new JLabel(""));
JScrollPane x = new JScrollPane(selectedInstructors);
JScrollPane y = new JScrollPane(unSelectedInstructors);
x.setPreferredSize(new Dimension(100, 200));
y.setPreferredSize(new Dimension(100, 200));
middle.add(new JLabel(""));
middle.add(x);
middle.add(centerButtons);
middle.add(y);
middle.add(new JLabel(""));
container.add(inputPanel);
container.add(topButtons);
container.add(middle);
container.add(footer);
update();
selectedInstructors.addListSelectionListener(e -> {
unSelectedInstructors.clearSelection();
if(selectedInstructors.getSelectedValue() != null) {
Staff s = Staff.lookup(selectedInstructors.getSelectedValue().toString().split(", ")[1], selectedInstructors.getSelectedValue().toString().split(", ")[0]);
lNameField.setText(s.getLastName());
fNameField.setText(s.getFirstName());
emsIdField.setText(String.format("%s", s.getEmtID()));
listSelected = selectedInstructors;
}
});
unSelectedInstructors.addListSelectionListener(e -> {
selectedInstructors.clearSelection();
if (unSelectedInstructors.getSelectedValue() != null) {
Staff s = Staff.lookup(unSelectedInstructors.getSelectedValue().toString().split(", ")[1], unSelectedInstructors.getSelectedValue().toString().split(", ")[0]);
lNameField.setText(s.getLastName());
fNameField.setText(s.getFirstName());
emsIdField.setText(String.format("%s", s.getEmtID()));
listSelected = unSelectedInstructors;
}
});
setContentPane(container);
setVisible(true);
addInstructor.addActionListener(e -> {
if(lNameField.getText().equalsIgnoreCase("") || fNameField.getText().equalsIgnoreCase("") || emsIdField.getText().equalsIgnoreCase("")) {
return;
}
if(Integer.parseInt(emsIdField.getText()) < 300000 || Integer.parseInt(emsIdField.getText()) > 900000) {
JOptionPane.showMessageDialog(null,"Please choose an EMS ID between 300000 and 900000.");
return;
}
for(Staff s : Staff.staffIndex) {
if(Integer.parseInt(emsIdField.getText()) == s.getEmtID()) {
JOptionPane.showMessageDialog(null, "EMS ID already taken.");
return;
}
}
new Staff(fNameField.getText(),lNameField.getText(),Integer.parseInt(emsIdField.getText()));
update();
});
editInstructor.addActionListener(e -> {
if(lNameField.getText().equalsIgnoreCase("") || fNameField.getText().equalsIgnoreCase("") || emsIdField.getText().equalsIgnoreCase("")) {
return;
}
if(Integer.parseInt(emsIdField.getText()) < 300000 || Integer.parseInt(emsIdField.getText()) > 900000) {
JOptionPane.showMessageDialog(null,"Please choose an EMS ID between 300000 and 900000.");
return;
}
for(Staff s : Staff.staffIndex) {
if(Integer.parseInt(emsIdField.getText()) == s.getEmtID()) {
JOptionPane.showMessageDialog(null, "EMS ID already taken.");
return;
}
}
Staff s = Staff.lookup(listSelected.getSelectedValue().toString().split(", ")[1],listSelected.getSelectedValue().toString().split(", ")[0]);
if(!s.getFirstName().equalsIgnoreCase(fNameField.getText()) || !s.getLastName().equalsIgnoreCase(lNameField.getText()) || s.getEmtID() != Integer.parseInt(emsIdField.getText())) {
s.setFirstName(fNameField.getText());
s.setLastName(lNameField.getText());
s.setEmtID(Integer.parseInt(emsIdField.getText()));
update();
}
});
removeInstructor.addActionListener(e -> {
if(listSelected.getSelectedValue() != null) {
Staff s = Staff.lookup(listSelected.getSelectedValue().toString().split(", ")[1],listSelected.getSelectedValue().toString().split(", ")[0]);
Staff.removeStaff(s);
update();
}
});
selectInstructor.addActionListener(e -> {
if(unSelectedInstructors.getSelectedValue() != null) {
Staff s = Staff.lookup(unSelectedInstructors.getSelectedValue().toString().split(", ")[1], unSelectedInstructors.getSelectedValue().toString().split(", ")[0]);
s.setActive(true);
update();
}
});
unSelectInstructor.addActionListener(e -> {
if(selectedInstructors.getSelectedValue() != null) {
Staff s = Staff.lookup(selectedInstructors.getSelectedValue().toString().split(", ")[1], selectedInstructors.getSelectedValue().toString().split(", ")[0]);
s.setActive(false);
update();
}
});
selectAllInstructors.addActionListener(e -> {
for(Staff s : Staff.staffIndex) {
s.setActive(true);
}
update();
});
unSelectAllInstructors.addActionListener(e -> {
for(Staff s : Staff.staffIndex) {
s.setActive(false);
}
update();
});
}
public int getIdentifier() {
return identifier;
}
public static InstructorGUI lookup(int id) {
for (InstructorGUI i : instructorGUIIndex) {
if (i.getIdentifier() == id) {
return i;
}
}
return null;
}
public void update() {
ArrayList<Staff> selected = new ArrayList<>();
ArrayList<Staff> notSelected = new ArrayList<>();
for (Staff s : Staff.staffIndex) {
if (s.isActive()) {
selected.add(s);
} else {
notSelected.add(s);
}
}
selectedInstructors.removeAll();
unSelectedInstructors.removeAll();
selectedInstructors.setListData(selected.toArray());
unSelectedInstructors.setListData(notSelected.toArray());
}
}
然而,我注意到,有时当我在列表之间切换而不是选择项目时,选项周围会出现一个蓝色框。我发生这种情况时试图调用getSelectionIndex(),它返回-1。如何在每次单击某个项目时选择它?
答案 0 :(得分:2)
您的问题在于ListSelectionListener。首先,让我们创建一个更好,更简单的MCVE,将代码简化为仅重现问题所需的基本要素:
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@SuppressWarnings("serial")
public class Main2 extends JPanel {
private JList<String> list1 = new JList<>(new String[] { "one", "two", "three" });
private JList<String> list2 = new JList<>(new String[] { "hello", "goodbye", "yes" });
public Main2() {
list1.setName("list 1");
list2.setName("list 2");
list1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list1.addListSelectionListener(new MySelectionListener(list2));
list2.addListSelectionListener(new MySelectionListener(list1));
setLayout(new GridLayout(1, 0));
add(new JScrollPane(list1));
add(new JScrollPane(list2));
}
private class MySelectionListener implements ListSelectionListener {
private JList<String> otherList;
public MySelectionListener(JList<String> otherList) {
this.otherList = otherList;
}
@Override
public void valueChanged(ListSelectionEvent e) {
otherList.clearSelection();
}
}
private static void createAndShowGui() {
Main2 mainPanel = new Main2();
JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
运行此选项,您将看到问题再现 - 新选择的选项未正确选择。另外,如果你注释掉otherList.clearSelection();
这一行,你会发现新选择的列表会显示新的选择,很好,所以这条线因为弄乱了你想要的行为而出错。
这可以通过限制何时仅在调整所选值时清除其他列表来修复:
@Override
public void valueChanged(ListSelectionEvent e) {
// otherList.clearSelection();
if (e.getValueIsAdjusting()) {
otherList.clearSelection();
}
}
为什么这样做?老实说,我不能肯定地说,但我知道这将清除其他列表的选择之前正在选择新列表的项目,因此它可以正常工作。此外,您只想在值未调整时提取所选值,因此需要if / else块,如下所示:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@SuppressWarnings("serial")
public class Main2 extends JPanel {
private JList<String> list1 = new JList<>(new String[] { "one", "two", "three" });
private JList<String> list2 = new JList<>(new String[] { "hello", "goodbye", "yes" });
private JTextField selectedItemTxtFld = new JTextField(10);
public Main2() {
list1.setName("list 1");
list2.setName("list 2");
list1.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list2.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list1.addListSelectionListener(new MySelectionListener(list2));
list2.addListSelectionListener(new MySelectionListener(list1));
JPanel listPanel = new JPanel(new GridLayout(1, 0));
listPanel.add(new JScrollPane(list1));
listPanel.add(new JScrollPane(list2));
JPanel topPanel = new JPanel();
topPanel.add(new JLabel("Selection:"));
topPanel.add(selectedItemTxtFld);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
add(listPanel, BorderLayout.CENTER);
}
private class MySelectionListener implements ListSelectionListener {
private JList<String> otherList;
public MySelectionListener(JList<String> otherList) {
this.otherList = otherList;
}
@Override
public void valueChanged(ListSelectionEvent e) {
// otherList.clearSelection();
if (e.getValueIsAdjusting()) {
otherList.clearSelection();
} else {
JList<String> thisList = (JList<String>) e.getSource();
if (!thisList.isSelectionEmpty()) {
String selectedText = thisList.getSelectedValue().toString();
selectedItemTxtFld.setText(selectedText);
}
}
}
}
private static void createAndShowGui() {
Main2 mainPanel = new Main2();
JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}