Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JSpinner dynamicali更新,如何删除元素?_Java_Swing_Jspinner - Fatal编程技术网

Java JSpinner dynamicali更新,如何删除元素?

Java JSpinner dynamicali更新,如何删除元素?,java,swing,jspinner,Java,Swing,Jspinner,我有一个JSpinner和一个喷丝头列表模型。我想做的是,一旦列表加载到模型中,JSpiner显示在一个框架中,就可以从微调器中删除元素。只需点击同一帧上的按钮即可完成此操作。单击操作的处理程序将删除微调器上当前选定的元素。 我当前的实现存在的问题是,当这个处理程序返回时,微调器中有一个IndexOutOfBoundsExeception(即当我从列表中删除最后一个元素时),这表明JSpinner没有得到很好的更新 我创建了一个新类ExtendedSpinner,它扩展了JSpinner,只是为

我有一个JSpinner和一个喷丝头列表模型。我想做的是,一旦列表加载到模型中,JSpiner显示在一个框架中,就可以从微调器中删除元素。只需点击同一帧上的按钮即可完成此操作。单击操作的处理程序将删除微调器上当前选定的元素。 我当前的实现存在的问题是,当这个处理程序返回时,微调器中有一个IndexOutOfBoundsExeception(即当我从列表中删除最后一个元素时),这表明JSpinner没有得到很好的更新

我创建了一个新类ExtendedSpinner,它扩展了JSpinner,只是为了使用fireStateChanged。 这是为了在删除元素时更新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();
    }
}