site logo
  • Կայքի մասին
  • Ծրագրավորում
  • Ժեշտ
  • Անվտանգություն
  • Հարց ու Պատասխան (ՀուՊ)
Սեպտեմբեր 22, 2012  |  By armenbadal In

Ինչպե՞ս Java ծրագիրն ընդլայնել սկրիպտերով

Ներածություն

Իմ նպատակն է ցուցադրել, թե ինչես կարելի է Java լեզվով գրված ծրագրի ֆունկցիոնալությունն ընդլայնել սկրիպտային մեխանիզմի միջոցով՝ օգտագործողին տալով գործողությունների մեծ ազատություն: Որպես մոդել դիտարկում եմ JPanel-ի վրա հատվածների միջոցով տարբեր երկրաչափական պատկերների ստացման խնդիրը:

Եթե չօգտագործվեր սկրիպտային մեխանիզմը, ապա կամայական պատկեր ստանալու համար կան հետևյալ եղանակները.

  • Նախատեսել ստանդարտ գործողություններ, որոնք օգտագործողին մատչելի կլինեն որպես մենյուի կամ գործիքների տողի գործողություններ: Այս դեպքում օգտագործողը ստիպված կլինի մկնիկով բազմաթիվ գործողություններ կատարել, իսկ կառուցված պատկերի համար մեծ ճշտություն ստանալն էլ դժվար կլինի:
  • Նախագծել մի նոր, հատկապես տվյալ խնդիրը սպասարկելու համար նախատեսված լեզու, որն իր հրամանների համակարգում կունենա գրաֆիկական պրիմիտիվներ (տվյալ դեպքում՝ հատված) պատկերելու հրամաններ: Այս դեպքում էլ ստիպվալ կլինենք գրաֆիկական պրիմիտիվներից բացի իրականացնել ալգորիթմներ կազմելու համար անգրաժեշտ հրահանգները՝ պայման, ցիկլ, ֆւնկցիաներ կամ պրոցեդուրաներ և այլն:

Իմ կարծիքով, նպատակահարմար է Java-ի գրաֆիկական միջոցներով (այս դեպքում՝ Swing) իրականացնել տրված սկզբնակետի ու վերջնակետի կոորդինատներ ունեցող հատված պատկերման կոդը (ես դա արել եմ JPanel-ի ընդլայնմամբ), ապա սկրիպտային լեզվով (այս դեպքում՝ Armed Bear Common Lisp) իրականացնել մյուս բոլոր անհրաժեշտ գրաֆիկական հրամանները:

Հատվածների պատկերում

Հատվածները պատկերելու համար ընդլայնվել է JPanel դասը: Եթե խոսենք ավելի հասկանալի տերմիններով, ապա paintComponent մեթոդում իրականացված է գրաֆիկական հրամանների վիրտուալ մեքենա, որը կատարում է երկու հրաման՝ հատվածի պատկերում և գույնի ընտրություն:

package jrobot;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class RobotField extends JPanel {
    /**/
    private CommandList commands = null;

    /**/
    public RobotField()
    {
        setBackground(Color.white);
    }

    /**/
    public void draw(CommandList com)
    {
        commands = com;
        repaint();
    }

    /**/
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if( null == commands ) return;
        int index = 0;
        while( index < commands.size() ) {
            if( commands.get(index) == CommandList.O_LINE ) {
                g.drawLine(commands.get(index+1), commands.get(index+2), commands.get(index+3), commands.get(index+4));
                index += 5;
            }
            else if( commands.get(index) == CommandList.O_COLOR ) {
                g.setColor(new Color(commands.get(index+1), commands.get(index+2), commands.get(index+3)));
                index += 4;
            }
        }
    }
}

paintComponent մեթոդը ենթադրում է, որ commands ցուցակում հանդիպող թվերից առաջինը գործողությանա կոդն է, իսկ նրան հաջորդողներն արգումենտներն են՝ համապատասխան քանակով: Այս իրականացման մեջ հատվածի (O_LINE) գործողությունն օգտագործում է իրեն հաջորդող չորս թվերը, իսկ գույնի (O_COLOR) ընտրման գործողությունը՝ իրեն հաջորդող երեք թվերը:

commands-ը CommandList դասին պատկանող օբյեկտ է: Այդ դասը ArrayList<Integer> ցուցակի ընդլայնումն է, որտեղ ավելացրած են երկու մեթոդներ՝ addLine և addColor, պարզապես աշխատանքի հարմարության համար:

package jrobot;

import java.util.ArrayList;

public class CommandList extends ArrayList<Integer> {
    public static final int O_LINE = 0x01;
    public static final int O_COLOR = 0x02;

    /**/
    public void addLine(int x0, int y0, int x1, int y1)
    {
        add(Integer.valueOf(O_LINE));
        add(Integer.valueOf(x0));
        add(Integer.valueOf(y0));
        add(Integer.valueOf(x1));
        add(Integer.valueOf(y1));
    }

    /**/
    public void addColor(int r, int g, int b)
    {
        add(Integer.valueOf(O_COLOR));
        add(Integer.valueOf(r));
        add(Integer.valueOf(g));
        add(Integer.valueOf(b));
    }
}

Ահա այսքանը բավարար է հատվածների պատկերումն ապահովելու համար:

JSR-223 մեխանիզմի օգտագործումը

JSR-223 մեխանիզմը հնարավորություն է տալիս Java ծրագրերում օգտագործել ստրիպտային լեզուների ամբողջ հզորությունը: Բնականաբար այստեղ ես չեմ ներկայացնի այդ մեխանիզմի բոլոր հնարավորությունները, այլ կպատմեմ, թե ինչպես է օգտագործվել Armed Bear Common Lisp (ABCL) լեզուն գրաֆիկական հրամաններ ստեղծելու համար:

ABCL-ի ինտերպրետատորը ծրագրում օգտագործելու համար MainWindow դասում նախատեսված է հետևյալը.

private ScriptEngine engine = null;

engine օբյեկտը ստեղծվում է createInterpreter մեթոդով, որը նախ ստեղծում է Lisp-ի ինտերպրետատորը, ապա բեռնում է համակարգի ինիցալիզացիայի drawersetup.lisp ֆայլը (այդ ֆայլի մասին՝ ստորև).

private void createInterpreter()
{
    ScriptEngineManager factory = new ScriptEngineManager();
    engine = factory.getEngineByName("ABCL");
    try {
        engine.eval(new FileReader("drawersetup.lisp"));
    }
    catch(Exception ex) { 
        System.err.println(ex.getMessage()); 
    }
}

ScriptEngineManager դասի getEngineByName մեթոդը ստեղծում է տրված անունով լեզվի ինտերպրետատոր այն դեպքում, երբ համակարգին հասանելի է համապատասխան լեզվի իրականացման jar ֆայլը. տվյալ դեպքում դա abcl.jar ֆայլն է:

Երբ օգտագործողը սկրիպտի համար նախատեսված տեքստային դաշտում հավաքում է Lisp ծրագիրը, կամ բացում է նախապես պատրաստված ֆայլը, և ընտրում է Script մենյուի Draw հրամանը, ապա կատարվում է runLispScript մեթոդը, որը.
  1. ստեղծում է նոր CommandList օբյեկտ,
  2. այդ օբյեկտը հասանելի է դառնում Lisp-ի ինտերպրետատորին *commands* անունով,
  3. ինտերպրետատորին կատարման է տալիս սկրիպտի դաշտի պարունակությունը,
  4. JPanel-ի նմուշին է փոխանցվում արժեքներով լցված ցուցակը:

private void runLispScript()

{
    CommandList test = new CommandList();
    engine.put("*commands*", test);
    try { 
        engine.eval(scriptCode.getText());
    }
    catch(Exception ex) { 
        JOptionPane.showMessageDialog(this, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
    }
    robotField.draw(test);
}

Գրաֆիկական հրամանները Common Lisp լեզվով

Քանի որ վիրտուալ մեքենան “հասկանում” է միայն հատվածի պատկերման և գույնի ընտրության հրամանները, ապա մնացած ամբողջ աշխատանքը, այն է՝ տարատեսակ գրաֆիկական նրամանների կաուցումը, պետք իրականացնել Lisp-ով:
drawersetup.lisp ֆայլում սահմանված են ստրուկտուրաներ, ֆունկցիաներ ու մակրոսներ, որոնք օգտագործողին հնարավորություն են տալիս երկրաչափական (գրաֆիկական) պատկերներ կառուցել աշխատանքի համար ավելի հարմար տեսքով: Այն էլեմենտները, որոնք կողմնակի ազդեցություն չեն թողնում, սահմանված են որպես ֆունկցիաներ, մյուսները՝ որպես մակրոսներ:
Եվ այսպես, նախ սահմանենք դեկարտյան կետը մոդելավորող ֆունկցիան.
(defstruct point x y)
+start-point+ հաստատունով նշենք (0,0) կետը.
(defconstant +start-point+ (make-point :x 0 :y 0))
Սահմանենք նաև երկու ֆունկցիաներ, որոնցից առաջինը վերադարձնում է տրված կետի շեղումը ըստ dx և dy դեկարտյան տարբերության,
(defun point-translate-cart (p dx dy)
  (make-point :x (+ dx (point-x p)) :y (+ dy (point-y p))))
Իսկ մյուսը վերադարձնում է տրված կետի շեղումը ըստ angle և dist բևեռային տարբերության (անկյունները տրվում են աստիճաններով).
(defun point-translate-polar (pos angle dist)
  (let* ((rad (/ (* pi angle) 180))
  (dx (truncate (* dist (cos rad))))
  (dy (truncate (* dist (sin rad)))))
  (point-translate-cart pos dx (* -1 dy))))
Գույնի մոդելը պարզապես կարմիր, կանաչ և կապույտ գույների միավորումն է.
(defstruct color red green blue)
(defconstant +black+ (make-color :red 0 :green 0 :blue 0))
(defconstant +white+ (make-color :red 255 :green 255 :blue 255))
Հատվածի մոդելը ներկայացված է նրա ծայրակետերի կոորդինատներով
(defstruct segment begin end)
segment-from-turn-go ֆունկցիան վերադարձնում է մի հատված, որի սկզբնակետը տրված է, իսկ վերջնակետը համընկնում է սկզբնակետը տրված անկյամբ ու հեռավորությամբ տեղաշարժած կետին.
(defun segment-from-turn-go (pos ang dis)
  (make-segment :begin pos :end (point-translate-polar pos ang dis)))

;;;
;;; Position and direction.
;;;
(defvar *position* +start-point+)
(defvar *direction* 0)

;;;
;;; Drawing commands (predefined primitives).
;;;

(defmacro reset ()
  `(progn (setf *position* +start-point+)
   (setf *direction* 0)))

(defmacro pen-up ()
  `(jcall "addColor" *commands* 255 255 255))

(defmacro pen-down ()
  `(jcall "addColor" *commands* 0 0 0))

(defmacro set-angle (alpha)
  `(setf *direction* ,alpha))

(defmacro turn (alpha)
  `(set-angle (rem (+ *direction* ,alpha) 360)))

(defmacro jump-to (nx ny)
  `(setf *position* (make-point :x ,nx :y ,ny)))

(defmacro move (dist)
  `(let* ((seg (segment-from-turn-go *position* *direction* ,dist))
          (be (segment-begin seg))
          (en (segment-end seg)))
     (jcall "addLine" *commands* (point-x be) (point-y be) (point-x en) (point-y en))
     (setf *position* en)))

(defmacro turn-and-go (ang dis)
  `(progn (set-angle ,ang) (move ,dis)))
(defmacro right (dist)
  `(turn-and-go 0 ,dist))
(defmacro left (dist)
  `(turn-and-go 180 ,dist))
(defmacro up (dist)
  `(turn-and-go 90 ,dist))
(defmacro down (dist)
  `(turn-and-go 270 ,dist))
(defmacro down-right (dist)
  `(turn-and-go 315 ,dist))
(defmacro up-right (dist)
  `(turn-and-go 45 ,dist))
(defmacro down-left (dist)
  `(turn-and-go 225 ,dist))
(defmacro up-left (dist)
  `(turn-and-go 135 ,dist))
Ինչպե՞ս Java ծրագիրն ընդլայնել սկրիպտերով, 10.0 out of 10 based on 6 ratings
Common Lisp Java Java JSR-223 Lisp և Common Lisp scripting
Previous StoryՊատմություն այն մասին, թե ինչպես ես PROLOG լեզվով գրեցի մի պարզ կոմպիլյատոր
Next StoryCisco NAT+encapsulation dot1Q

Comments: no replies

Join in: leave your comment Cancel Reply

(will not be shared)

Որոնում

Նշագրեր

*Nix-եր (18) android (17) C++ (19) C և C++ (27) Excel (10) html (10) Network Administration (16) System Administration (28) Windows 7 (14) Ալգորիթմներ (15) Անվտանգություն (29) ԳՆՈՒ/Լինուքս (16) Թեյնիկներին (57) Ժեշտ (44) Լակոնիկ (21) Լինուքս/Յունիքս հրամաններ (29) Լուսանկարչություն և մշակում (15) Խելախոսներ (19) Ծրագրավորման լեզուներ (16) Ծրագրավորում (64) Ծրագրեր (48) Հայականացում (28) Հումոր (11) Ուսումնական նյութեր (34) Սոցցանցային Հմտություններ (19) Վեբ (25) Վերլուծություն (10) Վորդպրես (21) ՏՏ և փիլիսոփայություն (21) Տվյալների բազաներ (12) Օպերացիոն համակարգեր (27) Օֆիսային ծրագրեր (22) անդրոիդ (16) բաշ (10) ինտերնետ (11) խելախոսներ (13) համացանց (15) հայատառ (10) հայերեն (11) հայերեն ստեղնաշար (11) հայկական սոֆթ (11) ստեղնաշար (10) սքրիփթ (14) վինդոուս (12) տեսանյութ (23)
Copyright ©2017 ThemeFuse. All Rights Reserved