Kalkulator - zdarzenie KeyReleased

Dyskusje na temat Javy.
Piotr

Kalkulator - zdarzenie KeyReleased

Post przez Piotr »

Witam

Aplikacja: prosty kalkulator który dodaje odejmuje mnoży dzieli itp.
Jeśli się klika w odpowiednie buttony wszytko działa jak trzeba. Chciałbym żeby działało wtedy kiedy naciskam klawisze cyferek na klawiaturze. Problem polega na tym, że nie potrafię wywołać metody ze słuchacza ActionListener w odpowiedniej metodzie KeyListener. Proszę o pomoc.

Pozdrawiam i z góry dziękuję za pomoc.
Piotr M.

Mój kod:

Code: Zaznacz cały

package kalkulator;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main
{

    public static void main(String[] args)
    {
        CalcFrame frame = new CalcFrame();
        frame.initComponets();
    }
}
/*
 *      Tworzy ramke kalkulatora i jego panel
 *      ustawia właściwości ramki
 */

class CalcFrame extends JFrame
{
    CalcFrame()
    {
        this.setTitle("Kalkulator");
        this.setBounds(100, 100, 200, 200);
        CalcPanel panel = new CalcPanel();
        this.add(panel);
        this.pack();
    }
    public void initComponets()
    {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}
/*
 *      Dodaje do panelu w ramce wszystkie
 *      komponenty jednoczesnie obsługując zdarzenia
 */
class CalcPanel extends JPanel
{
    CalcPanel()
    {
        this.setLayout(new BorderLayout());

        wynik = 0;
        lastCommand = "=";
        start = true;

        // Tworzy wyswetlacz i ustawia go na górze ramki

        display = new JButton("0");
        display.setEnabled(false);
        this.add(display, BorderLayout.NORTH);
        /*
         *      Inicjuje klasy dla sluchaczy
         *      ponizej sa definicje tych klass
         */
        ActionListener insert = new InsertAction();
        ActionListener command = new CommandAction();
        ActionListener delete = new DeleteAction();

        /*
         *
         */

        panel = new JPanel();
        panel.setLayout(new GridLayout(4, 5, 6, 6));

        addButton ("7", insert);
        addButton ("8", insert);
        addButton ("9", insert);
        addButton ("/", command);
        addButton ("<-", delete);

        addButton ("4", insert);
        addButton ("5", insert);
        addButton ("6", insert);
        addButton ("*", command);
        addButton ("C", delete);

        addButton ("1", insert);
        addButton ("2", insert);
        addButton ("3", insert);
        addButton ("-", command);
        addButton ("sqt", command);

        addButton ("0", insert);
        addButton (".", insert);
        addButton ("=", command);
        addButton ("+", command);
        addButton ("^x", command);

        add(panel, BorderLayout.CENTER);
    }

    /*
     *      Metoda dodajaca przyciski i obsluge zdarzenia
     */
    private void addButton (String label, ActionListener lisner)
    {
        JButton buton = new JButton(label);
        buton.addActionListener(lisner);
        buton.addKeyListener(new KeyAdapter()
        {
            @Override
            public void keyTyped(KeyEvent e)
            {
                if (e.getKeyChar() == 1)
                {
                    
                }
            }
            @Override
            public void keyPressed(KeyEvent e)
            {
                if (e.getKeyCode() == KeyEvent.VK_1)
                {
			// ??
                }
                if (e.getKeyCode() == KeyEvent.VK_2)
                {
			// ??
                }
            }
            @Override
            public void keyReleased(KeyEvent e)
            {
			// ??
            }
        });

        panel.add(buton);
    }
    /*
     *      Klasa obslugujaca zdarzenia imput, command i delete
     *      Imput zdarzenie dopisania liczby do wyswietlania
     *      Command zdarzenie wykonania dzialania matematycznego
     */
    private class InsertAction implements ActionListener
    {
	// Może do istniejącego lisnera da sie dopisac zeby 
	// słuchał rownież zdarzenia z KeyListener?

        public void actionPerformed(ActionEvent e)
        {
            String imput = e.getActionCommand();
            if (start)
            {
                display.setText("");
                start = false;
            }
            display.setText(display.getText() + imput);
        }
    }
    private class DeleteAction implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            String imput = e.getActionCommand();
            String p = "";
            if (imput.equals("<-"))
            {
                imput = display.getText();
                display.setText("");
                for (int i = 0; i <= imput.length()-2; i++)
                {
                    display.setText(display.getText() + imput.charAt(i));
                }
            }
            if (imput.equals("C"))
            {
                    display.setText("0");
            }
        }
    }
    private class CommandAction implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            String command = e.getActionCommand();
            if (start)
            {
                if (command.equals("-"))
                {
                    display.setText(command);
                    start = false;
                }
                else lastCommand = command;
            }
            else
            {
               calculate(Double.parseDouble(display.getText()), command);
               lastCommand = command;
               start = true;
            }
        }
    }
    /*
     *      Metoda wykonujaca polecenia matematyczne
     */
    public void calculate(double x, String command)
    {
        String com = command;
        if (lastCommand.equals("+"))
        {
            wynik += x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if (lastCommand.equals("-"))
        {
            wynik -= x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if (lastCommand.equals("*"))
        {
            wynik *= x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if (lastCommand.equals("/"))
        {
            wynik /= x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if ((lastCommand.equals("^x")) && (com.equals("=")))
        {
	    wynik = Math.pow(wynik, x);
            System.out.println(wynik + "  " + lastCommand + " " + x);
        }
        if (lastCommand.equals("="))
        {
            wynik = x;
            System.out.println(wynik + "  " + lastCommand);
        };
        display.setText("" + wynik);
    }

    private JButton display;
    private JPanel panel;
    private double wynik;
    private String lastCommand;
    private boolean start;
}
Morfidon
Administrator
Administrator
Posty: 1332
Dołączył(a): wtorek, 5 sierpnia 2008, 21:48
Contact:

Re: Zdarzenia

Post przez Morfidon »

Witam,

Możesz to zrobić np. tak:

Code: Zaznacz cały

package kalkulator;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;

public class Main
{

    public static void main(String[] args)
    {
        CalcFrame frame = new CalcFrame();
        frame.initComponets();
    }
}
/*
*      Tworzy ramke kalkulatora i jego panel
*      ustawia właściwości ramki
*/

class CalcFrame extends JFrame
{
    CalcFrame()
    {
        this.setTitle("Kalkulator");
        this.setBounds(100, 100, 200, 200);
        CalcPanel panel = new CalcPanel();
        this.add(panel);
        this.pack();
    }
    public void initComponets()
    {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}
/*
*      Dodaje do panelu w ramce wszystkie
*      komponenty jednoczesnie obsługując zdarzenia
*/
class CalcPanel extends JPanel
{
    CalcPanel()
    {
        this.setLayout(new BorderLayout());

        wynik = 0;
        lastCommand = "=";
        start = true;

        // Tworzy wyswetlacz i ustawia go na górze ramki

        display = new JButton("0");
        display.setEnabled(false);
        this.add(display, BorderLayout.NORTH);
        /*
         *      Inicjuje klasy dla sluchaczy
         *      ponizej sa definicje tych klass
         */
        ActionListener insert = new InsertAction();
        ActionListener command = new CommandAction();
        ActionListener delete = new DeleteAction();

        /*
         *
         */

        panel = new JPanel();
        panel.setLayout(new GridLayout(4, 5, 6, 6));
        
        addButton ("7", insert);
        addButton ("8", insert);
        addButton ("9", insert);
        addButton ("/", command);
        addButton ("<-", delete);

        addButton ("4", insert);
        addButton ("5", insert);
        addButton ("6", insert);
        addButton ("*", command);
        addButton ("C", delete);

        addButton ("1", insert);
        addButton ("2", insert);
        addButton ("3", insert);
        addButton ("-", command);
        addButton ("sqt", command);

        addButton ("0", insert);
        addButton (".", insert);
        addButton ("=", command);
        addButton ("+", command);
        addButton ("^x", command);

        add(panel, BorderLayout.CENTER);
        
        KeyAdapter adapter = new KeyAdapterImpl();
        
        panel.addKeyListener(adapter);
        
        panel.setFocusable(true);
        panel.requestFocus();
        
        
    }

    /*
     *      Metoda dodajaca przyciski i obsluge zdarzenia
     */
 
    private void addButton (String label, ActionListener lisner)
    {
        JButton buton = new JButton(label);
        buton.addActionListener(lisner);
        
        //tu zrobić jakies dodatkowe znaki w getKeyText w KeyEvent.java jest to opisane
        if (label.equals(("<-")))
            label = "Backspace";
        
        listaLabel.add(label);
        listaButton.add(buton);
        panel.add(buton);
        
       
    }
    /*
     *      Klasa obslugujaca zdarzenia imput, command i delete
     *      Imput zdarzenie dopisania liczby do wyswietlania
     *      Command zdarzenie wykonania dzialania matematycznego
     */
    private class InsertAction implements ActionListener
    {
   // Może do istniejącego lisnera da sie dopisac zeby 
   // słuchał rownież zdarzenia z KeyListener?

        public void actionPerformed(ActionEvent e)
        {
            String imput = e.getActionCommand();
            if (start)
            {
                display.setText("");
                start = false;
            }
            display.setText(display.getText() + imput);
            panel.requestFocus();
        }
    }
    private class DeleteAction implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            String imput = e.getActionCommand();
            String p = "";
            if (imput.equals("<-"))
            {
                imput = display.getText();
                display.setText("");
                for (int i = 0; i <= imput.length()-2; i++)
                {
                    display.setText(display.getText() + imput.charAt(i));
                }
            }
            if (imput.equals("C"))
            {
                    display.setText("0");
            }
             panel.requestFocus();
        }
    }
    private class CommandAction implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            String command = e.getActionCommand();
            if (start)
            {
                if (command.equals("-"))
                {
                    display.setText(command);
                    start = false;
                }
                else lastCommand = command;
            }
            else
            {
               calculate(Double.parseDouble(display.getText()), command);
               lastCommand = command;
               start = true;
            }
             panel.requestFocus();
        }
        
    }
    /*
     *      Metoda wykonujaca polecenia matematyczne
     */
    public void calculate(double x, String command)
    {
        String com = command;
        if (lastCommand.equals("+"))
        {
            wynik += x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if (lastCommand.equals("-"))
        {
            wynik -= x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if (lastCommand.equals("*"))
        {
            wynik *= x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if (lastCommand.equals("/"))
        {
            wynik /= x; System.out.println(wynik + "  " + lastCommand + " " + x);
        };
        if ((lastCommand.equals("^x")) && (com.equals("=")))
        {
       wynik = Math.pow(wynik, x);
            System.out.println(wynik + "  " + lastCommand + " " + x);
        }
        if (lastCommand.equals("="))
        {
            wynik = x;
            System.out.println(wynik + "  " + lastCommand);
        };
        display.setText("" + wynik);
    }

    private JButton display;
    private JPanel panel;
    private double wynik;
    private String lastCommand;
    private boolean start;

    private static class KeyAdapterImpl extends KeyAdapter 
    {

        private KeyAdapterImpl() 
        {

        }
        public void keyReleased(KeyEvent e) 
        {   
           
           for (int i = 0; i < listaLabel.size(); i++)
              if(KeyEvent.getKeyText(e.getKeyCode()).equals(listaLabel.get(i)))
              {
                    ((JButton)listaButton.get(i)).doClick();
                    break;
              }
        }

    }
    private static ArrayList listaLabel = new ArrayList();
    private static ArrayList listaButton = new ArrayList();
}



Zamiast dwóch ArrayList, można by też pomyśleć o mapach...

Pozdrawiam,

Arkadiusz
Piotr

Re: Kalkulator - zdarzenie KeyReleased

Post przez Piotr »

Witam

Przesłuchałem 20 lekcję z kursu Java - Tworzenie aplikacji :) zgodnie z sugestią :)

Ale czy nie dało by się zrobić jakoś szybciej tych map?

Mój kod z mapami i AbstractAction:
Kod:

Code: Zaznacz cały

package kalkulator;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Main
{

    public static void main(String[] args)
    {
        CalcFrame frame = new CalcFrame();
        frame.initComponets();
    }
}
/*
*      Tworzy ramke kalkulatora i jego panel
*      ustawia właściwości ramki
*/

class CalcFrame extends JFrame
{
    CalcFrame()
    {
        this.setTitle("Kalkulator");
        this.setBounds(100, 100, 200, 200);
        CalcPanel panel = new CalcPanel();
        this.add(panel);
        this.pack();
    }
    public void initComponets()
    {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }
}
/*
*      Dodaje do panelu w ramce wszystkie
*      komponenty jednoczesnie obsługując zdarzenia
*/
class CalcPanel extends JPanel
{
    CalcPanel()
    {
        this.setLayout(new BorderLayout());

        wynik = 0;
        lastCommand = "=";
        start = true;

        // Tworzy wyswetlacz i ustawia go na górze ramki

        display = new JButton("0");
        display.setEnabled(false);
        this.add(display, BorderLayout.NORTH);
        /*
         *      Inicjuje klasy dla sluchaczy
         *      ponizej sa definicje tych klass
         */
        panel = new JPanel();
        panel.setLayout(new GridLayout(4, 5, 6, 6));
        final Action b7 = new InsertAction ("7", "7");
        final Action b8 = new InsertAction ("8", "8");
        final Action b9 = new InsertAction ("9", "9");
        final Action bdzielenie =  new CommandAction ("/", "Dzielenie", "/");
        final Action bbackspace =  new DeleteAction ("<-", "Usuń", "Backspace");

        JButton buton7 = new JButton(b7); panel.add(buton7);
        JButton buton8 = new JButton(b8); panel.add(buton8);
        JButton buton9 = new JButton(b9); panel.add(buton9);
        JButton butondzielenie = new JButton(bdzielenie); panel.add(butondzielenie);
        JButton butonbackspace = new JButton(bbackspace); panel.add(butonbackspace);

        final Action b4 = new InsertAction ("4", "4");
        final Action b5 = new InsertAction ("5", "5");
        final Action b6 = new InsertAction ("6", "6");
        final Action bmnozenie =  new CommandAction ("*", "Mnożenie", "shift 8");
        final Action bkasuj =  new DeleteAction ("C", "Kasuj", "Escape");

        JButton buton4 = new JButton(b4); panel.add(buton4);
        JButton buton5 = new JButton(b5); panel.add(buton5);
        JButton buton6 = new JButton(b6); panel.add(buton6);
        JButton butonmnozenie = new JButton(bmnozenie); panel.add(butonmnozenie);
        JButton butonkasuj = new JButton(bkasuj); panel.add(butonkasuj);

        final Action b1 = new InsertAction ("1", "ctrl 1");
        final Action b2 = new InsertAction ("2", "2");
        final Action b3 = new InsertAction ("3", "3");
        final Action bodejmij =  new CommandAction ("-", "Odejmowanie", "-");
        final Action bpierwiastek =  new CommandAction ("sqrt", "Pierwiastek", "");

        JButton buton1 = new JButton(b1); panel.add(buton1);
        JButton buton2 = new JButton(b2); panel.add(buton2);
        JButton buton3 = new JButton(b3); panel.add(buton3);
        JButton butonodejmij = new JButton(bodejmij); panel.add(butonodejmij);
        JButton butonpierwiastek = new JButton(bpierwiastek); panel.add(butonpierwiastek);

        final Action b0 = new InsertAction ("0", "0");
        final Action bkropka = new InsertAction (".", ".");
        final Action browna = new CommandAction ("=", "Oblicza wynik", "Enter");
        final Action bdodaj =  new CommandAction ("+", "Dodawanie", "Shift +");
        final Action bpotega =  new CommandAction ("^x", "Potęga x^y", "Shift 6");

        JButton buton0 = new JButton(b0); panel.add(buton0);
        JButton butonkropka = new JButton(bkropka); panel.add(butonkropka);
        JButton butonrowna = new JButton(browna); panel.add(butonrowna);
        JButton butondodaj = new JButton(bdodaj); panel.add(butondodaj);
        JButton butonpotega = new JButton(bpotega); panel.add(butonpotega);

        add(panel, BorderLayout.CENTER);
        
        InputMap imap = panel.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
        imap.put(KeyStroke.getKeyStroke("1"), "b1");
        imap.put(KeyStroke.getKeyStroke("2"), "b2");
        imap.put(KeyStroke.getKeyStroke("3"), "b3");
        imap.put(KeyStroke.getKeyStroke("4"), "b4");
        imap.put(KeyStroke.getKeyStroke("5"), "b5");
        imap.put(KeyStroke.getKeyStroke("6"), "b6");
        imap.put(KeyStroke.getKeyStroke("7"), "b7");
        imap.put(KeyStroke.getKeyStroke("8"), "b8");
        imap.put(KeyStroke.getKeyStroke("9"), "b9");
        imap.put(KeyStroke.getKeyStroke("0"), "b0");
        imap.put(KeyStroke.getKeyStroke("typed ="), "browna");
        imap.put(KeyStroke.getKeyStroke("typed +"), "bdodaj");
        imap.put(KeyStroke.getKeyStroke("typed -"), "bodejmij");
        imap.put(KeyStroke.getKeyStroke("typed *"), "bmnozenie");
        imap.put(KeyStroke.getKeyStroke("typed /"), "bdzielenie");
        imap.put(KeyStroke.getKeyStroke("typed ="), "browna");


        // Powiązanie nazw z akcjami.
        ActionMap amap = panel.getActionMap();
        amap.put("b1", b1);
        amap.put("b2", b2);
        amap.put("b3", b3);
        amap.put("b4", b4);
        amap.put("b5", b5);
        amap.put("b6", b6);
        amap.put("b7", b7);
        amap.put("b8", b8);
        amap.put("b9", b9);
        amap.put("b0", b0);
        amap.put("browna", browna);
        amap.put("bdodaj", bdodaj);
        amap.put("bodejmij", bodejmij);
        amap.put("bmnozenie", bmnozenie);
        amap.put("bdzielenie", bdzielenie);
        amap.put("browna", browna);
        
//        panel.setFocusable(true);
//        panel.requestFocus();
    }

    /*
     *      Klasa obslugujaca zdarzenia imput, command i delete
     *      Imput zdarzenie dopisania liczby do wyswietlania
     *      Command zdarzenie wykonania dzialania matematycznego
     */
    private class InsertAction extends AbstractAction
    {
        InsertAction(String nazwa, String podpowiedz)
        {
            this.putValue(Action.NAME, nazwa);
            this.putValue(Action.SHORT_DESCRIPTION, nazwa);
            //this.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(nazwa));
           // this.putValue(Action.ACTION_COMMAND_KEY, KeyStroke.getKeyStroke(nazwa));
        }
        public void actionPerformed(ActionEvent e)
        {

            String imput = e.getActionCommand();
            System.out.println(imput);
            if (start)
            {
                display.setText("");
                start = false;
            }
            display.setText(display.getText() + imput);
            panel.requestFocus();
        }
    }
    private class DeleteAction extends AbstractAction
    {
        DeleteAction(String nazwa, String podpowiedz, String klawskrotu)
        {
            this.putValue(Action.NAME, nazwa);
            this.putValue(Action.SHORT_DESCRIPTION, podpowiedz);
            //this.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(klawskrotu));

        }
        public void actionPerformed(ActionEvent e)
        {
            String imput = e.getActionCommand();
            String p = "";
            if (imput.equals("<-"))
            {
                imput = display.getText();
                display.setText("");
                if (imput.length() != 0)
                {
                    for (int i = 0; i <= imput.length()-2; i++)
                    {
                        display.setText(display.getText() + imput.charAt(i));
                    }
                } else display.setText("0"); 


            }
            if (imput.equals("C"))
            {
                    display.setText("0");
                    start = true;
            }
             panel.requestFocus();
        }
    }
    private class CommandAction extends AbstractAction
    {
        CommandAction(String nazwa, String podpowiedz, String klawskrotu)
        {
            this.putValue(Action.NAME, nazwa);
            this.putValue(Action.SHORT_DESCRIPTION, podpowiedz);
            this.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(klawskrotu));
        }
        public void actionPerformed(ActionEvent e)
        {
            String command = e.getActionCommand();
            if (start)
            {
                if (command.equals("-"))
                {
                    display.setText(command);
                    start = false;
                }
                else lastCommand = command;
            }
            else
            {
               calculate(Double.parseDouble(display.getText()), command);
               lastCommand = command;
               start = true;
            }
             panel.requestFocus();
        }

    }
    /*
     *      Metoda wykonujaca polecenia matematyczne
     */
    @SuppressWarnings("empty-statement")
    public void calculate(double x, String command)
    {
        String com = command;
        if (lastCommand.equals("+"))  wynik += x; 
        if (lastCommand.equals("-"))  wynik -= x;
        if (lastCommand.equals("*"))  wynik *= x;
        if (lastCommand.equals("/"))  wynik /= x;;
        if ((lastCommand.equals("^x")) && (com.equals("="))) wynik = Math.pow(wynik, x);
        if (lastCommand.equals("="))  wynik = x;
        display.setText("" + wynik);
    }

    private JButton display;
    private JPanel panel;
    private double wynik;
    private String lastCommand;
    private boolean start;

}
ale czy nie da się zrobić tych map jakoś bardziej automatycznie razem z buttonami?

Pozdrawiam
Piotr
P.S. Myślę, że napisanie podobnego kalkulatora to świetne ćwiczenie po kursie Java - Tworzenie aplikacji. Prawda?
Można do niego dodać jeszcze kilka rzeczy w ramach ćwiczeń.
Morfidon
Administrator
Administrator
Posty: 1332
Dołączył(a): wtorek, 5 sierpnia 2008, 21:48
Contact:

Re: Kalkulator - zdarzenie KeyReleased

Post przez Morfidon »

Gdziekolwiek są dane, kod nie będzie jakoś specjalnie krótki, chyba że umieścisz dane zewnętrznie, czyli np. w pliku XML, lub też w bazie MySql, wtedy możesz stworzyć buttony przy pomocy jednej pętli i przy dodaniu jakiegokolwiek rekordu, nie będziesz musiał już analizować jak pisałeś kod, tylko dodajesz następny rekord do bazy danych, a pętla dodaje button automatycznie.
Piotr napisał(a):P.S. Myślę, że napisanie podobnego kalkulatora to świetne ćwiczenie po kursie Java - Tworzenie aplikacji. Prawda?
Oczywiście, jakiekolwiek pisanie, w jakimkolwiek języku jest dobrym ćwiczeniem umiejętności programowania ;)

Pozdrawiam,

Arkadiusz
Post Reply