2015-09-19 40 views
1

所以我製作了一個利用JComboBox的程序。我已經加入一個項目聽者像這樣:JComboBox getSelectedIndex不能工作兩次?

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變量 井是int和選定的是一個布爾值。

現在,項目偵聽器在第一次執行時工作,沒有問題。但是,在程序結束時,我有一個選項,提示用戶看看他們是否要再次運行程序。整個代碼基本上被封裝在一個while(true)循環中,如果用戶說不,他們不想再次運行。如果第二次再次運行,則項監聽器停止工作,並且getSelectedIndex()不再返回選定的索引。有人知道爲什麼嗎?

再次運行時JCombo框會再次被初始化BTW

我希望我能提供足夠的信息來獲得的解決方案。

UPDATE:

通過一個建議給我會嘗試更好地問我的問題

我有三個公共無效方法

在第一次運行該程序,擴展了公衆「類名」的方法JFrame初始化構建第一個JPanel並將其添加到JFrame的第一個part1方法。點擊一個按鈕後,第一個JPanel將從JFrame中刪除,第一種方法將在第二種方法中構建第二個JPanel並將其添加到JFrame中,從而使第二種方法在第二種方法中引發我們第二種方法

。點擊另一個按鈕後,將從JFrame中刪除第二個JPanel,第二種方法將我們帶到第三個方法

第三種方法構建第三個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); 
} 
} 

回答

2

整個代碼基本上包裹在一段時間(true)循環,打破如果用戶說沒有,他們不希望再次運行。

雖然這是對簡單的線性控制檯(僅文字)程序,這種結構將不能很好地與事件驅動程序的工作。相反,你應該將你的GUI組件重新設置爲它們的原始狀態(你如何做到這一點的細節將取決於你的程序的結構和組件,我們還不知道的事情),並且擺脫那個while (true)塊。

如果再次運行,項監聽器停止工作,並且getSelectedIndex()不再返回選定的索引。

我的猜測是你有不正確的引用。重新運行代碼時,顯示的JComboBox與正在偵聽的JComboBox不一樣。爲什麼?很難說你迄今爲止發佈的信息,但是你可能會創建一個新的JComboBox,它會以某種方式導致引用的分離。

我希望我已經提供了足夠的信息來獲得解決方案。

只是一個通用的解決方案,例如我上面發佈的。要獲得更詳細的解決方案,您需要創建併發布您的Minimal, Complete, and Verifiable example


編輯:使用您的代碼上面貼小執行的程序,而是一個不會重現,你有問題。請注意,有不相關的問題與您的代碼和我的代碼的推導,我還沒有固定的:

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); 
      } 
     } 
    }); 

當你運行這個時,你會看到不會重新創建cont按鈕並獲取多個ActionListeners,因此顯示的JComboBox不是被測試的。我建議簡化您的代碼結構,並掛在該...


編輯2
這裏是一個更糟糕的實現,採用的是CardLayout的MCVE,之一。它仍然可以通過使其更加MVC-ish,從與模型的控制視角分離得到改進:

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); 
    } 

} 
+0

謝謝你的迴應,我想我自言自語很差。 IT實際上並沒有包含在一個while(true)循環中,而是效果如此。我有3種公共無效的方法,第一種將第一種帶到第二種,第二種到第三種,如果在第三種,他們再說一遍,那麼第三種將把它帶回第一種。 – AntonioK

+0

@AntonioK:你會想改善你的問題,然後張貼足夠的相關代碼來幫助我們更好地理解你的問題,最好是[mcve](請閱讀鏈接,因爲如何創建這個鏈接的細節很重要)。祝你好運。 –

+0

我已經延長我的問題,試圖解釋的,希望它有助於找到一個解決方案... – AntonioK

相關問題