2014-12-01 8 views
0

Я делаю очень плохую попытку в ActionListeners здесь.ActionListeners JMenuItems - Перекрестные классы

Я пытаюсь использовать ActionListeners для запуска кода из другого класса (AddForm.java) после нажатия JMenuItem (в MainMenu.java).

Во-первых, вот код: MainMenu.java

package carparksystem; 

import javax.swing.JFrame; 
import javax.swing.*; 
import java.awt.event.ActionListener; 
import java.awt.event.ActionEvent; 
import java.awt.*; 
import java.awt.event.*; 

public class MainMenu extends JFrame 
{ 
public MainMenu() 
{ 
    JMenuBar mainMenu = new JMenuBar(); 
    JMenu main = new JMenu("Menu"); 

    mainMenu.add(main); 

    JMenuItem addCar = new JMenuItem("Add Car"); 
    addCar.setActionCommand("Add"); 
    main.add(addCar); 
    //addCar.addActionListener(); 

    JMenuItem removeCar = new JMenuItem("Remove Car"); 
    removeCar.setActionCommand("Remove"); 
    main.add(removeCar); 

    JMenuItem searchCars = new JMenuItem("Search Cars"); 
    searchCars.setActionCommand("Search"); 
    main.add(searchCars); 

    setJMenuBar(mainMenu); 

    /* 
    //Add action listener for the Add Car button 
    addCar.addActionListener 
    (
     new ActionListener() 
      { 
       @Override 
       public void actionPerformed(ActionEvent e) 
       { 
        MainMenu.windowClosed(); 
       }  
      }   
    ); 
    */ 
} 
} 

AddForm.java:

package carparksystem; 

import javax.swing.ButtonGroup; 
import javax.swing.GroupLayout; 
import javax.swing.JButton; 
import javax.swing.JLabel; 
import javax.swing.JRadioButton; 
import javax.swing.JTextField; 
import javax.swing.WindowConstants; 
import javax.swing.JFrame; 

public class AddForm extends JFrame 
{ 
public AddForm() 
{   
    JLabel regNumLabel = new JLabel("Registration Number:"); 
    JLabel highValLabel = new JLabel("High Value?"); 
    JLabel largeLabel = new JLabel("Large Vehicle?"); 

    JRadioButton btnYesHighVal = new JRadioButton("Yes", false); 
    JRadioButton btnNoHighVal = new JRadioButton("No", true); 
    JRadioButton btnYesLarge = new JRadioButton("Yes", false); 
    JRadioButton btnNoLarge = new JRadioButton("No", true); 

    ButtonGroup highVal = new ButtonGroup();  //allows just one radio button from the group to be selected 
    highVal.add(btnYesHighVal); 
    highVal.add(btnNoHighVal); 

    ButtonGroup largeCar = new ButtonGroup();  //allows just one radio button from the group to be selected 
    largeCar.add(btnYesLarge); 
    largeCar.add(btnNoLarge); 

    JTextField regNumField = new JTextField(); 

    JButton addCar = new JButton(" Add "); 
    JButton addCancel = new JButton("Cancel"); 

    GroupLayout addLayout = new GroupLayout(getContentPane());  //chosen to display components in group layout 
    getContentPane().setLayout(addLayout); 
    addLayout.setAutoCreateGaps(true); 
    addLayout.setAutoCreateContainerGaps(true); 

    addLayout.setHorizontalGroup(addLayout.createSequentialGroup() 
     .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.LEADING) 
      .addComponent(regNumLabel) 
      .addComponent(highValLabel) 
      .addComponent(largeLabel)) 
     .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.LEADING) 
      .addComponent(regNumField) 
      .addGroup(addLayout.createSequentialGroup() 
       .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.LEADING) 
       .addComponent(btnYesHighVal) 
       .addComponent(btnYesLarge)) 
      .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.LEADING) 
       .addComponent(btnNoHighVal) 
       .addComponent(btnNoLarge)))) 
     .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.LEADING) 
      .addComponent(addCar) 
      .addComponent(addCancel)) 
    ); 

    addLayout.setVerticalGroup(addLayout.createSequentialGroup() 
     .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 
      .addComponent(regNumLabel) 
      .addComponent(regNumField) 
      .addComponent(addCar)) 
     .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.LEADING) 
      .addGroup(addLayout.createSequentialGroup() 
       .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 
        .addComponent(highValLabel) 
        .addComponent(btnYesHighVal) 
        .addComponent(btnNoHighVal)) 
       .addGroup(addLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) 
        .addComponent(largeLabel)  
        .addComponent(btnYesLarge) 
        .addComponent(btnNoLarge))) 
       .addComponent(addCancel)) 
     ); 

    setSize(375, 150); 
    setTitle("Add Car"); 
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
} 

На основной раме я нарисовал ряд форм, которые будут появляться на раме в первом , И над ним будет JMenu с JMenuItems Добавить, удалить и найти автомобили в меню.

После нажатия этих кнопок «Удалить» и «Поиск» они откроют соответствующую форму, которая позволит пользователю вводить данные.

Когда я запускаю свой код с и без прослушивателей действий, он работает как обычно, но меню вообще не ссылаются. Как будто они не имеют никакого значения?

+3

Я настоятельно рекомендую вам пересмотреть заголовок к чему-то более содержательному. –

ответ

2

Некоторые основные вопросы:

  • Если один класс должен иметь эффект на другой, это будет нужно ссылку на этот другой класс, так что он может все его методы.
  • Таким образом, если вашему классу MainMenu необходимо изменить состояние класса AddForm, то для этого для MainMenu потребуется поле AddForm, и, что более важно, это поле должно ссылаться на текущий активный объект AddForm.
  • Еще лучшая структура программы заключается в использовании структуры M-V-C или Model-View-Control, в которой два представления соединены совместно используемой моделью, но это может быть немного продвинуто для вашей простой программы. Тем не менее, если вы хотите следовать лучшим практикам, это будет путь. This example показывает более простую концепцию View-Control, которая также может работать.
  • Как правило, это плохая идея для того, чтобы графический интерфейс имел несколько окон верхнего уровня, что для Java означает несколько JFrames. Лучше иметь одно главное окно и другие представления, которые могут быть заменены в нем, если необходимо, с помощью CardLayout или которые могут отображаться в диалоговых окнах, если это необходимо. Пожалуйста, проверьте The Use of Multiple JFrames, Good/Bad Practice?.

Для простого примера, не MVC, вы могли бы иметь методы, требующие один класс из второго. Предположим, что JPanel, который содержит JList называется View1, который имеет открытый метод, addItem(String item), который добавляет элементы карапуз он модель JList в:

public class View1 extends JPanel { 
    private static final String PROTOTYPE = String.format("%50s", " "); 
    private DefaultListModel<String> listModel = new DefaultListModel<>(); 
    private JList<String> list = new JList<>(listModel); 

    public View1() { 
     list.setPrototypeCellValue(PROTOTYPE); 
     list.setVisibleRowCount(8); 
     JScrollPane scrollPane = new JScrollPane(list); 
     scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 
     add(scrollPane); 
    } 

    public void addItem(String item) { 
     listModel.addElement(item); 
    } 
} 

Рассмотрим второй класс JPanel, View2, что держит JTextArea и JButton и экземпляр View1. Этот второй класс может затем вызвать addItem(...) метод View1:

public class View2 extends JPanel { 
    private View1 view1; 
    private JTextField textField = new JTextField(10); 

    public View2(View1 view1) { 
     Action addItemAction = new AddItemAction(); 
     this.view1 = view1; 
     add(textField); 
     add(new JButton(addItemAction)); 
     textField.setAction(addItemAction); 
    } 

    private class AddItemAction extends AbstractAction { 
     public AddItemAction() { 
     super("Add Item"); 
     putValue(MNEMONIC_KEY, KeyEvent.VK_A); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     view1.addItem(textField.getText()); // *** calls view1's method here 
     textField.selectAll(); 
     } 
    } 
} 

Затем вы могли бы создать два класса, передавая View1 в конструктор VIEW2 в

View1 view1 = new View1(); 
    View2 view2 = new View2(view1); 

А затем уложить в JFrame другой в немодальный JDialog и дисплей.Например:

import java.awt.Dialog.ModalityType; 
import java.awt.event.ActionEvent; 
import java.awt.event.KeyEvent; 

import javax.swing.*; 

public class SimpleGuis { 
    private static void createAndShowGui() { 
     View1 view1 = new View1(); 
     View2 view2 = new View2(view1); 

     JFrame frame = new JFrame("SimpleGuis"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(view1); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 

     JDialog dialog = new JDialog(frame, "View2", ModalityType.MODELESS); 
     dialog.add(view2); 
     dialog.pack(); 
     dialog.setLocationByPlatform(true); 
     dialog.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

class View1 extends JPanel { 
    private static final String PROTOTYPE = String.format("%50s", " "); 
    private DefaultListModel<String> listModel = new DefaultListModel<>(); 
    private JList<String> list = new JList<>(listModel); 

    public View1() { 
     list.setPrototypeCellValue(PROTOTYPE); 
     list.setVisibleRowCount(8); 
     JScrollPane scrollPane = new JScrollPane(list); 
     scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); 
     add(scrollPane); 
    } 

    public void addItem(String item) { 
     listModel.addElement(item); 
    } 
} 

class View2 extends JPanel { 
    private View1 view1; 
    private JTextField textField = new JTextField(10); 

    public View2(View1 view1) { 
     Action addItemAction = new AddItemAction(); 
     this.view1 = view1; 
     add(textField); 
     add(new JButton(addItemAction)); 
     textField.setAction(addItemAction); 
    } 

    private class AddItemAction extends AbstractAction { 
     public AddItemAction() { 
     super("Add Item"); 
     putValue(MNEMONIC_KEY, KeyEvent.VK_A); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     view1.addItem(textField.getText()); 
     textField.selectAll(); 
     } 
    } 
} 
+0

Кроме того, 'ActionListener' обрабатывает (Swing)' ActionEvent', но вам, вероятно, нужно что-то сделать для остальных. Не добавляйте ссылки на класс, чтобы вы могли легко получить доступ к его методам. Вместо этого вы можете использовать другие механизмы (шаблоны проектирования), чтобы помочь вызвать метод для других классов, когда происходит событие GUI. – hfontanez

+1

@hfontanez: Я согласен, лучше пойти M-V-C, если это возможно. –

+0

Я не уверен, что вы имеете в виду с первым пунктом. Как вы имеете в виду ссылку? Это единственный способ, которым я планирую это сделать, так как я должен завершить его на завтра, а его изменение теперь будет кошмаром ?! А также что такое MVC? ха-ха. Все еще довольно нова для Java. – user3223921