Search code examples
javaswingjbuttonactionlistener

Implementing an ActionListener to a JMenuItem


in my code I used ActionListener before for an JButton. I tried to enhance my program with some menubars I learned. So, I tired to implement an ActionListener to my JButtonItem but it won't respond. Whatever I write it does not respond, just the error I get.

I want that my JButtonItem versItem use an ActionListener to open e.g. an system.out.print or an new text field.

*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package yttut;

// Einbindung der Bibs

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
/**
 *
 * @author tom
 */
public class GuiTaschenrechner extends JFrame implements ActionListener { // Klasse benutzt JFrame
    
    JMenuBar menuBar;
    JMenu fileMenu;
    JMenu testMenu;
    JMenuItem versItem;
    
    JLabel labelOperand1; //Schildchen
    JLabel labelOperand2;
    JLabel labelOperator;
    
    JTextField fieldOperand1; // Normale Textfelder 
    JTextField fieldOperand2;
    
    JButton buttonRechnen; // Normaler Button
    
    String operator; // Normale Zuweisung
    public GuiTaschenrechner(String titel, String operator){
     
    this.operator = operator;    
       
    setTitle(titel); // Titel des Fensters
    setDefaultCloseOperation(EXIT_ON_CLOSE); // Was passiert wenn man das Fenster schließt
    
    setLayout(new FlowLayout()); // Ordnet die Komponten auf dem Interface
    
    setSize(350,150); // Größe des Fensters
    setResizable(true); // Ob der Benutzer das Fenster vergrößern kann
    
    
     
    
    initComponents(); // Methodenaufruf
    
    // WICHTIG!: Nach dem Methodenaufruf machen
    
    menuBar.add(fileMenu);
    menuBar.add(testMenu);
    testMenu.add(versItem);
   
    add(labelOperand1); //Aufruf der einzelnen Komponenten
    add(labelOperand2);
    add(fieldOperand1);
    add(labelOperator);
    add(fieldOperand2);
    add(buttonRechnen);
    
    setVisible(true); // Fenster wird sichtbar gemacht
    setLocationRelativeTo(null); // Wo das Fenster gespawnt wird
    
    
    
    }
    
    private void initComponents(){
        
    
     
    
    labelOperand1 = new JLabel("1.Summand"); //Was auf dem Label stehen soll
    labelOperand2 = new JLabel("2.Summand");  
    labelOperator = new JLabel(operator);
    
    fieldOperand1 = new JTextField(8); // Wie groß das Textfield sein soll
    fieldOperand2 = new JTextField(8);
    
    
    buttonRechnen = new JButton("Rechen!"); // Was auf dem Button stehen soll
    buttonRechnen.addActionListener(this); // Hört dem Button zu
    
    
    
    menuBar = new JMenuBar();
    
    setJMenuBar( menuBar);
    
    fileMenu = new JMenu("Datei");
    testMenu = new JMenu("Testing...");
    fileMenu.addActionListener(this);
    versItem = new JMenuItem("Versionsansicht");
    versItem.addActionListener(this);
    
    }

    /**
     *
     * @param e
     */
    @Override
    public void actionPerformed(ActionEvent e) { //Override aus implements ActionListener
        
        
        int op1 = Integer.parseInt(fieldOperand1.getText()); // get Text gibt String daher umwandlung nach int
        int op2 = Integer.parseInt(fieldOperand2.getText());
        
        int ergebnis;
        
        if(e.getSource().equals(versItem)){
            
            System.out.println("Dsa");
        }
        
         if(e.getSource()==fileMenu){
            
            System.out.println("Dsa");
        }
        
        
        
        if(operator.equals("+")){
            ergebnis = op1 + op2;
            
        }else if(operator.equals("-")){
            ergebnis = op1 - op2;
            
        }else if(operator.equals("*")){
            ergebnis = op1 * op2;
            
        }else if(operator.equals("/")){
            ergebnis = op1 / op2;
            
        }else{
            System.out.println("ERROR");
            ergebnis = Integer.MAX_VALUE;
        }
    
        // Ergbnisausgabe in einer Dialogbox
         JOptionPane.showMessageDialog(null, "Ergebnis: " + ergebnis,"BERECHNET",JOptionPane.INFORMATION_MESSAGE);
         
         fieldOperand1.setText(""); // Nach Ergebnisausgabe werden hier die Felder wieder leer gemaacht
         fieldOperand2.setText("");
            
                 }
        
    }
    



Solution

  • If I understand correctly, what you're trying to do is:

    When the menuItem is pressed, do something (System.out.println) like printing ("Dsa") and when the button is pressed, do somethign else (the calculations).

    Whatever I write it does not respond, just the error I get.

    But you were getting an error and Dsa printed at the very bottom

    And I think the error you were getting was something like this:

    Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: ""
        at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
        at java.base/java.lang.Integer.parseInt(Integer.java:662)
        at java.base/java.lang.Integer.parseInt(Integer.java:770)
    

    And if you scrolled to the bottom of the error you'd find Dsa on your console.

    The error above means you didn't write something into the fields, and because you were executing the calculations every time you entered the ActionListener this was happening because the text fields were empty.

    You were on the right track with this:

    if(e.getSource().equals(versItem)){
            
        System.out.println("Dsa");
    }
        
    if(e.getSource()==fileMenu){
            
        System.out.println("Dsa");
    }
    

    However you were asking for the fileMenu and versItem but never for your button, and actually the fileMenu one isn't really needed, so you could change things this way:

    @Override
    public void actionPerformed(ActionEvent e) { // Override aus implements ActionListener
        if (e.getSource().equals(versItem)) {
            System.out.println("Dsa");
        } else if (e.getSource().equals(buttonRechnen)) {
            doOperation();
        }
    }
    

    Where you move all the logic of the operations out of that method, this way it's easier to understand what's happening.

    And your doOperation method could look like this with some improvements with a switch instead (You could move the operations to an enum if you wanted to):

    private void doOperation() {
        int ergebnis = 0;
        int op1 = Integer.parseInt(fieldOperand1.getText()); // get Text gibt String daher umwandlung nach int
        int op2 = Integer.parseInt(fieldOperand2.getText());
        
        switch(operator) {
        case "+":
            ergebnis = op1 + op2;
            break;
        case "-":
            ergebnis = op1 - op2;
            break;
        case "*":
            ergebnis = op1 * op2;
            break;
        case "/":
            ergebnis = op1 / op2;
            break;
        default:
            System.out.println("Invalid operator");
            break;
        }
        // Ergbnisausgabe in einer Dialogbox
        JOptionPane.showMessageDialog(null, "Ergebnis: " + ergebnis, "BERECHNET", JOptionPane.INFORMATION_MESSAGE);
    
        fieldOperand1.setText(""); // Nach Ergebnisausgabe werden hier die Felder wieder leer gemaacht
        fieldOperand2.setText("");
    }
    

    Now everytime you click on the versItem you'll print Dsa to the console and continue doing your operations when pressing the button.

    If this wasn't your problem, let me know so that I can edit and improve the answer accordingly