Kurs Java Podstawy - rozszerzony

Wywołanie kodu javascript z poziomu Javy

Wielu z was na pewno miało już do czynienia nie tylko z programowaniem w Javie, ale także z technologiami webowymi i tworzycie strony. Na pewno niektórzy z was wykorzystywali już różne skrypty w JavaScripcie i czasami brakuje wam niektórych funkcji, które można tam wykorzystać. W tej lekcji przekonamy się, że w Javie istnieje mechanizm pozwalający wykonywać kod JavaScript, pokażemy też oczywiście przykład - kalkulator i zobaczymy jak bardzo omawiane rozwiązanie ułatwia w tym przypadku program.

1. Co to jest JavaScript

2. Co to jest ScriptEngine

3. Przykład - kalkulator

 

1. Co to jest JavaScript

Przede wszystkim dla tych, którzy nie odróżniają Javy od JavaScript - są to dwa zupełnie różne języki programowania o różnych zastosowaniach i składni i nie należy ich mylić. JavaScript jest najczęściej wykorzystywany jako uzupełnienie stron internetowych - często można się z nim spotkać na stronach, gdzie jakiś content ładowany jest dynamicznie bez przeładowania strony. Inne wykorzystanie to wszelkie ficzery - animacje menu, czy walidacja formularzy "w locie". Więcej nie będę opisywał - zainteresowani mogą poczytać na wikipedii.

2. Co to jest ScriptEngine

Jest to silnik wprowadzony w Javie 6, który pozwala na wykonywanie skryptów napisanych w języku JavaScript (a także EcmaScript bazującym na JS). Mogłoby się wydawać, że to raczej bezużyteczne narzędzie, bo w końcu po co pisać coś w JavaScript, skoro można to napisać po prostu w Javie - przecież będzie to wolniejsze i na pewno da się to też napisać w czystej Javie. Jak się okaże za chwilę są jednak pewne ciekawe zastosowania, gdzie niesamowicie upraszcza nam to pracę. (Sam nie jestem ekspertem od JS, ale na poniższym przykładzie widać jak ułatwia życie).

3. Przykład - kalkulator

 CalculatorPanel.java

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class CalculatorPanel extends JPanel {
    private JTextArea resultArea;

    public CalculatorPanel() {
        JPanel centralPanel = new JPanel();
        centralPanel.setLayout(new GridLayout(4, 3));
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new GridLayout(4, 1));
        ActionListener listener = new CalcAction();

        addButton("1", listener, centralPanel);
        addButton("2", listener, centralPanel);
        addButton("3", listener, centralPanel);
        addButton("4", listener, centralPanel);
        addButton("5", listener, centralPanel);
        addButton("6", listener, centralPanel);
        addButton("7", listener, centralPanel);
        addButton("8", listener, centralPanel);
        addButton("9", listener, centralPanel);
        addButton("0", listener, centralPanel);
        addButton(".", listener, centralPanel);
        addButton("=", listener, centralPanel);

        addButton("+", listener, rightPanel);
        addButton("-", listener, rightPanel);
        addButton("*", listener, rightPanel);
        addButton("/", listener, rightPanel);

        resultArea = new JTextArea();
        resultArea.setEditable(false);

        this.setLayout(new BorderLayout());
        this.add(resultArea, BorderLayout.NORTH);
        this.add(centralPanel, BorderLayout.CENTER);
        this.add(rightPanel, BorderLayout.EAST);
    }

    private void addButton(String label, ActionListener listener, JPanel panel) {
        JButton button = new JButton(label);
        button.addActionListener(listener);
        panel.add(button);
    }

    private class CalcAction implements ActionListener {
        ScriptEngineManager manager;
        ScriptEngine engine;

        public CalcAction() {
            manager = new ScriptEngineManager();
            engine = manager.getEngineByName("js");
        }

        @Override
        public void actionPerformed(ActionEvent action) {
            String click = action.getActionCommand();
            String resultString = null;
            if ("=".equals(click)) {
                try {
                    Double eval = (Double) engine.eval(resultArea.getText());
                    resultString = eval.toString();
                } catch (ScriptException e) {
                    e.printStackTrace();
                }
            } else {
                resultString = resultArea.getText() + click;
            }
            resultArea.setText(resultString);
        }
    }

}

CalcFrame.java

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class CalcFrame extends JFrame {
    JPanel calcPanel;

    public CalcFrame() {
        calcPanel = new CalculatorPanel();
        this.add(calcPanel);
        setPreferredSize(new Dimension(200, 200));
        pack();
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

Main.java

import java.awt.EventQueue;

public class Main {
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new CalcFrame();
            }
        });
    }
}

Prosty kalkulator w javie z użyciem ScriptEngineCała magia odbywa się praktycznie w 1 z wymienionych klas. Tworzymy tam wszystkie niezbędne przyciski i główny panel programu. Po wciśnięciu jakiegokolwiek przycisku innego od "=" sekwencja działań jest wprowadzana do okienka obliczeń. Jeśli wciskany jest jednak przycisk równości wywoływany jest skrypt JS, który w rezultacie zwraca nam wartość Double z obliczonym wynikiem. Oczywiście należałoby w tym miejscu również zapewnić pewną niezawodność, gdy np. ktoś nie wprowadzi poprawnego ciągu działań (np. 2+5*) - ale to zostawiam wam.

Niektórym w tym miejscu może się wydawać, że to żaden problem napisać w Javie taki prosty kalkulator. O ile jeśli chcemy stworzyć kalkulator, który może wykonywać czynności tylko sekwencyjnie, czyli:

wprowadzamy 2+2 - dostajemy wynik

wynik mnożymy *2 i otrzymujemy wynik

nie jest wcale trudne, tak już stworzenie czegoś co będzie potrafiło rozwiązać wprowadzone działanie 2+2*2 mocno się komplikuje, ponieważ musimy rozebrać działanie na czynniki pierwsze, a biorąc pod uwagę kolejność działań to ilość kodu, którą musimy napisać w porównaniu do powyższego rozwiązania jest bardzo duża.

Komentarze

Robert

W którym dokładnie miejscu jest wywoływany ten javascript i jak on wygląda(kod)? Został osobno napisany czy jest to gotowy do użycia w bibliotekach javy(?)? Bo nie ogarniam tego. Chodzi mi o to czy żeby efektywnie programować w javie należałoby się nauczyć również javascriptu, żeby sobie ułatwiać zadanie?

Szef

Nie ma żadnego kodu ;) JavaScript po prostu rozwiązuje to działanie, to tak jakbyś je wypisał w System.out.print, tyle, że w Javie nie ma czegoś takiego jak eval :)

Piotr Li

Mam pewien problem bo z kolegom chcemy zrobic gre, ale on nie zna javy tylko javascrypt a ja na odwrut. Pytanie brzmi, czy ja mogę wywoływać funkcję z jego kodu JS i czy on może wywoływać metody z moich class.

Lolo

1.odwrót
2.Jak pokazuje ta lekcja możesz wywołać skrypt js, w drugą stronę też jest to raczej możliwe.
docstore.mik.ua/orelly/webprog/jscript/ch22_03.htm
3.Dlaczego nie nauczycie się Ty JavyScriptu, a kolega Javy? Możecie sobie nawzajem pomagać w nauce przecież. Ty znając Javę możesz jemu tłumaczyć rzeczy z którymi będzie miał problemy a on Tobie zawiłości JavyScriptu.
4. Jeśli można wiedzieć cóż to za grę planujecie?