JComboBox getSelectedIndex 没有工作两次?
JComboBox getSelectedIndex not working twice?
所以我制作了一个利用 JComboBox 的程序。我添加了一个项目监听器,如下所示:
wellbox.addItemListener(
new ItemListener(){
@Override
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED){
well = (wellbox.getSelectedIndex()-1);
if (well >=0){selected = true;}
}
}
}
);
wellbox 是 JComboBox 变量
well 是一个 int,selected 是一个布尔值。
现在,项目侦听器在第一次执行时就可以工作,没问题。但是,在程序结束时,我有一个选项提示用户查看他们是否想再次 运行 该程序。整个代码基本上包含在一个 while(true) 循环中,如果用户说不,他们不想再次 运行 ,该循环就会中断。如果再次 运行 第二次,项目侦听器停止工作并且 getSelectedIndex() 不再返回选定的索引。有人知道为什么吗?
当 运行 再次初始化 JCombo Box 顺便说一句
我希望我提供了足够的信息以获得解决方案。
更新:
根据建议,我会尽量更好地提出我的问题
我有三个 public void 方法
首先 运行 启动程序时,扩展 JFrame 的 public "class name" 方法初始化第一个 part1 方法,该方法构建第一个 JPanel 并将其添加到 JFrame。单击按钮后,第一个 JPanel 从 JFrame 中删除,第一个方法将我们带到第二个方法
在第二种方法中,构建了第二个 JPanel,并将其添加到 JFrame 中。单击另一个按钮后,第二个 JPanel 从 JFrame 中删除,第二个方法将我们带到第三个方法
第三种方法构建第三个 JPanel 并将其添加到 JFrame。然后单击按钮后,使用以下代码删除所有内容:
part1.removeAll();
part2.removeAll();
part3.removeAll();
第三种方法然后从 JFrame 中删除第三个 JPanel。如果用户单击表示他们希望再次 运行 的按钮,第三种方法将我们再次带到第一种方法,再次重建 JPanel 并添加它们...
在第二种方法中,在第二个 JPanel 中我有一个 JComboBox 正在初始化并添加到第二个 JPanel。第一次,它 运行 是应该的,项目侦听器返回正确的索引。但是一旦再次运行如前所述,在删除所有内容然后重建之后,项目侦听器不再returns一个索引值。有谁知道为什么?
如果需要,这几乎是我的代码。任何我没有描述的我正在使用的方法都是不重要的。我已经拿出了一堆与这个问题完全无关的代码。
主要class:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class ReportCardGenerator {
public static void main(String[] args) {
debugReportGUI f = new debugReportGUI();
f.setVisible(true);
}
}
debugReportGUI Class
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.*;
public class debugReportGUI extends JFrame
{
JPanel part1 = new JPanel ();
JPanel part2 = new JPanel ();
JPanel part3 = new JPanel ();
JComboBox wellbox;
JButton cont = new JButton ("Continue");
int buttonW = 110, buttonL = 30, well = -1;
Actions AL = new Actions ();
String[] skills = {"", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
public debugReportGUI ()
{
super ("JFrame");
setLayout (new BorderLayout ());
setSize (800, 700);
setLocationRelativeTo (null);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setResizable (false);
add (part1, BorderLayout.CENTER);
Part1 ();
}
public void Part1 ()
{
part1.setLayout (null);
part1.add (cont);
cont.addActionListener (AL);
cont.setBounds (325, 630, buttonW, buttonL);
cont.setToolTipText ("Once all fields have been completed press to continue to next part of Generator");
}
private class Actions implements ActionListener
{
public void actionPerformed (ActionEvent ae)
{
if (ae.getSource () == cont)
{
part1.setVisible(false);
add (part2, BorderLayout.CENTER);
part2.setVisible (true);
Part2 ();
}
}
}
public void Part2 ()
{
part2.setLayout (null);
wellbox = new JComboBox (skills);
part2.add (wellbox);
wellbox.setLocation (75, 120);
wellbox.setSize (650, 40);
wellbox.addItemListener (
new ItemListener ()
{
//@ Override
public void itemStateChanged (ItemEvent ie)
{
if (ie.getStateChange () == ItemEvent.SELECTED)
{
well = (wellbox.getSelectedIndex () - 1);
System.out.println (well);
/*Initialized value of well is -1*/
}
}
}
);
JButton cont2 = new JButton ("Continue");
cont2.setBounds (345, 625, buttonW, buttonL);
cont2.setToolTipText ("When the skill for the ''well done'' comment and all failed items have been selected, press button ");
cont2.addActionListener (
new ActionListener ()
{
//@ Override
public void actionPerformed (ActionEvent ae)
{
if (well >= 0)
{
part2.setVisible(false);
add (part3, BorderLayout.CENTER);
part3.setVisible (true);
Part3 ();
}
else{
JOptionPane.showMessageDialog(null,"must select an option in the JComboBox","",JOptionPane.ERROR_MESSAGE);
}
}
}
);
part2.add (cont2);
}
public void Part3 ()
{
part3.setLayout (null);
JButton again = new JButton ("Write Another");
again.setBounds (530, 550, buttonW + 30, buttonL);
again.setToolTipText ("If you are finished with report card you can write another one for another student by clicking this button");
again.addActionListener (
new ActionListener ()
{
//@ Override
public void actionPerformed (ActionEvent ae)
{
well = -1;
part1.removeAll ();
part2.removeAll ();
part3.removeAll ();
remove (part3);
add (part1, BorderLayout.CENTER);
part1.setVisible (true);
Part1 ();
}
}
);
part3.add(again);
}
}
The entire code is essentially wrapped in a while(true) loop that breaks if the user says no, they do not want to run again.
虽然这对于简单的线性控制台(纯文本)程序来说很好,但这种结构不适用于事件驱动程序。相反,您应该将 GUI 的组件重新设置为它们的原始状态(如何执行此操作的细节将取决于程序的结构和组件,这些我们还不知道)并摆脱它 while (true)
块。
If run again for a second time, the item listener stops working and the getSelectedIndex() is no longer returning the selected index.
我的猜测是您的引用不正确。当您重新运行您的代码时,显示的JComboBox 与正在收听的不一样。为什么?很难说到目前为止您 post 编辑的信息,但您可能正在创建一个新的 JComboBox,它以某种方式导致引用解除关联。
I hope I have provided enough information to get a solution.
只是一个通用的解决方案,就像我在上面 post 编辑的那样。要获得更详细的解决方案,您需要创建 post 您的 Minimal, Complete, and Verifiable example.
编辑:一个 运行可用的小程序,它使用上面 post 编写的代码,但 不会重现您遇到的问题.请注意,您的代码和我对您的代码的推导存在不相关的问题,但我尚未修复:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class ReportGUI extends JFrame {
JPanel part1 = new JPanel();
JPanel part2 = new JPanel();
JPanel part3 = new JPanel();
// !! added
private JComboBox<String> wellbox;
protected int well;
protected boolean selected;
private String[] DUMMY_DATA = { "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday" };
public ReportGUI() {
super("Report Card Generator");
setLayout(new BorderLayout());
setSize(800, 700);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
// v.lvl = 10; add(part2, BorderLayout.CENTER); Part2();
add(part1, BorderLayout.CENTER);
Part1();
}
public void Part1() {
JButton nextPartBtn = new JButton("Next Part");
nextPartBtn.addActionListener(new Actions());
part1.add(nextPartBtn);
}
private class Actions implements ActionListener {
public void actionPerformed(ActionEvent ae) {
remove(part1);
add(part2, BorderLayout.CENTER);
part2.setVisible(true);
Part2();
//!!
revalidate();
repaint();
}
}
public void Part2() {
/* building JPanel part2 */
// !! wellbox = new JComboBox(v.wellskills[v.lvl]);
wellbox = new JComboBox<>(DUMMY_DATA);
part2.add(wellbox);
wellbox.setLocation(75, 120);
wellbox.setSize(650, 40);
wellbox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED) {
well = (wellbox.getSelectedIndex() - 1);
System.out.println(well);
if (well >= 0) {
selected = true;
}
}
}
});
/* rest of building JPanel part2 */
//!!
JButton showPart3Btn = new JButton(new AbstractAction("Show Part 3") {
@Override
public void actionPerformed(ActionEvent arg0) {
remove(part2);
add(part3, BorderLayout.CENTER);
part3.setVisible(true);
Part3();
revalidate();
repaint();
}
});
part2.add(showPart3Btn);
}
public void Part3() {
/* building JPanel part3 */
part1.removeAll();
part2.removeAll();
part3.removeAll();
remove(part3);
add(part1, BorderLayout.CENTER);
// part1.setVisible(true);
Part1();
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ReportGUI().setVisible(true);
}
});
}
}
编辑
使用您的最新代码,添加一些调试行,包括:
private class Actions implements ActionListener {
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == cont) {
ActionListener[] listeners = ((AbstractButton) cont).getActionListeners();
System.out.println("number of listeners added to cont: " + listeners.length);
part1.setVisible(false);
add(part2, BorderLayout.CENTER);
part2.setVisible(true);
Part2();
}
}
}
和
public void Part2() {
part2.setLayout(null);
wellbox = new JComboBox(skills);
System.out.println("wellbox created. hashcode: " + wellbox.hashCode());
part2.add(wellbox);
wellbox.setLocation(75, 120);
wellbox.setSize(650, 40);
wellbox.addItemListener(new ItemListener() {
// @ Override
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED) {
System.out.println("wellbox state change. hashcode: " + wellbox.hashCode());
well = (wellbox.getSelectedIndex() - 1);
System.out.println(well);
}
}
});
当您 运行 执行此操作时,您会看到没有重新创建连续按钮并添加了多个 ActionListeners,因此显示的 JComboBox 不是经过测试的那个。我会建议简化您的代码结构,并坚持下去...
编辑 2
这是 MCVE 的更多 OOP 实现,它使用 CardLayout。它仍然可以通过使其更像 MVC 来改进,将视图与控制从模型中分离出来:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class DebugReport2 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 700;
public static final String PART_1 = "part 1";
public static final String PART_2 = "part 2";
public static final String PART_3 = "part 3";
private CardLayout cardLayout = new CardLayout();
private Part1Panel part1Panel = new Part1Panel(this);
private Part2Panel part2Panel = new Part2Panel(this);
private Part3Panel part3Panel = new Part3Panel(this);
public DebugReport2() {
setLayout(cardLayout);
System.out.println(Part1Panel.class.getName());
add(part1Panel, PART_1);
add(part2Panel, PART_2);
add(part3Panel, PART_3);
}
// public method to allow other classes to swap views
public void showCard(String key) {
cardLayout.show(this, key);
}
public void part2Reset() {
part2Panel.reset();
}
public void setPart3SelectedOptionText(String selectedItem) {
part3Panel.setSelectedOptionText(selectedItem);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
DebugReport2 mainPanel = new DebugReport2();
JFrame frame = new JFrame("Debug Report 2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class BaseContinueAction extends AbstractAction {
private String key;
private DebugReport2 debugReport2;
public BaseContinueAction(String name, DebugReport2 debugReport2, String key) {
super(name);
int mnemnoic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemnoic); // first letter is mnemonic alt-key press.
this.key = key;
this.debugReport2 = debugReport2;
}
public String getKey() {
return key;
}
public DebugReport2 getDebugReport2() {
return debugReport2;
}
@Override
public void actionPerformed(ActionEvent e) {
debugReport2.showCard(key);
}
}
@SuppressWarnings("serial")
class Part1Panel extends JPanel {
private DebugReport2 debugReport2;
public Part1Panel(DebugReport2 debugReport2) {
this.debugReport2 = debugReport2;
setBorder(BorderFactory.createTitledBorder("Part 1 Panel")); // for debug purposes
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new ContinueAction("Continue", debugReport2, DebugReport2.PART_2)));
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.SOUTH);
}
private class ContinueAction extends BaseContinueAction {
public ContinueAction(String name, DebugReport2 debugReport2, String key) {
super(name, debugReport2, key);
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
getDebugReport2().part2Reset();
}
}
}
@SuppressWarnings("serial")
class Part2Panel extends JPanel {
private static final String[] DEFAULT_DATA = {"0", "1", "2", "3", "4", "5", "6"};
private DebugReport2 debugReport2;
private ComboBoxModel<String> comboModel = new DefaultComboBoxModel<>();
private JComboBox<String> skillsCombo = new JComboBox<>(comboModel);
public Part2Panel(DebugReport2 debugReport2) {
((DefaultComboBoxModel<String>)comboModel).addElement("");
for (String item : DEFAULT_DATA) {
((DefaultComboBoxModel<String>)comboModel).addElement("Selection " + item);
}
this.debugReport2 = debugReport2;
setBorder(BorderFactory.createTitledBorder("Part 2 Panel")); // for debug purposes
JPanel centerPanel = new JPanel(); // uses default FlowLayout
centerPanel.add(skillsCombo);
JPanel bottomPanel = new JPanel(); // again default FlowLayout
bottomPanel.add(new JButton(new ContinueAction("Continue", debugReport2, DebugReport2.PART_3)));
setLayout(new BorderLayout());
add(centerPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
// if you need outside classes to be able to change the combo box model
// also resets selected index to -1
public void setComboModel(ComboBoxModel<String> comboModel) {
// reset combobox selection to -1, but remove listeners before doing so, and then
// re-add them afterwards
ItemListener[] itemListeners = skillsCombo.getItemListeners();
for (ItemListener itemListener : itemListeners) {
skillsCombo.removeItemListener(itemListener);
}
this.comboModel = comboModel;
skillsCombo.setModel(comboModel);
skillsCombo.setSelectedIndex(-1);
for (ItemListener itemListener : itemListeners) {
skillsCombo.addItemListener(itemListener);
}
}
public void reset() {
ComboBoxModel<String> model = skillsCombo.getModel();
setComboModel(model);
}
private class ContinueAction extends BaseContinueAction {
private String selectedItem = "";
public ContinueAction(String name, DebugReport2 debugReport2, String key) {
super(name, debugReport2, key);
}
@Override
public void actionPerformed(ActionEvent e) {
selectedItem = (String) skillsCombo.getSelectedItem();
if (selectedItem == null || selectedItem.trim().isEmpty()) {
Component parent = debugReport2;
String title = "Option Not Selected";
String message = "You must select an option before continuing";
int type = JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(parent, message, title, type);
} else {
// show the next view in the card layout
super.actionPerformed(e);
getDebugReport2().setPart3SelectedOptionText(selectedItem);
}
}
}
}
@SuppressWarnings("serial")
class Part3Panel extends JPanel {
private DebugReport2 debugReport2;
private JTextField selectedOptionField = new JTextField(10);
public Part3Panel(DebugReport2 debugReport2) {
this.debugReport2 = debugReport2;
setBorder(BorderFactory.createTitledBorder("Part 3 Panel")); // for debug purposes
add(new JLabel("Selected Option:"));
add(selectedOptionField);
add(new JButton(new BaseContinueAction("Continue", debugReport2, DebugReport2.PART_1)));
}
public void setSelectedOptionText(String text) {
selectedOptionField.setText(text);
}
}
所以我制作了一个利用 JComboBox 的程序。我添加了一个项目监听器,如下所示:
wellbox.addItemListener(
new ItemListener(){
@Override
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED){
well = (wellbox.getSelectedIndex()-1);
if (well >=0){selected = true;}
}
}
}
);
wellbox 是 JComboBox 变量 well 是一个 int,selected 是一个布尔值。
现在,项目侦听器在第一次执行时就可以工作,没问题。但是,在程序结束时,我有一个选项提示用户查看他们是否想再次 运行 该程序。整个代码基本上包含在一个 while(true) 循环中,如果用户说不,他们不想再次 运行 ,该循环就会中断。如果再次 运行 第二次,项目侦听器停止工作并且 getSelectedIndex() 不再返回选定的索引。有人知道为什么吗?
当 运行 再次初始化 JCombo Box 顺便说一句
我希望我提供了足够的信息以获得解决方案。
更新:
根据建议,我会尽量更好地提出我的问题
我有三个 public void 方法
首先 运行 启动程序时,扩展 JFrame 的 public "class name" 方法初始化第一个 part1 方法,该方法构建第一个 JPanel 并将其添加到 JFrame。单击按钮后,第一个 JPanel 从 JFrame 中删除,第一个方法将我们带到第二个方法
在第二种方法中,构建了第二个 JPanel,并将其添加到 JFrame 中。单击另一个按钮后,第二个 JPanel 从 JFrame 中删除,第二个方法将我们带到第三个方法
第三种方法构建第三个 JPanel 并将其添加到 JFrame。然后单击按钮后,使用以下代码删除所有内容:
part1.removeAll();
part2.removeAll();
part3.removeAll();
第三种方法然后从 JFrame 中删除第三个 JPanel。如果用户单击表示他们希望再次 运行 的按钮,第三种方法将我们再次带到第一种方法,再次重建 JPanel 并添加它们...
在第二种方法中,在第二个 JPanel 中我有一个 JComboBox 正在初始化并添加到第二个 JPanel。第一次,它 运行 是应该的,项目侦听器返回正确的索引。但是一旦再次运行如前所述,在删除所有内容然后重建之后,项目侦听器不再returns一个索引值。有谁知道为什么?
如果需要,这几乎是我的代码。任何我没有描述的我正在使用的方法都是不重要的。我已经拿出了一堆与这个问题完全无关的代码。
主要class:
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
public class ReportCardGenerator {
public static void main(String[] args) {
debugReportGUI f = new debugReportGUI();
f.setVisible(true);
}
}
debugReportGUI Class
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.event.*;
public class debugReportGUI extends JFrame
{
JPanel part1 = new JPanel ();
JPanel part2 = new JPanel ();
JPanel part3 = new JPanel ();
JComboBox wellbox;
JButton cont = new JButton ("Continue");
int buttonW = 110, buttonL = 30, well = -1;
Actions AL = new Actions ();
String[] skills = {"", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
public debugReportGUI ()
{
super ("JFrame");
setLayout (new BorderLayout ());
setSize (800, 700);
setLocationRelativeTo (null);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setResizable (false);
add (part1, BorderLayout.CENTER);
Part1 ();
}
public void Part1 ()
{
part1.setLayout (null);
part1.add (cont);
cont.addActionListener (AL);
cont.setBounds (325, 630, buttonW, buttonL);
cont.setToolTipText ("Once all fields have been completed press to continue to next part of Generator");
}
private class Actions implements ActionListener
{
public void actionPerformed (ActionEvent ae)
{
if (ae.getSource () == cont)
{
part1.setVisible(false);
add (part2, BorderLayout.CENTER);
part2.setVisible (true);
Part2 ();
}
}
}
public void Part2 ()
{
part2.setLayout (null);
wellbox = new JComboBox (skills);
part2.add (wellbox);
wellbox.setLocation (75, 120);
wellbox.setSize (650, 40);
wellbox.addItemListener (
new ItemListener ()
{
//@ Override
public void itemStateChanged (ItemEvent ie)
{
if (ie.getStateChange () == ItemEvent.SELECTED)
{
well = (wellbox.getSelectedIndex () - 1);
System.out.println (well);
/*Initialized value of well is -1*/
}
}
}
);
JButton cont2 = new JButton ("Continue");
cont2.setBounds (345, 625, buttonW, buttonL);
cont2.setToolTipText ("When the skill for the ''well done'' comment and all failed items have been selected, press button ");
cont2.addActionListener (
new ActionListener ()
{
//@ Override
public void actionPerformed (ActionEvent ae)
{
if (well >= 0)
{
part2.setVisible(false);
add (part3, BorderLayout.CENTER);
part3.setVisible (true);
Part3 ();
}
else{
JOptionPane.showMessageDialog(null,"must select an option in the JComboBox","",JOptionPane.ERROR_MESSAGE);
}
}
}
);
part2.add (cont2);
}
public void Part3 ()
{
part3.setLayout (null);
JButton again = new JButton ("Write Another");
again.setBounds (530, 550, buttonW + 30, buttonL);
again.setToolTipText ("If you are finished with report card you can write another one for another student by clicking this button");
again.addActionListener (
new ActionListener ()
{
//@ Override
public void actionPerformed (ActionEvent ae)
{
well = -1;
part1.removeAll ();
part2.removeAll ();
part3.removeAll ();
remove (part3);
add (part1, BorderLayout.CENTER);
part1.setVisible (true);
Part1 ();
}
}
);
part3.add(again);
}
}
The entire code is essentially wrapped in a while(true) loop that breaks if the user says no, they do not want to run again.
虽然这对于简单的线性控制台(纯文本)程序来说很好,但这种结构不适用于事件驱动程序。相反,您应该将 GUI 的组件重新设置为它们的原始状态(如何执行此操作的细节将取决于程序的结构和组件,这些我们还不知道)并摆脱它 while (true)
块。
If run again for a second time, the item listener stops working and the getSelectedIndex() is no longer returning the selected index.
我的猜测是您的引用不正确。当您重新运行您的代码时,显示的JComboBox 与正在收听的不一样。为什么?很难说到目前为止您 post 编辑的信息,但您可能正在创建一个新的 JComboBox,它以某种方式导致引用解除关联。
I hope I have provided enough information to get a solution.
只是一个通用的解决方案,就像我在上面 post 编辑的那样。要获得更详细的解决方案,您需要创建 post 您的 Minimal, Complete, and Verifiable example.
编辑:一个 运行可用的小程序,它使用上面 post 编写的代码,但 不会重现您遇到的问题.请注意,您的代码和我对您的代码的推导存在不相关的问题,但我尚未修复:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
@SuppressWarnings("serial")
public class ReportGUI extends JFrame {
JPanel part1 = new JPanel();
JPanel part2 = new JPanel();
JPanel part3 = new JPanel();
// !! added
private JComboBox<String> wellbox;
protected int well;
protected boolean selected;
private String[] DUMMY_DATA = { "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday" };
public ReportGUI() {
super("Report Card Generator");
setLayout(new BorderLayout());
setSize(800, 700);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
// v.lvl = 10; add(part2, BorderLayout.CENTER); Part2();
add(part1, BorderLayout.CENTER);
Part1();
}
public void Part1() {
JButton nextPartBtn = new JButton("Next Part");
nextPartBtn.addActionListener(new Actions());
part1.add(nextPartBtn);
}
private class Actions implements ActionListener {
public void actionPerformed(ActionEvent ae) {
remove(part1);
add(part2, BorderLayout.CENTER);
part2.setVisible(true);
Part2();
//!!
revalidate();
repaint();
}
}
public void Part2() {
/* building JPanel part2 */
// !! wellbox = new JComboBox(v.wellskills[v.lvl]);
wellbox = new JComboBox<>(DUMMY_DATA);
part2.add(wellbox);
wellbox.setLocation(75, 120);
wellbox.setSize(650, 40);
wellbox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED) {
well = (wellbox.getSelectedIndex() - 1);
System.out.println(well);
if (well >= 0) {
selected = true;
}
}
}
});
/* rest of building JPanel part2 */
//!!
JButton showPart3Btn = new JButton(new AbstractAction("Show Part 3") {
@Override
public void actionPerformed(ActionEvent arg0) {
remove(part2);
add(part3, BorderLayout.CENTER);
part3.setVisible(true);
Part3();
revalidate();
repaint();
}
});
part2.add(showPart3Btn);
}
public void Part3() {
/* building JPanel part3 */
part1.removeAll();
part2.removeAll();
part3.removeAll();
remove(part3);
add(part1, BorderLayout.CENTER);
// part1.setVisible(true);
Part1();
revalidate();
repaint();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new ReportGUI().setVisible(true);
}
});
}
}
编辑
使用您的最新代码,添加一些调试行,包括:
private class Actions implements ActionListener {
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == cont) {
ActionListener[] listeners = ((AbstractButton) cont).getActionListeners();
System.out.println("number of listeners added to cont: " + listeners.length);
part1.setVisible(false);
add(part2, BorderLayout.CENTER);
part2.setVisible(true);
Part2();
}
}
}
和
public void Part2() {
part2.setLayout(null);
wellbox = new JComboBox(skills);
System.out.println("wellbox created. hashcode: " + wellbox.hashCode());
part2.add(wellbox);
wellbox.setLocation(75, 120);
wellbox.setSize(650, 40);
wellbox.addItemListener(new ItemListener() {
// @ Override
public void itemStateChanged(ItemEvent ie) {
if (ie.getStateChange() == ItemEvent.SELECTED) {
System.out.println("wellbox state change. hashcode: " + wellbox.hashCode());
well = (wellbox.getSelectedIndex() - 1);
System.out.println(well);
}
}
});
当您 运行 执行此操作时,您会看到没有重新创建连续按钮并添加了多个 ActionListeners,因此显示的 JComboBox 不是经过测试的那个。我会建议简化您的代码结构,并坚持下去...
编辑 2
这是 MCVE 的更多 OOP 实现,它使用 CardLayout。它仍然可以通过使其更像 MVC 来改进,将视图与控制从模型中分离出来:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
@SuppressWarnings("serial")
public class DebugReport2 extends JPanel {
private static final int PREF_W = 800;
private static final int PREF_H = 700;
public static final String PART_1 = "part 1";
public static final String PART_2 = "part 2";
public static final String PART_3 = "part 3";
private CardLayout cardLayout = new CardLayout();
private Part1Panel part1Panel = new Part1Panel(this);
private Part2Panel part2Panel = new Part2Panel(this);
private Part3Panel part3Panel = new Part3Panel(this);
public DebugReport2() {
setLayout(cardLayout);
System.out.println(Part1Panel.class.getName());
add(part1Panel, PART_1);
add(part2Panel, PART_2);
add(part3Panel, PART_3);
}
// public method to allow other classes to swap views
public void showCard(String key) {
cardLayout.show(this, key);
}
public void part2Reset() {
part2Panel.reset();
}
public void setPart3SelectedOptionText(String selectedItem) {
part3Panel.setSelectedOptionText(selectedItem);
}
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
DebugReport2 mainPanel = new DebugReport2();
JFrame frame = new JFrame("Debug Report 2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class BaseContinueAction extends AbstractAction {
private String key;
private DebugReport2 debugReport2;
public BaseContinueAction(String name, DebugReport2 debugReport2, String key) {
super(name);
int mnemnoic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemnoic); // first letter is mnemonic alt-key press.
this.key = key;
this.debugReport2 = debugReport2;
}
public String getKey() {
return key;
}
public DebugReport2 getDebugReport2() {
return debugReport2;
}
@Override
public void actionPerformed(ActionEvent e) {
debugReport2.showCard(key);
}
}
@SuppressWarnings("serial")
class Part1Panel extends JPanel {
private DebugReport2 debugReport2;
public Part1Panel(DebugReport2 debugReport2) {
this.debugReport2 = debugReport2;
setBorder(BorderFactory.createTitledBorder("Part 1 Panel")); // for debug purposes
JPanel bottomPanel = new JPanel();
bottomPanel.add(new JButton(new ContinueAction("Continue", debugReport2, DebugReport2.PART_2)));
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.SOUTH);
}
private class ContinueAction extends BaseContinueAction {
public ContinueAction(String name, DebugReport2 debugReport2, String key) {
super(name, debugReport2, key);
}
@Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
getDebugReport2().part2Reset();
}
}
}
@SuppressWarnings("serial")
class Part2Panel extends JPanel {
private static final String[] DEFAULT_DATA = {"0", "1", "2", "3", "4", "5", "6"};
private DebugReport2 debugReport2;
private ComboBoxModel<String> comboModel = new DefaultComboBoxModel<>();
private JComboBox<String> skillsCombo = new JComboBox<>(comboModel);
public Part2Panel(DebugReport2 debugReport2) {
((DefaultComboBoxModel<String>)comboModel).addElement("");
for (String item : DEFAULT_DATA) {
((DefaultComboBoxModel<String>)comboModel).addElement("Selection " + item);
}
this.debugReport2 = debugReport2;
setBorder(BorderFactory.createTitledBorder("Part 2 Panel")); // for debug purposes
JPanel centerPanel = new JPanel(); // uses default FlowLayout
centerPanel.add(skillsCombo);
JPanel bottomPanel = new JPanel(); // again default FlowLayout
bottomPanel.add(new JButton(new ContinueAction("Continue", debugReport2, DebugReport2.PART_3)));
setLayout(new BorderLayout());
add(centerPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
}
// if you need outside classes to be able to change the combo box model
// also resets selected index to -1
public void setComboModel(ComboBoxModel<String> comboModel) {
// reset combobox selection to -1, but remove listeners before doing so, and then
// re-add them afterwards
ItemListener[] itemListeners = skillsCombo.getItemListeners();
for (ItemListener itemListener : itemListeners) {
skillsCombo.removeItemListener(itemListener);
}
this.comboModel = comboModel;
skillsCombo.setModel(comboModel);
skillsCombo.setSelectedIndex(-1);
for (ItemListener itemListener : itemListeners) {
skillsCombo.addItemListener(itemListener);
}
}
public void reset() {
ComboBoxModel<String> model = skillsCombo.getModel();
setComboModel(model);
}
private class ContinueAction extends BaseContinueAction {
private String selectedItem = "";
public ContinueAction(String name, DebugReport2 debugReport2, String key) {
super(name, debugReport2, key);
}
@Override
public void actionPerformed(ActionEvent e) {
selectedItem = (String) skillsCombo.getSelectedItem();
if (selectedItem == null || selectedItem.trim().isEmpty()) {
Component parent = debugReport2;
String title = "Option Not Selected";
String message = "You must select an option before continuing";
int type = JOptionPane.ERROR_MESSAGE;
JOptionPane.showMessageDialog(parent, message, title, type);
} else {
// show the next view in the card layout
super.actionPerformed(e);
getDebugReport2().setPart3SelectedOptionText(selectedItem);
}
}
}
}
@SuppressWarnings("serial")
class Part3Panel extends JPanel {
private DebugReport2 debugReport2;
private JTextField selectedOptionField = new JTextField(10);
public Part3Panel(DebugReport2 debugReport2) {
this.debugReport2 = debugReport2;
setBorder(BorderFactory.createTitledBorder("Part 3 Panel")); // for debug purposes
add(new JLabel("Selected Option:"));
add(selectedOptionField);
add(new JButton(new BaseContinueAction("Continue", debugReport2, DebugReport2.PART_1)));
}
public void setSelectedOptionText(String text) {
selectedOptionField.setText(text);
}
}