/* * 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 fxpaintwitheffectsandtransformsforcanvas; import javafx.animation.AnimationTimer; import javafx.application.*; import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.*; import javafx.scene.layout.*; import javafx.stage.*; import javafx.scene.control.*; import javafx.geometry.*; import javafx.scene.canvas.*; import javafx.scene.paint.*; import javafx.scene.text.*; import javafx.scene.transform.*; import javafx.scene.effect.*; import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.MouseEvent; /** * * @author Admin */ public class FXPaintWithEffectsAndTransformsForCanvas extends Application{ GraphicsContext gc; GraphicsContext grc; Color colors[]={Color.RED,Color.BLUE,Color.GREEN,Color.BLACK,Color.PINK,Color.ORANGE,Color.MAGENTA}; int cidx=0; double size[]={5.0,10.0,20.0,30.0,40.0,50.0}; int ind=0; double ang=0.0; double glVal=0.4; double scFact=1.0; double transX=0.0; double transY=0.0; double ref=0.0; double re=0.0; double l=0.0; double lg=1.0; double lDc=0.0; double lSc=0.0; double bl=0.0; double bb=0.0; double rad=0.0; Glow g=new Glow(0.0); Reflection r=new Reflection(); Rotate rot=new Rotate(); Scale sc=new Scale(scFact,scFact); Translate tr=new Translate(); Bloom bL=new Bloom(); Lighting light=new Lighting(); BoxBlur Bb=new BoxBlur(); SepiaTone st=new SepiaTone(); InnerShadow inSh=new InnerShadow(rad,colors[cidx]); int mouseX = 0; int mouseY = 0; Label mou ; double mouseX2=0,mouseY2=0; Label mou2 ; AnimationTimer timer; /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } @Override @SuppressWarnings("empty-statement") public void start(Stage myStage) throws Exception { myStage.setTitle("Рисование на холсте с различными эффектами."); final Group rootNode=new Group(); Scene myScene=new Scene(rootNode,1500,700); myStage.setScene(myScene); final Canvas myC=new Canvas(800,500); Canvas can=new Canvas(400,350); can.setVisible(false); gc=myC.getGraphicsContext2D(); grc=can.getGraphicsContext2D(); Button btnCCol=new Button("Change Color"); btnCCol.setTooltip(new Tooltip("Изменяет цвет заливки элементов для холста 1")); Button btnCCol2=new Button("Изменение цвета"); btnCCol2.setTooltip(new Tooltip("Изменяет цвет заливки элементов для холста 2")); btnCCol2.setOnAction((ActionEvent ae)->{ grc.setStroke(colors[cidx]); grc.setFill(colors[cidx]); grc.setFont(new Font(20)); grc.fillText("Это второй холст.", 50,320); grc.fillRect(10, 80, 100, 20); grc.fillOval(50, 150, 200, 100); cidx++; if(cidx==colors.length)cidx=0; }); btnCCol.setOnAction((ActionEvent ae)->{ gc.setStroke(colors[cidx]); gc.setFill(colors[cidx]); gc.strokeLine(0, 0, 200, 200); gc.strokeLine(350, 100, 400, 300); gc.strokeLine(350, 100, 300, 300); gc.strokeLine(300, 300, 400, 300); gc.strokeLine(250, 250, 400, 300); gc.strokeLine(250, 250, 300, 300); gc.strokeLine(250, 250, 350, 100); gc.setFont(new Font(20)); gc.fillText("This is drawn on the canvas.", 60, 50); gc.fillRect(100, 320, 300, 40); gc.fillOval(150, 150, 200, 100); cidx++; if(cidx==colors.length)cidx=0; }); Button btnFont=new Button("Change Font"); btnFont.setTooltip(new Tooltip("Изменяет цвет заливки и размер шрифта для текста")); btnFont.setOnAction((ae)->{ gc.setFont(new Font(size[ind])); gc.setFill(colors[cidx]); gc.fillText("The Text's Effects.", 20, 100); ind++; if(ind==size.length)ind=0; cidx++; if(cidx==colors.length)cidx=0; }); ToggleButton btnCan=new ToggleButton("Холст 2 вкл./выкл."); btnCan.setTooltip(new Tooltip("Рисует и стирает второй холст")); btnCan.setOnAction((ae)->{ if(btnCan.isSelected())can.setVisible(true); else can.setVisible(false); }); ColorAdjust effect=new ColorAdjust(); effect.setBrightness(0.3); effect.setContrast(0.5); effect.setHue(0.5); effect.setSaturation(0.5); btnCan.selectedProperty().addListener(new javafx.beans.value.ChangeListener(){ @Override public void changed(javafx.beans.value.ObservableValue ov,Boolean oldV, Boolean newV) { if(newV.equals(Boolean.TRUE))btnCan.setEffect(effect); else btnCan.setEffect(null); } }); ToggleButton btnDis=new ToggleButton("DisplacementMap"); int w=200; int h=200; final FloatMap map1=new FloatMap(); map1.setWidth(w); map1.setHeight(h); for(int i=0;i{ if(btnDis.isSelected()){ btnDis.setEffect(effect); can.setEffect(dm); timer.start(); } else { btnDis.setEffect(null); timer.stop(); can.setEffect(null); } }); ToggleButton btn1All=new ToggleButton("Все эффекты 1"); btn1All.setTooltip(new Tooltip("Соединяет все применённые эффекты для холста 1")); btn1All.setOnAction((ae)->{ if( btn1All.isSelected()){ btn1All.setEffect(effect); myC.setEffect(dm); dm.setInput(g); g.setInput(r); r.setInput(inSh); timer.start(); } else { btn1All.setEffect(null); myC.setEffect(null); timer.stop(); } }); ToggleButton btn2All=new ToggleButton("Все эффекты 2"); btn2All.setTooltip(new Tooltip("Соединяет все применённые эффекты для холста 2")); btn2All.setOnAction((ae)->{ if( btn2All.isSelected()){ btn2All.setEffect(effect); can.setEffect(dm); dm.setInput(bL); bL.setInput(Bb) Bb.setInput(st); st.setInput(light); timer.start(); } else { timer.stop(); btn2All.setEffect(null); can.setEffect(null); } }); gc.strokeLine(0, 0, 200, 200); gc.strokeOval(100, 100,100, 200); gc.strokeRect(0, 200, 50, 200); gc.fillOval(0, 0, 20, 20); gc.fillRect(100, 320, 300, 40); grc.fillRoundRect(300,150, 100, 50, 30, 20); grc.strokeOval(50, 100, 200, 200); grc.strokeLine(10, 80, 30, 65); grc.strokeLine(30, 65, 130, 65); grc.strokeLine(110, 80, 130, 65); grc.strokeLine(110, 100, 130, 85); grc.strokeLine(130, 65, 130, 85); //Устанавливаем размер шрифта,для текстовой строки. //Если мы хотим,чтобы текст появился сразу же,при запуске программы,то нижеследующие //строчки кода надо раскоментировать. // gc.setFont(new Font(20)); // gc.fillText("This is drawn on the canvas.", 60, 50); Button btnRot = new Button("Rotate"); btnRot.setTooltip(new Tooltip("Поворачивает элементы холста вокруг центра холста на 30 град.")); Button btnGl = new Button("Glow"); btnGl.setTooltip(new Tooltip("Придаёт элементам эффект свечения")); Button btnShOn = new Button("Shadow on"); btnShOn .setTooltip(new Tooltip("Включает эффект внутреннего оттенения для элементов холста ")); Button btnSc = new Button("Scale"); btnSc.setTooltip(new Tooltip("Придаёт элементам определённый масштаб")); Button btnRefOn = new Button("Reflection on"); btnRefOn.setTooltip(new Tooltip("Придаёт элементам эффект отражения")); Button btnTrx = new Button("Translate X"); btnTrx.setTooltip(new Tooltip("Перемещает элементы вперёд по оси Х")); Button btnTry = new Button("Translate Y"); btnTry.setTooltip(new Tooltip("Перемещает элементы вперёд по оси У")); Button btnRevx = new Button("Reverse X"); btnRevx.setTooltip(new Tooltip("Перемещает элементы назад по оси Х")); Button btnRevy = new Button("Reverse Y"); btnRevy.setTooltip(new Tooltip("Перемещает элементы назад по оси У")); myC.setEffect(g); myC.getTransforms().add(rot); myC.getTransforms().add(sc); myC.getTransforms().add(tr); btnRot.setOnAction((ae) -> { ang+=30.0; rot.setAngle(ang); rot.setPivotX(myC.getWidth()/2); rot.setPivotY(myC.getHeight()/2); }); btnSc.setOnAction((ae) -> { scFact+=0.1; if( scFact>1.0) scFact=0.4; sc.setX( scFact); sc.setY( scFact); }); btnTrx.setOnAction((ae) -> { transX+=20; tr.setX(transX); }); btnTry.setOnAction((ae) -> { transY+=20; tr.setY(transY); }); btnRevx.setOnAction((ae) -> { transX-=20; tr.setX(transX); }); btnRevy.setOnAction((ae) -> { transY-=20; tr.setY(transY); }); btnGl.setOnAction((ae) -> { glVal+=0.1; if(glVal>1.0)glVal=0.0; g.setLevel(glVal); myC.setEffect(g); }); btnShOn.setOnAction((ae) -> { cidx++; if(cidx==colors.length)cidx=0; rad+=10.0; if(rad>100.0)rad=0.0; myC.setEffect(inSh); }); Button btnLOn = new Button("Lighting on"); btnLOn .setTooltip(new Tooltip("Включает теневые эффекты источника света для элементов холста 2 ")); Button btnLOff = new Button("BoxBlur -"); btnLOff.setTooltip(new Tooltip("Уменьшает эффект размывания узла")); Button btnBlOn = new Button("Bloom on +"); btnBlOn .setTooltip(new Tooltip("Включает эффект увеличения яркости узлов холста 2 ")); Button btnBb = new Button("BoxBlur on +"); btnBb.setTooltip(new Tooltip("Включает эффект размывания узла и наращивает его.")); btnBlOn .setOnAction((ae) -> { bl+=0.1; if(bl>1.0)bl=0.0; bL.setThreshold(bl); can.setEffect(bL); }); btnBb .setOnAction((ae) -> { bb+=5.0; if(bb>255.0)bb=0.0; Bb.setHeight(bb); Bb.setWidth(bb); can.setEffect(Bb); }); btnLOff .setOnAction((ae) -> { bb-=5.0; if(bb<0.0)bb=0.0; Bb.setHeight(bb); Bb.setWidth(bb); Bb.setIterations(cidx); can.setEffect(Bb); }); Button btnStof = new Button("Top Offset");//,new ImageView("clearBPIcon.gif")); btnStof.setTooltip(new Tooltip("Передвигает ось отображения на некоторое расстояние")); Button btnFr = new Button("Fraction");//,new ImageView("resumeIcon.gif")); btnFr.setTooltip(new Tooltip("Увеличивает площадь отражения")); Button btnTO = new Button("Top Opacity");//,new ImageView("resumeIcon.gif")); btnTO.setTooltip(new Tooltip("Увеличивает интенсивность вершины отражения")); Button btnBO = new Button("Bottom Opacity");//,new ImageView("resumeIcon.gif")); btnBO.setTooltip(new Tooltip("Увеличивает интенсивность дна отражения")); Label ch = new Label("Reflection"); ch.setStyle("-fx-background-color:yellow;-fx-border-color:blue;"); EventHandlereH1=new EventHandler(){ @Override public void handle(ActionEvent event) { re+=10.0; if(re>100.0)re=0.0; r.setTopOffset(re); } }; EventHandlereH2=(ActionEvent event) -> { ref+=0.1; if(ref>1.0)ref=0.0; r.setFraction(ref); }; EventHandlereH3=(ActionEvent event) -> { ref+=0.1; if(ref>1.0)ref=0.0; r.setTopOpacity(ref); }; EventHandlereH4=(ActionEvent event) -> { ref+=0.1; if(ref>1.0)ref=0.0; r.setBottomOpacity(ref); }; btnStof.setOnAction(eH1); btnFr.setOnAction(eH2); btnTO.setOnAction(eH3); btnBO.setOnAction(eH4); btnRefOn.setOnAction((ae) -> { myC.setEffect(r); });. Button btnDc = new Button("Diffuse Constant");//,new ImageView("clearBPIcon.gif")); btnDc.setTooltip(new Tooltip("Изменяет цвет подсвечиваемого элемента")); Button btnScon = new Button("Specular Constant");//,new ImageView("resumeIcon.gif")); btnScon.setTooltip(new Tooltip("Изменяет цвет подсвечиваемого элемента размывая его внизу")); Button btnSe = new Button("Specular Exponent");//,new ImageView("resumeIcon.gif")); btnSe.setTooltip(new Tooltip("Размывает элемент и наращивает чёткость сверху")); Button btnSs = new Button("Surface Scale");//,new ImageView("resumeIcon.gif")); btnSs.setTooltip(new Tooltip("Делает подсвечиваемый элемент,как-бы объёмным")); Label lig = new Label("Lighting"); lig.setStyle("-fx-background-color:yellow;-fx-border-color:blue;"); EventHandlereH5=new EventHandler(){ @Override public void handle(ActionEvent event) { lg+=0.5; if(lg>10.0)lg=0.0; light.setSurfaceScale(lg); } }; EventHandlereH6=(ActionEvent event) -> { lDc+=0.1; if(lDc>2.0)lDc=0.0; light.setDiffuseConstant(lDc); }; EventHandlereH7=(ActionEvent event) -> { lSc+=0.1; if(lSc>2.0)lSc=0.0; light.setSpecularConstant(lSc); }; EventHandlereH8=(ActionEvent event) -> { l+=1.0; if(l>40.0)l=0.0; light.setSpecularExponent(l); }; btnSs.setOnAction(eH5); btnDc.setOnAction(eH6); btnScon.setOnAction(eH7); btnSe.setOnAction(eH8); btnLOn.setOnAction((ae) -> { can.setEffect(light); }); MenuItem can1 = new MenuItem("Первый холст."); MenuItem EfOff=new MenuItem("Отключение эффектов"); MenuItem can2 = new MenuItem("Второй холст."); MenuItem EfOff2=new MenuItem("Отключение эффектов"); EventHandlereH9=(ActionEvent event) -> { myC.setEffect(null); }; EventHandlereH11=(ActionEvent event) -> { can.setEffect(null); }; EfOff.setOnAction(eH9); EfOff2.setOnAction(eH11); final ContextMenu off=new ContextMenu(can1,EfOff,can2,EfOff2) ; rootNode.setOnContextMenuRequested(new EventHandler(){ @Override public void handle(ContextMenuEvent event) { off.show(rootNode, event.getScreenX(), event.getScreenY()); } }); /* Тоже самое,но с помощью лямбда-выражения. rootNode.setOnContextMenuRequested((ContextMenuEvent event) -> { event.getScreenY() off.show(rootNode, event.getScreenX(), event.getScreenY()); }); */ mou = new Label(); mou.setStyle("-fx-background-color:yellow;-fx-border-color:red;"); myC.setOnMouseMoved(new EventHandler() { @Override public void handle(javafx.scene.input.MouseEvent event) { mouseX=(int) event.getX(); mouseY=(int) event.getY(); mou.setText("Координаты мыши 1: "+mouseX+", "+ mouseY); } }); mou2 = new Label(); mou2.setStyle("-fx-background-color:yellow;-fx-border-color:red;"); can.setOnMouseMoved(new EventHandler() { @Override public void handle(javafx.scene.input.MouseEvent event) { mouseX2=event.getX(); mouseY2=event.getY(); mou2.setText("Координаты мыши 2: "+mouseX2+", "+ mouseY2); } }); BorderPane bpV=new BorderPane(); BorderPane bpH=new BorderPane(); final GridPane gp=new GridPane(); final ToolBar tbRef=new ToolBar(ch,btnStof,btnFr,btnTO,btnBO); gp.addRow(1, tbRef); gp.setHgap(5); ToolBar tbL=new ToolBar(lig,btnDc,btnScon,btnSe,btnSs); gp.addRow(2, tbL); gp.setHgap(5); ToolBar tbB1=new ToolBar(btnGl,btnShOn,btnSc,btnRefOn,btnFont,mou); gp.addRow(3, tbB1); gp.setHgap(5); ToolBar tbB2=new ToolBar(btnLOn,btnBlOn,btnBb,btnLOff,btnCCol,btn1All); gp.addRow(4,tbB2); gp.setHgap(5); ToolBar tbB3=new ToolBar(btnRot,btnTrx,btnTry,btnRevx,btnRevy,btn2All); gp.addRow(5,tbB3); ToolBar tbB4=new ToolBar(btnCan,btnCCol2,btnDis,mou2); gp.addRow(6,tbB4); Stop[]stops=new Stop[]{new Stop(0,Color.RED),new Stop(1,Color.ORANGE)}; LinearGradient lG=new LinearGradient(0,0,0.25,0.25,true,CycleMethod.REFLECT,stops); ColorInput cIn=new ColorInput(); cIn.setWidth(550); cIn.setHeight(220); cIn.setPaint(lG); final Blend blend=new Blend(); blend.setMode(BlendMode.LIGHTEN); blend.setBottomInput(cIn); gp.setOnMouseEntered(new EventHandler(){ @Override public void handle(MouseEvent event) { gp.setEffect(blend); } }); gp.setOnMouseExited((MouseEvent event) -> { gp.setEffect(null); }); bpV.setTop(gp); bpV.setBottom(can); bpH.setRight(bpV); bpH.setLeft(myC); PerspectiveTransform pt=new PerspectiveTransform(); pt.setLlx(myC.getLayoutX()); pt.setUlx(myC.getLayoutX()); pt.setLly(myC.getLayoutY()+150); pt.setUly(myC.getLayoutY()); pt.setLrx(myC.getLayoutX()+180); pt.setUrx(myC.getLayoutX()+180); pt.setLry(myC.getLayoutY()+130); pt.setUry(myC.getLayoutY()+20); myC.setOnMouseEntered(new EventHandler(){ @Override public void handle(MouseEvent event) { myC.setEffect(pt); } }); myC.setOnMouseExited((MouseEvent event) -> { myC.setEffect(null); }); st.setLevel(1.0); can.setOnMouseEntered(new EventHandler(){ @Override public void handle(MouseEvent event) { can.setEffect(st); } }); can.setOnMouseExited((MouseEvent event) -> { can.setEffect(null); }); rootNode.getChildren().add(bpH); myStage.show(); } }