Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.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 stateChanged方法更新JOptionPane中的消息_Java_Swing_Joptionpane_Jspinner - Fatal编程技术网

Java 使用JSpinner stateChanged方法更新JOptionPane中的消息

Java 使用JSpinner stateChanged方法更新JOptionPane中的消息,java,swing,joptionpane,jspinner,Java,Swing,Joptionpane,Jspinner,我制作了一个包含JSpinner组件的JOptionPane。我有一个名为skillMessage的字符串,它将是JOptionPane中显示的消息。我结合了我在网上所做的研究,制作了这样一个选项窗格(带有消息和微调器,以及被覆盖的stateChanged方法)。这是我的代码: skillMessage = "Current skill level: " + currLevel + "\n"; if (skillPoint > 0) { skillMessage += "Do y

我制作了一个包含JSpinner组件的JOptionPane。我有一个名为skillMessage的字符串,它将是JOptionPane中显示的消息。我结合了我在网上所做的研究,制作了这样一个选项窗格(带有消息和微调器,以及被覆盖的stateChanged方法)。这是我的代码:

skillMessage = "Current skill level: " + currLevel + "\n";

if (skillPoint > 0) {
    skillMessage += "Do you want to upgrade this skill to level " + (currLevel + 1)  + "?\n";
} else {
    skillMessage += "You do not have enough skill point to upgrade this skill!\n";
}

skillMessage += "Cost: 1 skill point\nYou have: " + skillPoint + " skill point(s) left";

if (skillPoint > 0) {
    Object[] options = {"Upgrade", "Cancel"};

    JSpinner spinner = new JSpinner(new SpinnerNumberModel(currLevel, currLevel, maxLevel, 1));
    JComponent comp = spinner.getEditor();
    JFormattedTextField field = (JFormattedTextField)comp.getComponent(0);
    DefaultFormatter formatter = (DefaultFormatter)field.getFormatter();
    formatter.setCommitsOnValidEdit(true);
    ((JSpinner.DefaultEditor)comp).getTextField().setEditable(false);
    ((JSpinner.DefaultEditor)comp).getTextField().setFocusable(false);

    spinner.addChangeListener(new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent ce) {
            int valueChanged = (Integer)spinner.getValue() - currLevel;
            skillMessage = "Current skill level: " + spinner.getValue() + "\n";

            if ((skillPoint - valueChanged) > 0) {
                skillMessage += "Do you want to upgrade this skill to level " + (currLevel + 1)  + "?\n";
            } else {
                skillMessage += "You do not have enough skill point to upgrade this skill!\n";
            }

            skillMessage += "Cost: 1 skill point\nYou have: " + (skillPoint - valueChanged) + " skill point(s) left";
            repaint();
        }
    });

    if (JOptionPane.showOptionDialog(null, new Object[] {skillMessage, spinner}, "Upgrade Skill", 1, 3, null, options, options[0]) == 0) {
        if ((skillPoint - (Integer)spinner.getValue() - currLevel) >= 0) {
            currLevel++;
            JOptionPane.showMessageDialog(null, "You've successfully upgraded this skill to level " + currLevel);
        } else {
            JOptionPane.showMessageDialog(null, "You do not have enough skill point!");
        }
    }
}

我现在要做的是,每次调用微调器的stateChanged方法时,都要使JopOptions窗格中的skillMessage得到“更新”。重新粉刷似乎不管用。提前谢谢

您实际上并没有在
作业窗格
上触发重新绘制,即使您触发了,我也不确定它是否会更新

更好的解决方案是将您试图执行的功能封装到它自己的类/组件中,这样,您就可以控制视图本身,并可以根据需要更新组件

例如:

public class SkillPane extends JPanel {

    private JSpinner spinner;
    private JLabel[] messages;
    private int skillPoints;
    private int currLevel;

    public SkillPane(final int currLevel, final int maxLevel, final int skillPoint) {
        spinner = new JSpinner(new SpinnerNumberModel(currLevel, currLevel, maxLevel, 1));
        this.skillPoints = skillPoint;
        this.currLevel = currLevel;

        messages = new JLabel[]{new JLabel(), new JLabel(), new JLabel()};
        updateMessages();

        setBorder(new EmptyBorder(4, 4, 4, 4));
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(4, 4, 4, 4);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.anchor = GridBagConstraints.LINE_START;
        add(messages[0], gbc);
        add(messages[1], gbc);
        add(messages[2], gbc);
        add(spinner, gbc);

        spinner.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent ce) {
                updateMessages();
            }
        });
    }

    public int getValue() {
        return (int) spinner.getValue();
    }

    public void updateMessages() {
        int valueChanged = (Integer) spinner.getValue() - currLevel;
        messages[0].setText("Current skill level: " + spinner.getValue());

        if ((skillPoints - valueChanged) > 0) {
            messages[1].setText("Do you want to upgrade this skill to level " + (currLevel + 1) + "?");
        } else {
            messages[1].setText("You do not have enough skill point to upgrade this skill!");
        }

        messages[2].setText("Cost: 1 skill point\nYou have: " + (skillPoints - valueChanged) + " skill point(s) left");
    }

}
注意:我最初的设计只有一个标签,并使用HTML来格式化文本,但我发现,随着对话框的不断中断,您也可以使用不可编辑的
JTextArea
或类似组件来生成类似的效果

你可以用类似于

    int skillPoint = 10;
    int currLevel = 0;

    Object[] options = {"Upgrade", "Cancel"};
    SkillPane pane = new SkillPane(currLevel, 100, skillPoint);

    if (JOptionPane.showOptionDialog(null, pane, "Upgrade Skill", 1, 3, null, options, options[0]) == 0) {
        int value = pane.getValue();

        if ((skillPoint - value - currLevel) >= 0) {
            currLevel++;
            JOptionPane.showMessageDialog(null, "You've successfully upgraded this skill to level " + currLevel);
        } else {
            JOptionPane.showMessageDialog(null, "You do not have enough skill point!");
        }
    }

实际上,您没有在
作业窗格
上触发重新绘制,即使触发了,我也不确定它是否会更新

更好的解决方案是将您试图执行的功能封装到它自己的类/组件中,这样,您就可以控制视图本身,并可以根据需要更新组件

例如:

public class SkillPane extends JPanel {

    private JSpinner spinner;
    private JLabel[] messages;
    private int skillPoints;
    private int currLevel;

    public SkillPane(final int currLevel, final int maxLevel, final int skillPoint) {
        spinner = new JSpinner(new SpinnerNumberModel(currLevel, currLevel, maxLevel, 1));
        this.skillPoints = skillPoint;
        this.currLevel = currLevel;

        messages = new JLabel[]{new JLabel(), new JLabel(), new JLabel()};
        updateMessages();

        setBorder(new EmptyBorder(4, 4, 4, 4));
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(4, 4, 4, 4);
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.anchor = GridBagConstraints.LINE_START;
        add(messages[0], gbc);
        add(messages[1], gbc);
        add(messages[2], gbc);
        add(spinner, gbc);

        spinner.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent ce) {
                updateMessages();
            }
        });
    }

    public int getValue() {
        return (int) spinner.getValue();
    }

    public void updateMessages() {
        int valueChanged = (Integer) spinner.getValue() - currLevel;
        messages[0].setText("Current skill level: " + spinner.getValue());

        if ((skillPoints - valueChanged) > 0) {
            messages[1].setText("Do you want to upgrade this skill to level " + (currLevel + 1) + "?");
        } else {
            messages[1].setText("You do not have enough skill point to upgrade this skill!");
        }

        messages[2].setText("Cost: 1 skill point\nYou have: " + (skillPoints - valueChanged) + " skill point(s) left");
    }

}
注意:我最初的设计只有一个标签,并使用HTML来格式化文本,但我发现,随着对话框的不断中断,您也可以使用不可编辑的
JTextArea
或类似组件来生成类似的效果

你可以用类似于

    int skillPoint = 10;
    int currLevel = 0;

    Object[] options = {"Upgrade", "Cancel"};
    SkillPane pane = new SkillPane(currLevel, 100, skillPoint);

    if (JOptionPane.showOptionDialog(null, pane, "Upgrade Skill", 1, 3, null, options, options[0]) == 0) {
        int value = pane.getValue();

        if ((skillPoint - value - currLevel) >= 0) {
            currLevel++;
            JOptionPane.showMessageDialog(null, "You've successfully upgraded this skill to level " + currLevel);
        } else {
            JOptionPane.showMessageDialog(null, "You do not have enough skill point!");
        }
    }

问题是,您真正重新绘制的是什么-提示,这不是
JOptionPane
,我的建议是将消息和微调器包装到一个自包含的类中,该类从
JPanel
扩展,然后将消息输出到
JLabel
@MadProgrammer是,我必须承认,我有点急切地想把repait()放在那里,我想它是在重新绘制整个画面,而不是JOptionPane本身。如果我按照你的建议,将JLabel(用于放置输出消息)放在JOptionPane中,我是否能够使用微调器的stateChanged方法“更新”它?问题是,你真正要重新绘制什么-提示,它不是
JOptionPane
,我的建议是将消息和微调器包装到一个自包含类中,该类从
JPanel
扩展而来,然后将消息输出到
JLabel
@MadProgrammer是的,我必须承认,我有点急于将repaint()放在那里,我认为这是在重新绘制整个框架,而不是JOptionPane本身。如果我按照你的建议,将JLabel(用于放置输出消息)放在JOptionPane中,我是否能够使用微调器的stateChanged方法“更新”它?谢谢!这似乎是正确的!我最终使用了不可编辑的JTextPane,因为我希望能够修改某些文本的颜色。仅供参考
JLabel
支持
HTML
rendering;)非常感谢。这似乎是正确的!我最终使用了不可编辑的JTextPane,因为我希望能够修改某些文本的颜色。仅供参考
JLabel
支持
HTML
rendering;)