Java JSpinner dynamicali更新,如何删除元素?
我有一个JSpinner和一个喷丝头列表模型。我想做的是,一旦列表加载到模型中,JSpiner显示在一个框架中,就可以从微调器中删除元素。只需点击同一帧上的按钮即可完成此操作。单击操作的处理程序将删除微调器上当前选定的元素。 我当前的实现存在的问题是,当这个处理程序返回时,微调器中有一个IndexOutOfBoundsExeception(即当我从列表中删除最后一个元素时),这表明JSpinner没有得到很好的更新 我创建了一个新类ExtendedSpinner,它扩展了JSpinner,只是为了使用fireStateChanged。 这是为了在删除元素时更新JSpinner。它适用于删除列表中间的元素,但不适用于最后一个元素 我做错了什么?代码如下:Java JSpinner dynamicali更新,如何删除元素?,java,swing,jspinner,Java,Swing,Jspinner,我有一个JSpinner和一个喷丝头列表模型。我想做的是,一旦列表加载到模型中,JSpiner显示在一个框架中,就可以从微调器中删除元素。只需点击同一帧上的按钮即可完成此操作。单击操作的处理程序将删除微调器上当前选定的元素。 我当前的实现存在的问题是,当这个处理程序返回时,微调器中有一个IndexOutOfBoundsExeception(即当我从列表中删除最后一个元素时),这表明JSpinner没有得到很好的更新 我创建了一个新类ExtendedSpinner,它扩展了JSpinner,只是为
package image;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
import javax.swing.SpinnerModel;
public class ImageDealer2 {
protected JFrame selectCoverFrame;
protected JExtendedSpinner spinnerCovers;
protected JButton deleteCoverButton;
protected SpinnerListModel spinnerCoversM;
protected ArrayList<Object> stringList = new ArrayList<Object>();
public ImageDealer2() {
selectFrameInit();
}
public void selectFrameInit(){
selectCoverFrame = new JFrame("Select");
selectCoverFrame.setSize(new Dimension(500,100));
selectCoverFrame.getContentPane().setLayout(new BoxLayout(selectCoverFrame.getContentPane(),BoxLayout.Y_AXIS));
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.add("d");
spinnerCoversM = new SpinnerListModel(stringList);
spinnerCovers = new JExtendedSpinner(spinnerCoversM);
deleteCoverButton = new JButton("Delete current element");
DeleteCurrentCoverHandler deleteCurrentCoverHandler = new DeleteCurrentCoverHandler();
deleteCoverButton.addActionListener(deleteCurrentCoverHandler);
selectCoverFrame.getContentPane().add(spinnerCovers);
selectCoverFrame.getContentPane().add(deleteCoverButton);
selectCoverFrame.setVisible(true);
}
public class JExtendedSpinner extends JSpinner{
/**
*
*/
private static final long serialVersionUID = 6109392800971431371L;
public JExtendedSpinner() {
super();
// TODO Auto-generated constructor stub
}
public JExtendedSpinner(SpinnerModel model) {
super(model);
// TODO Auto-generated constructor stub
}
public void fireUpdate(){
this.fireStateChanged();
}
}
private class DeleteCurrentCoverHandler implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (stringList.size()>1){
stringList.remove(spinnerCovers.getValue());
spinnerCoversM.setList(stringList);
spinnerCovers.setModel(spinnerCoversM);
spinnerCovers.fireUpdate();
} else{
stringList.clear();
selectCoverFrame.dispose();
}
}
}
}
包装图像;
导入java.awt.Dimension;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.util.ArrayList;
导入javax.swing.BoxLayout;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JSpinner;
导入javax.swing.SpinnerListModel;
导入javax.swing.SpinnerModel;
公共类ImageDealer2{
保护JFrame selectCoverFrame;
受保护的Jettendedspinner喷丝头盖;
受保护的JButton deleteCoverButton;
保护喷丝头模型喷丝头;
受保护的ArrayList stringList=新的ArrayList();
公共ImageDealer2(){
选择frameinit();
}
public void selectFrameInit(){
selectCoverFrame=新JFrame(“选择”);
选择CoverFrame.setSize(新尺寸(500100));
选择CoverFrame.getContentPane().setLayout(新的BoxLayout(选择CoverFrame.getContentPane(),BoxLayout.Y_轴));
stringList.添加(“a”);
字符串列表。添加(“b”);
添加(“c”);
stringList.添加(“d”);
spinnerCoversM=新SpinnerListModel(stringList);
喷丝头罩=新的JExtendedSpinner(喷丝头罩SM);
deleteCoverButton=新JButton(“删除当前元素”);
DeleteCurrentCoverHandler DeleteCurrentCoverHandler=新的DeleteCurrentCoverHandler();
deleteCoverButton.addActionListener(deleteCurrentCoverHandler);
选择CoverFrame.getContentPane().add(喷丝头罩);
选择CoverFrame.getContentPane().add(删除CoverButton);
选择CoverFrame.setVisible(真);
}
公共类JExtendedSpinner扩展了JSpinner{
/**
*
*/
私有静态最终长serialVersionUID=610939280097143131L;
公共JExtendedSpinner(){
超级();
//TODO自动生成的构造函数存根
}
公共喷射器(喷丝头模型){
超级(模型);
//TODO自动生成的构造函数存根
}
public-void-firefupdate(){
this.fireStateChanged();
}
}
私有类DeleteCurrentCoverHandler实现ActionListener{
已执行的公共无效操作(操作事件e){
如果(stringList.size()>1){
stringList.remove(spinnerCovers.getValue());
喷丝头覆盖层设置列表(stringList);
喷丝头罩。setModel(喷丝头罩SM);
喷丝头罩。fireUpdate();
}否则{
stringList.clear();
选择CoverFrame.dispose();
}
}
}
}
我认为这太复杂了,不需要扩展JSpinner
启动程序时,请确保在创建JSpinner之前添加值:
//create the list
stringList.add("a");
stringList.add("b");
stringList.add("c");
stringList.add("d");
//make sure you set the model to the list
jSpinner.setModel(new javax.swing.SpinnerListModel(stringList));
您应该这样创建事件(在执行其他操作之前执行此操作):
stateChanged(evt)
方法应如下所示:
//Get selected item/object
Object selected = jSpinner.getValue();
//Remove selected item/object
stringList.remove(selected);
你很接近。在列表中添加和删除元素时确实需要触发事件,但这是模型的责任,而不是微调器的责任。因此,您必须实现自己的模型。
另一个问题是当列表被清空时,微调器将无法显示任何内容,这可能就是您获得异常的原因。
因此,您必须决定当微调器变空时要做什么 例如,您希望微调器在为空时禁用,在不为空时返回启用状态。
正如我之前告诉过您的,您必须实现
SpinnerListModel
,以便手动触发用于添加和删除的事件。但是现在您还希望根据模型禁用和启用微调器。因此,您可以实现该模型以获取微调器的参考…下面是示例代码:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
public class ImageDealer2 {
public static class RemoveSpinnerListModel extends SpinnerListModel {
private static final String VALUE_OF_EMPTY_LIST = ""; //This value indicates the spinner is empty.
protected JSpinner spin; //The spinner which this model referes to.
private boolean empty; //indicates if the list spinner is empty.
//The spinner is empty if it contains only the VALUE_OF_EMPTY_LIST value.
public RemoveSpinnerListModel() {
super(new ArrayList(Arrays.asList(VALUE_OF_EMPTY_LIST))); //We initialize to an "empty" read-write list.
empty = true; //The spinner does not contain any valid value.
}
public void setSpinner(final JSpinner spin) {
this.spin = Objects.requireNonNull(spin); //Just a null check plus assignment.
//We ensure the list has at least one element in it (the VALUE_OF_EMPTY_LIST):
if (getList().isEmpty())
((List)getList()).add(VALUE_OF_EMPTY_LIST);
//The spinner is empty if and only if the list contains only the VALUE_OF_EMPTY_LIST.
empty = getList().size() == 1 && getList().get(0).equals(VALUE_OF_EMPTY_LIST);
//We enable/disable the spinner accordingly:
spin.setEnabled(!empty);
if (empty) //If the spinner is empty of valid values:
spin.setValue(VALUE_OF_EMPTY_LIST); //then we add the VALUE_OF_EMPTY_LIST.
}
public void add(final Object value) {
if (empty) //If the spinner contains only the VALUE_OF_EMPTY_LIST, then:
getList().clear(); //Remove the VALUE_OF_EMPTY_LIST string.
((List)getList()).add(value); //Add the requested value.
if (spin != null) {
spin.setEnabled(true); //Enable the spinner for sure, because now it has at least one valid value.
spin.setValue(value);
}
empty = false; //The spinner is surely not empty.
fireStateChanged(); //Important step: updates the spinner via firing an event in the model.
}
public void remove(final Object value) {
if (!getList().isEmpty()) { //If there is something to remove.
getList().remove(value); //Remove the requested value.
if (getList().isEmpty()) //If now the list is empty, then we mark the spinner as empty:
markTheSpinnerAsEmpty();
else //Else the list still contains valid elements, so we mark the spinner as not-empty:
empty = false;
}
else //Else, the list is empty, so nothing to remove and the spinner must be marked as empty:
markTheSpinnerAsEmpty();
if (spin != null)
spin.setEnabled(!empty);
fireStateChanged(); //Important step: updates the spinner via firing an event in the model.
}
public void clear() {
getList().clear(); //Remove everything for sure.
markTheSpinnerAsEmpty();
}
private void markTheSpinnerAsEmpty() {
((List)getList()).add(VALUE_OF_EMPTY_LIST);
if (spin != null) {
spin.setValue(VALUE_OF_EMPTY_LIST); //Let's show the user that nothing is here.
spin.setEnabled(false);
}
empty = true;
}
}
protected JFrame selectCoverFrame;
protected JSpinner spinnerCovers;
protected JButton deleteCoverButton;
protected RemoveSpinnerListModel spinnerCoversM;
public ImageDealer2() {
selectFrameInit();
}
private void selectFrameInit() {
selectCoverFrame = new JFrame("Select");
selectCoverFrame.setSize(new Dimension(500, 100));
selectCoverFrame.getContentPane().setLayout(new BoxLayout(selectCoverFrame.getContentPane(), BoxLayout.Y_AXIS));
spinnerCoversM = new RemoveSpinnerListModel();
spinnerCoversM.add("a");
spinnerCoversM.add("b");
spinnerCoversM.add("c");
spinnerCoversM.add("d");
spinnerCovers = new JSpinner(spinnerCoversM);
spinnerCoversM.setSpinner(spinnerCovers); //DO NOT forget this step!
deleteCoverButton = new JButton("Delete current element");
DeleteCurrentCoverHandler deleteCurrentCoverHandler = new DeleteCurrentCoverHandler();
deleteCoverButton.addActionListener(deleteCurrentCoverHandler);
final JButton addButton = new JButton("Add an element");
AddANewCoverHandler addANewCoverHandler = new AddANewCoverHandler();
addButton.addActionListener(addANewCoverHandler);
final JPanel buttonPanel = new JPanel(); //FlowLayout.
buttonPanel.add(deleteCoverButton);
buttonPanel.add(addButton);
selectCoverFrame.getContentPane().add(spinnerCovers);
selectCoverFrame.getContentPane().add(buttonPanel);
selectCoverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //With this call, when you close the frame, then the application gets terminated.
selectCoverFrame.setLocationRelativeTo(null); //With this call, the frame gets to the center of the screen.
selectCoverFrame.setVisible(true);
}
private class DeleteCurrentCoverHandler implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
spinnerCoversM.remove(spinnerCovers.getValue());
}
}
private class AddANewCoverHandler implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
spinnerCoversM.add(JOptionPane.showInputDialog("Enter the new element string:"));
}
}
public static void main(final String[] args) {
new ImageDealer2();
}
}
如果要从微调器中添加或删除任何对象,则必须通过此模型进行操作。对于任何其他“只读”操作(例如
isEmpty()
和size()
),您可以调用模型的getList()
。可能这是一个比预期更大的解决方案,但它是可重用的。SpinnerListModel只保留了对构造函数中传递的列表的引用,因此只需从列表中删除元素并触发事件就足够了。无需再次调用
setList
和setModel
。这甚至可以解决你的问题,但我不确定。请注意,我并不真正希望有一个支持该模型的列表,但是如果不触发事件,您就无法更改该列表。我更喜欢一个能自己照顾自己的模型,并能自己启动活动。谢谢。我试着先去掉那两条线,但都没用。然后我尝试扩展SpinnerListModel,但结果相同。我缺少其他内容。该元素应通过按钮上的事件而不是微调器上的事件删除。这样,每次单击微调器时都会删除该元素。我也尝试过通过按钮处理程序中的事件激活布尔值,但这很复杂,因为需要以某种方式触发微调器事件。但是,如果在单击按钮后单击微调器,您也会遇到与我在第一个版本的代码中遇到的问题相同的问题。
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerListModel;
public class ImageDealer2 {
public static class RemoveSpinnerListModel extends SpinnerListModel {
private static final String VALUE_OF_EMPTY_LIST = ""; //This value indicates the spinner is empty.
protected JSpinner spin; //The spinner which this model referes to.
private boolean empty; //indicates if the list spinner is empty.
//The spinner is empty if it contains only the VALUE_OF_EMPTY_LIST value.
public RemoveSpinnerListModel() {
super(new ArrayList(Arrays.asList(VALUE_OF_EMPTY_LIST))); //We initialize to an "empty" read-write list.
empty = true; //The spinner does not contain any valid value.
}
public void setSpinner(final JSpinner spin) {
this.spin = Objects.requireNonNull(spin); //Just a null check plus assignment.
//We ensure the list has at least one element in it (the VALUE_OF_EMPTY_LIST):
if (getList().isEmpty())
((List)getList()).add(VALUE_OF_EMPTY_LIST);
//The spinner is empty if and only if the list contains only the VALUE_OF_EMPTY_LIST.
empty = getList().size() == 1 && getList().get(0).equals(VALUE_OF_EMPTY_LIST);
//We enable/disable the spinner accordingly:
spin.setEnabled(!empty);
if (empty) //If the spinner is empty of valid values:
spin.setValue(VALUE_OF_EMPTY_LIST); //then we add the VALUE_OF_EMPTY_LIST.
}
public void add(final Object value) {
if (empty) //If the spinner contains only the VALUE_OF_EMPTY_LIST, then:
getList().clear(); //Remove the VALUE_OF_EMPTY_LIST string.
((List)getList()).add(value); //Add the requested value.
if (spin != null) {
spin.setEnabled(true); //Enable the spinner for sure, because now it has at least one valid value.
spin.setValue(value);
}
empty = false; //The spinner is surely not empty.
fireStateChanged(); //Important step: updates the spinner via firing an event in the model.
}
public void remove(final Object value) {
if (!getList().isEmpty()) { //If there is something to remove.
getList().remove(value); //Remove the requested value.
if (getList().isEmpty()) //If now the list is empty, then we mark the spinner as empty:
markTheSpinnerAsEmpty();
else //Else the list still contains valid elements, so we mark the spinner as not-empty:
empty = false;
}
else //Else, the list is empty, so nothing to remove and the spinner must be marked as empty:
markTheSpinnerAsEmpty();
if (spin != null)
spin.setEnabled(!empty);
fireStateChanged(); //Important step: updates the spinner via firing an event in the model.
}
public void clear() {
getList().clear(); //Remove everything for sure.
markTheSpinnerAsEmpty();
}
private void markTheSpinnerAsEmpty() {
((List)getList()).add(VALUE_OF_EMPTY_LIST);
if (spin != null) {
spin.setValue(VALUE_OF_EMPTY_LIST); //Let's show the user that nothing is here.
spin.setEnabled(false);
}
empty = true;
}
}
protected JFrame selectCoverFrame;
protected JSpinner spinnerCovers;
protected JButton deleteCoverButton;
protected RemoveSpinnerListModel spinnerCoversM;
public ImageDealer2() {
selectFrameInit();
}
private void selectFrameInit() {
selectCoverFrame = new JFrame("Select");
selectCoverFrame.setSize(new Dimension(500, 100));
selectCoverFrame.getContentPane().setLayout(new BoxLayout(selectCoverFrame.getContentPane(), BoxLayout.Y_AXIS));
spinnerCoversM = new RemoveSpinnerListModel();
spinnerCoversM.add("a");
spinnerCoversM.add("b");
spinnerCoversM.add("c");
spinnerCoversM.add("d");
spinnerCovers = new JSpinner(spinnerCoversM);
spinnerCoversM.setSpinner(spinnerCovers); //DO NOT forget this step!
deleteCoverButton = new JButton("Delete current element");
DeleteCurrentCoverHandler deleteCurrentCoverHandler = new DeleteCurrentCoverHandler();
deleteCoverButton.addActionListener(deleteCurrentCoverHandler);
final JButton addButton = new JButton("Add an element");
AddANewCoverHandler addANewCoverHandler = new AddANewCoverHandler();
addButton.addActionListener(addANewCoverHandler);
final JPanel buttonPanel = new JPanel(); //FlowLayout.
buttonPanel.add(deleteCoverButton);
buttonPanel.add(addButton);
selectCoverFrame.getContentPane().add(spinnerCovers);
selectCoverFrame.getContentPane().add(buttonPanel);
selectCoverFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //With this call, when you close the frame, then the application gets terminated.
selectCoverFrame.setLocationRelativeTo(null); //With this call, the frame gets to the center of the screen.
selectCoverFrame.setVisible(true);
}
private class DeleteCurrentCoverHandler implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
spinnerCoversM.remove(spinnerCovers.getValue());
}
}
private class AddANewCoverHandler implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
spinnerCoversM.add(JOptionPane.showInputDialog("Enter the new element string:"));
}
}
public static void main(final String[] args) {
new ImageDealer2();
}
}