我正在再次掌握Java并与Swing一起玩。目前正在尝试了解JList。
在JList中选择项目时,我启用了一个按钮(“删除”按钮)。如果没有选择,则应禁用该按钮(如果未选择该项,则无法删除该项,如果您没有项目索引,则JVM会呕吐)。
通过JTextField默认操作(输入)添加列表项时,按钮启用但JList中没有选择。启用按钮的代码甚至无法运行。这是怎么回事?也许我在某个地方错过了一个听众?
所有听众都在主要课堂上,但对其他人来说似乎不是问题。我看不到类实例化两次,所以不是这样。任何想法都会很棒?
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class GUI extends JFrame implements Runnable, ActionListener, DocumentListener, ListDataListener, ListSelectionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
//declare and instantiate interface components
DefaultListModel<String> lm=new DefaultListModel<String>();
JList<String> jl=new JList<String>(lm);
JTextField jt=new JTextField(50);
JButton b_add=new JButton("Add");
JButton b_del=new JButton("Remove");
@Override
public void run() {
//FROM RUNNABLE INTERFACE
//set GUI (JFrame) attributes
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationByPlatform(true);
setName("List of Lists");
setSize(1280, 500);
setLayout(new FlowLayout());
//set component attributes
jl.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); //single selection list
jt.getDocument().addDocumentListener(this);
//other interface components
JScrollPane sp=new JScrollPane(jl);
JButton b_exit=new JButton("Exit");
//other component attributes
sp.setSize(500, 500);
b_add.setEnabled(false);
b_del.setEnabled(false);
//set component listeners
b_add.addActionListener(this);
b_del.addActionListener(this);
b_exit.addActionListener(this);
jt.setActionCommand("TXT");
jt.addActionListener(this);
lm.addListDataListener(this);
jl.addListSelectionListener(this);
//add GUI components
add(jt);
add(sp);
add(b_add);
add(b_del);
add(b_exit);
//set GUI visible
setVisible(true);
}
//FROM ACTIONLISTENER INTERFACE
@Override
public void actionPerformed(ActionEvent ae) {
//default action on text field (enter key)
if (ae.getActionCommand()=="TXT") {
lm.addElement(jt.getText());
jt.setText(null);
} else {
//actions from buttons
switch (ae.getActionCommand()) {
//add button
case "Add":
lm.addElement(jt.getText());
jt.setText(null);
break;
//remove button
case "Remove":
if (jl.getSelectedIndex()>=0) {
lm.remove(jl.getSelectedIndex());
}
break;
//exit button
case "Exit":
setVisible(false);
dispose();
break;
//just in case
default:
break;
}
}
}
//FROM DOCUMENTEVENTLISTENER INTERFACE
@Override
public void changedUpdate(DocumentEvent de) {
b_add.setEnabled(de.getDocument().getLength()>0);
}
@Override
public void insertUpdate(DocumentEvent de) {
b_add.setEnabled(de.getDocument().getLength()>0);
}
@Override
public void removeUpdate(DocumentEvent de) {
b_add.setEnabled(de.getDocument().getLength()>0);
}
//FROM LISTDATALISTENER INTERFACE
@Override
public void contentsChanged(ListDataEvent ld) {
b_del.setEnabled(lm.getSize()>0);
}
@Override
public void intervalAdded(ListDataEvent ld) {
b_del.setEnabled(lm.getSize()>0);
}
@Override
public void intervalRemoved(ListDataEvent ld) {
b_del.setEnabled(lm.getSize()>0);
}
//FROM LISTSELECTIONLISTENER INTERFACE
@Override
public void valueChanged(ListSelectionEvent ls) {
b_del.setEnabled(jl.getSelectedIndex()>=0);
}
}
应该发生的是,“删除”按钮只应在JList中的项突出显示(选中)时启用。
应该发生的是,“删除”按钮只应在JList中的项突出显示(选中)时启用。
那么你的代码中有太多的监听器。
不需要DocumentListener。文本字段中的数据是否更改无关紧要。将文本字段中的数据添加到JList时,选择不会自动更改。
不需要ListDataListener。同样,您不关心数据是否发生变化。
唯一与此要求相关的听众是ListSelectionListener
。当选择发生更改时,此侦听器将触发事件。然后在侦听器代码中,根据列表中的选择启用/禁用按钮。
监听器中的基本代码可能是:
int index = list.getSelectedIndex();
button.setEnabled( index = -1 ? false : true );
阅读How to Write a ListSelectionListener上的Swing教程中的部分以获取更多信息和工作示例。
只需在Add case中添加b_del.setEnabled(false);
即可。
//add button
case "Add":
lm.addElement(jt.getText());
jt.setText(null);
b_del.setEnabled(false);
break;
另外,我建议使用system.exit(0)
而不是dispose ()
。仅出于内存原因(显然,这取决于您的需求:))。