所以我创建了一个使用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 btw
我希望我提供了足够的信息来获得解决方案。
更新:
根据建议,我会尝试更好地提出我的问题
我有三个公共无效方法
首次运行程序时,公共"类名称"扩展JFrame的方法初始化第一个part1方法,该方法构建第一个JPanel并将其添加到JFrame。单击一个按钮后,第一个JPanel将从JFrame中删除,第一个方法将我们带到第二个方法
在第二种方法中构建第二个JPanel,并添加到JFrame中。单击另一个按钮后,第二个JPanel将从JFrame中删除,第二个方法将我们带到第三个方法
第三种方法构建第三个JPanel并将其添加到JFrame。然后,单击一个按钮后,将使用以下代码删除所有内容:
part1.removeAll();
part2.removeAll();
part3.removeAll();
然后第三种方法从JFrame中删除第三个JPanel。如果用户单击了表示他们希望再次运行它的按钮,则第三种方法再次将我们带到第一种方法,再次重建JPanel并添加它们......
在第二种方法中,在第二个JPanel中,我初始化了JComboBox并添加了第二个JPanel。第一次,它运行应该,项侦听器返回正确的索引。但是,如前所述再次运行,在删除所有内容然后重建之后,项侦听器不再返回索引值。有谁知道为什么?
如果需要,这里几乎是我的代码。我没有描述过我正在使用的任何方法都是不重要的。我已经拿出了一堆与这个问题无关的代码。
主要课程:
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类
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);
}
}
答案 0 :(得分:2)
整个代码基本上都包含在while(true)循环中,如果用户拒绝,则会中断,他们不想再次运行。
虽然这对于简单的线性控制台(纯文本)程序来说很好,但这种构造对于事件驱动的程序不会很好。相反,您应该将GUI的组件重新设置为其原始状态(有关如何执行此操作的详细信息取决于程序的结构和组件,我们还不知道的事情)并删除{{1}阻止。
如果再次运行,则项侦听器停止工作,并且getSelectedIndex()不再返回所选索引。
我的猜测是你的错误引用。重新运行代码时,显示的JComboBox与正在侦听的代码不同。为什么?很难说你到目前为止发布的信息,但你可能会创建一个新的JComboBox,它会以某种方式导致引用的解除关联。
我希望我提供了足够的信息来获得解决方案。
只是一个通用的解决方案,例如我上面发布的。要获得更详细的解决方案,您需要创建并发布Minimal, Complete, and Verifiable example。
编辑:一个小型的可运行程序,它使用上面发布的代码,但不能重现您遇到的问题。请注意,您的代码存在无关的问题以及我尚未修复的代码派生问题:
while (true)
修改
使用您的最新代码,添加一些调试行,包括:
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();
}
}
}
当你运行它时,你会看到没有重新创建cont按钮并添加了多个ActionListener,因此显示的JComboBox不是被测试的那个。我建议简化你的代码结构,并坚持下去......
编辑2
这是MCVE的更多OOP实现,使用CardLayout。它仍然可以通过使其更多MVC-ish来改进,将视图与控件分离:
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);
}
}
});