2017-02-07 2 views
2

Итак, я создал простой графический интерфейс Java Swing для графического движка opengl, который я разрабатывал.JAVA: Swing - actionPerformed() на JMenuItem срабатывает, но обновленные значения не сохраняются

Проблема, с которой я столкнулась, заключается в том, что панель меню не работает, как мне бы хотелось. В частности, у меня есть класс MenuBarBuilder, который создает различные меню, подменю и пункты меню. Когда элемент меню добавляется, ему назначается новый actionEventListener и задается простая задача: установить значение Boolean в true; это Boolean значение сохраняется в списке состояний, связанных с этим меню. Каждое состояние элемента меню создается при добавлении пункта меню в меню. Состояния сохраняются в классе 'StateList' как объект типа 'State'.

В классе MenuBarBuilder каждый элемент меню, который должен функционировать как единое целое, добавляется как «группа». Когда это делается, к каждому элементу меню добавляется второй исполнитель событий событий, который устанавливает все связанные значения группы меню в false. В конечном итоге это приводит к тому, что только один элемент меню в группе имеет состояние в списке состояний, для которого установлено значение true.

При нажатии на элемент меню активируются события прослушивателя действий. При выстреле они распечатать список, чтобы определить порядок их обжигают в и чтобы убедиться, что государственные значения устанавливаются, как и ожидалось, смотрите ниже:

setfalse 
list 
MenuItem1Name: false 
MenuItem2Name: false 

MenuItem1Name 
setTrue 
list 
MenuItem1Name: true 
MenuItem2Name: false 

setfalse 
list 
MenuItem1Name: false 
MenuItem2Name: false 

MenuItem2Name 
setTrue 
list 
MenuItem1Name: false 
MenuItem2Name: true 

Это гарантирует, что события стрельбы и в правильном порядке. Мы видим, что когда нажата кнопка MenuItem1Name, значения правильно установлены на false, и соответствующее поле впоследствии обновляется до значения true. То же самое можно увидеть для MenuItem2Name. Теперь, чтобы перейти к актуальной проблеме.

Когда я получаю список состояний и проверяю значения в цикле через класс GUI, я всегда получаю «ложные» значения из списка состояний. Я реализовал этот шаблон аналогичным образом, используя Swing toolbars, который отлично работает, но я просто не могу понять, почему я не могу получить значения, которые правильно установлены событиями прослушивания действия. Я не вижу места, где значения перезаписываются или где странный порядок/смешивание экземпляра объекта.

Итак, вопрос: почему я только когда-нибудь ложные при проверке списка состояния?

ОБНОВЛЕНО: попытка SSCCE


Here is UML class Diagram with the relevant classes

Ниже приводится реализация соответствующих классов.

State.java

public class State { 

    private String name; 
    private Object value; 

    State(String name, Object value){ 
     this.name=name; 
     this.value=value; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public Object getValue() { 
     return value; 
    } 

    public void setValue(Object value) { 
     this.value = value; 
    } 

    public String toString(){ 
     return getName() + ": " + getValue(); 
    } 

} 

StatesList.java

import java.util.ArrayList; 

public class StatesList { 

    private ArrayList<State> states; 

    StatesList(){ 
     states= new ArrayList<State>(); 
    } 

    void addState(String name, Object value){ 
     states.add(new State(name, value)); 
    } 

    State getState(String name){ 
     for(State s : states){ 
      if(s.getName().equals(name)){ 
       return s; 
      } 
     } 
     return null; 
    } 

    ArrayList<State> getStates() { 
     return states; 
    } 

    public String toString(){ 
     String rString=""; 
     rString+="list\n"; 
     for (State s : states) { 
      rString+=s.toString()+"\n"; 
     } 
     return rString; 
    } 

} 

MenuBar.java

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 

public class MenuBar { 

    private JMenuBar menuBar; 
    private StatesList menustates; 

    public MenuBar() { 
     menuBar = new JMenuBar(); 
     menustates = new StatesList(); 
    } 

    void createMenu(String title) { 
     JMenu menu = new JMenu(title); 
     menuBar.add(menu); 
    } 

    void createMenuItem(JMenu menu, String itemTitle) { 

     JMenuItem menuItem = new JMenuItem(itemTitle); 

     menustates.addState(itemTitle, false); 

     menuItem.addActionListener(new ActionListener() { 
      int menuItemindex = menustates.getStates().size()-1 ; 

      @Override 
      public void actionPerformed(ActionEvent actionEvent) { 
       System.out.println(actionEvent.getActionCommand()); 
       menustates.getStates().get(menuItemindex).setValue(true); 
       //print list of current states 
       System.out.println("setTrue"); 
       System.out.println(menustates.toString()); 
      } 
     }); 
     menu.add(menuItem); 
    } 

    //not a real group, just ensures MenuItem behaves the same as other menu items 
    void addMenuGroup(JMenuItem[] jMenuItems, int startComponentIndex) {  

     for (int i = 0; i < jMenuItems.length; i++) { 
      jMenuItems[i].addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        for (int i2 = 0; i2 < jMenuItems.length; i2++) { 
         //make sure each state related to the menuItemGroup is to false 
         menustates.getStates().get(i2 + startComponentIndex).setValue(false); 
        } 
        //print list of current states 
        System.out.println("setfalse"); 
        System.out.println(menustates.toString()); 
       } 
      }); 
     } 
    } 

    JMenuBar getMenuBar() { 
     return menuBar; 
    } 

    public StatesList getStates() { 
     return menustates; 
    } 


} 

MenuBarBuilder.Java

import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 

public class MenuBarBuilder { 

    private MenuBar DataViewMenuBar; 

    MenuBarBuilder() { 
     DataViewMenuBar = buildDataViewMenu(); 
    } 

    MenuBar buildDataViewMenu() { 
     MenuBar tb = new MenuBar(); 

     //create menu 
     tb.createMenu("TestScenes"); 

     //add two menuItems 
     tb.createMenuItem(tb.getMenuBar().getMenu(0), "MenuItem1Name"); 
     tb.createMenuItem(tb.getMenuBar().getMenu(0), "MenuItem2Name"); 

     //add buttons two a 'group' sort of 
     tb.addMenuGroup(new JMenuItem[] { 
       (JMenuItem) tb.getMenuBar().getMenu(0).getItem(0), 
       (JMenuItem) tb.getMenuBar().getMenu(0).getItem(1), }, 
       tb.getStates().getStates().size() - 2); 

     return tb; 
    } 

    StatesList getDataViewMenuBarStates() { 
     return DataViewMenuBar.getStates(); 
    } 

    JMenuBar getDataViewMenuBarMenubar() { 
     return DataViewMenuBar.getMenuBar(); 
    } 

} 

GUI.java

import javax.swing.JFrame; 

public class GUI { 

    MenuBarBuilder mbb; 
    boolean Selected = false; 

    GUI() { 
     mbb = new MenuBarBuilder(); 
    } 

    void run() { 
     final JFrame frame = new JFrame("Main"); 
     frame.setJMenuBar(mbb.buildDataViewMenu().getMenuBar()); 

     frame.pack(); 
     frame.setVisible(true); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     while (!Selected) { 
      selectLoadScene(); 
     } 
     System.out.print("bap- selection must have occured"); 
    } 

    void selectLoadScene() { 
     String selectedTest = ""; 


    // The Test Occurs here 
    // loop through states list 
     System.out.println(mbb.getDataViewMenuBarStates().getStates().toString()); 
     for (State s : mbb.getDataViewMenuBarStates().getStates()) { 
      // check the value for each state -this value is always false,.. 
      // thats the problem 
      if ((boolean) s.getValue() == true) { 
       // if true save value 
       selectedTest = s.getName(); 
       break; 
      } 
     } 

     // test selected value and see if it matches the following cases 
     switch (selectedTest) { 
     case "MenuItem1Name": 
      // dosomething 
      Selected = true; // breaks while loop 
      break; 
     case "MenuItem2Name": 
      // dosomething 
      Selected = true;// breaks while loop 
      break; 
     default: 
      // do nothing 
     } 
    } 
} 

Start.java

public class Start { 

    GUI gui; 

    public static void main(String[] args) { 
     GUI gui= new GUI(); 
     gui.run(); 
    } 

} 
+0

Вы ищете javax.swing.ButtonGroup? – ControlAltDel

+0

Запустили ли вы это через отладчик? –

+1

Чтобы лучше помочь, опубликуйте [MCVE] или [Short, Self Contained, Correct Example] (http://www.sscce.org/). –

ответ

1

строки меню в то время как цикл отличается от строки меню в действие выполняется методами. Зачем? Если вы внимательно изучите следующие 2 строки из GUI класса, вы узнаете.

mbb = new MenuBarBuilder(); 
frame.setJMenuBar(mbb.buildDataViewMenu().getMenuBar()); 

Здесь представлены 2 разных меню. поскольку конструктор MenuBarBuilder внутренне вызывает buildDataViewMenu(), поэтому 2 вызова на «buildDataViewMenu()». , который в итоге создаст 2 меню.

Чтобы избежать этого

Dont называть «buildDataViewMenu()» в

frame.setJMenuBar(mbb.buildDataViewMenu().getMenuBar()); 

Как вы просто хотите строку меню, вы должны управлять код таким образом, что вы получите ручку для this.tb = new MenuBar() может быть, вы можете добавить геттер и сеттер для того же самого.

Когда я добавил геттер и сеттер для того же, что и ниже, он начал работать.

public class MenuBarBuilder { 

private MenuBar DataViewMenuBar; 
MenuBar tb; 

MenuBarBuilder() { 
    DataViewMenuBar = buildDataViewMenu(); 
} 

MenuBar buildDataViewMenu() { 
    this.tb = new MenuBar(); 

    //create menu 
    tb.createMenu("TestScenes"); 

    //add two menuItems 
    tb.createMenuItem(tb.getMenuBar().getMenu(0), "MenuItem1Name"); 
    tb.createMenuItem(tb.getMenuBar().getMenu(0), "MenuItem2Name"); 

    //add buttons two a 'group' sort of 
    tb.addMenuGroup(new JMenuItem[] { 
      (JMenuItem) tb.getMenuBar().getMenu(0).getItem(0), 
      (JMenuItem) tb.getMenuBar().getMenu(0).getItem(1), }, 
      tb.getStates().getStates().size() - 2); 

    return tb; 
} 

public MenuBar getMenuBar(){ 
    return this.tb; 
} 

StatesList getDataViewMenuBarStates() { 
    return DataViewMenuBar.getStates(); 
} 

JMenuBar getDataViewMenuBarMenubar() { 
    return DataViewMenuBar.getMenuBar(); 
} 

} 

и в GUI вызова класса должен быть, как

frame.setJMenuBar(mbb.getMenuBar().getMenuBar()); 

Это позволит решить эту проблему. Дайте мне знать, если вы столкнулись с какой-либо проблемой.

+0

lol, .. я не даже. Да, это решает исходную проблему. – Kreals

+0

Я сделал методы сборки частными, что должно помешать мне сделать такую ​​глупую ошибку в будущем, спасибо. – Kreals

+0

Добро пожаловать! – NewToJava