JAVA chapter17. javaFX. 


17.12 화면 이동과 애니메이션

17.12.1 화면 이동



AppMain.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package sec12.exam01_move_animation;
 
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
 
public class AppMain extends Application {
    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("AppMain");
        Parent root= FXMLLoader.load(getClass().getResource("root.fxml"));
        Scene scene = new Scene(root);
        primaryStage.setScene(scene); // 메인 화면 설정
        primaryStage.setWidth(350);       //윈도우의 고정 폭 설정
        primaryStage.setHeight(500);      //윈도우의 고정 높이 설정
        primaryStage.setResizable(false);   //윈도우 크기를 조정할 수 없도록 함
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}
cs


LoginController.java // 로그인 화면 컨트롤러
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package sec12.exam01_move_animation;
 
import java.net.URL;
import java.util.ResourceBundle;
 
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
 
public class LoginController implements Initializable {
    @FXML private BorderPane login;
    @FXML private Button btnMain;
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        btnMain.setOnAction(e->handleBtnMain(e));
    }
    
    public void handleBtnMain(ActionEvent event) {
        try {
            StackPane root = (StackPane) btnMain.getScene().getRoot();
            
            login.setTranslateX(0); // 시작값을 0으로 설정
            
            Timeline timeline = new Timeline();
            KeyValue keyValue = new KeyValue(login.translateXProperty(), 350); // 종료값을 350으로 설정하고
            KeyFrame keyFrame = new KeyFrame(
                Duration.millis(100), // 0.1초간 애니메이션 실행
                new EventHandler<ActionEvent>() { // 애니메이션이 종료되면 handle() 메소드가 자동 호출됨
                    @Override
                    public void handle(ActionEvent event) {
                        root.getChildren().remove(login); // StackPane에서 로그인 화면 제거
                    } // 애니메이션 종료 후 로그인 화면 제거
                }, 
                keyValue
            );
            timeline.getKeyFrames().add(keyFrame);
            timeline.play();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}
cs


RootController.java // 메인 화면 컨트롤러
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package sec12.exam01_move_animation;
 
import java.net.URL;
import java.util.ResourceBundle;
 
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.util.Duration;
 
public class RootController implements Initializable {
    @FXML private Button btnLogin;
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        btnLogin.setOnAction(e->handleBtnLogin(e));
    }
    
    public void  handleBtnLogin(ActionEvent event) {
        try { // 로그인 화면으로 이동
            Parent login= FXMLLoader.load(getClass().getResource("login.fxml"));
            StackPane root = (StackPane) btnLogin.getScene().getRoot();
            root.getChildren().add(login);
            
            login.setTranslateX(350); // 시작값을 350으로 설정(로그인 화면의 폭)
 
            Timeline timeline = new Timeline(); // 종료값을 0으로 설정하고, 0.1초간 지속
            KeyValue keyValue = new KeyValue(login.translateXProperty(), 0); //
            KeyFrame keyFrame = new KeyFrame(Duration.millis(100), keyValue); //
            timeline.getKeyFrames().add(keyFrame); //
            timeline.play();//
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}
cs


login.fxml // 로그인 화면
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.geometry.*?>
 
<BorderPane  xmlns:fx="http://javafx.com/fxml" 
    fx:id="login" prefHeight="500" prefWidth="350" 
    fx:controller="sec12.exam01_move_animation.LoginController">
    <top>
        <BorderPane style="-fx-background-color: #eaeaea;">
            <left>
                <Button fx:id="btnMain" text="메인"/>
            </left>
            <center>            
                <Label alignment="CENTER" prefWidth="215" text="로그인 화면" />
            </center>
            <padding>
                <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
            </padding>
        </BorderPane>
    </top>
    
   <center>
      <VBox style="-fx-background-color: #ffff00;">
      </VBox>
   </center>        
</BorderPane>
cs


root.fxml // 메인 화면
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.geometry.*?>
 
<StackPane xmlns:fx="http://javafx.com/fxml" 
    prefHeight="500" prefWidth="350" 
    fx:controller="sec12.exam01_move_animation.RootController">
    <children>
        <BorderPane>
            <top>
                <BorderPane style="-fx-background-color: #eaeaea;">
                    <center>            
                        <Label alignment="CENTER" prefWidth="215" text="메인 화면" />
                    </center>
                    
                    <right>
                        <Button fx:id="btnLogin" text="로그인"/>
                    </right>
                    <padding>
                        <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
                    </padding>
                </BorderPane>
            </top>
            
           <center>
              <VBox style="-fx-background-color: #0000ff;">
              </VBox>
           </center>        
        </BorderPane>
    </children>
</StackPane>
cs


17.12.2 애니메이션


AppMain.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package sec12.exam02_move_animation_sample;
 
 
 
import java.io.IOException;
 
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
 
public class AppMain extends Application {
    public static StackPane stackPane;
    
    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("AppMain");
        stackPane= (StackPane) FXMLLoader.load(AppMain.class.getResource("main/main_scene.fxml"));
        Scene scene = new Scene(AppMain.stackPane);
        primaryStage.setScene(scene);
        primaryStage.setWidth(350);
        primaryStage.setHeight(550);
        primaryStage.setResizable(false);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}
cs


Animation.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package sec12.exam02_move_animation_sample.util;
 
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.util.Duration;
 
public class Animation {
    /**
     * @param
     * start: 0.0~width
     * end: 0.0~width
     */        
    public static void slide(Node node, double start, double end) {
        node.setTranslateX(start);
        Timeline timeline = new Timeline();
        KeyValue keyValue = new KeyValue(node.translateXProperty(), end);
        KeyFrame keyFrame = new KeyFrame(Duration.millis(300), keyValue);
        timeline.getKeyFrames().add(keyFrame);
        timeline.play();
    }
    
    public static void slide(Node node, double start, double end, EventHandler<ActionEvent> onFinish) {
        node.setTranslateX(start);
        Timeline timeline = new Timeline();
        KeyValue keyValue = new KeyValue(node.translateXProperty(), end);
        KeyFrame keyFrame = new KeyFrame(Duration.millis(300), onFinish, keyValue);
        timeline.getKeyFrames().add(keyFrame);
        timeline.play();
    }
 
    /**
     * @param
     * start: 0.0~1.0
     * end: 0.0~1.0
     */    
    public static void fade(Node node, double start, double end) {
        node.setOpacity(start);
        Timeline timeline = new Timeline();
        KeyValue keyValue = new KeyValue(node.opacityProperty(), end);
        KeyFrame keyFrame = new KeyFrame(Duration.millis(500), keyValue);
        timeline.getKeyFrames().add(keyFrame);
        timeline.play();
    }
    
    public static void fade(Node node, double start, double end, EventHandler<ActionEvent> onFinish) {
        node.setOpacity(start);
        Timeline timeline = new Timeline();
        KeyValue keyValue = new KeyValue(node.opacityProperty(), end);
        KeyFrame keyFrame = new KeyFrame(Duration.millis(500), onFinish, keyValue);
        timeline.getKeyFrames().add(keyFrame);
        timeline.play();
    }        
}
cs


MainController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package sec12.exam02_move_animation_sample.main;
 
 
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
 
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import sec12.exam02_move_animation_sample.AppMain;
import sec12.exam02_move_animation_sample.list.ListController;
import sec12.exam02_move_animation_sample.util.Animation;
 
public class MainController implements Initializable {
    @FXML private Button btnList;
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        btnList.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                handleBtnList(event);
            }
        });
    }
    
    public void handleBtnList(ActionEvent event) {
        try {
            Parent parent = FXMLLoader.load(ListController.class.getResource("list_scene.fxml"));
            AppMain.stackPane.getChildren().add(parent);
            Animation.fade(parent, 01);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
cs


ListController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package sec12.exam02_move_animation_sample.list;
 
import java.net.URL;
import java.util.ResourceBundle;
 
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import sec12.exam02_move_animation_sample.AppMain;
import sec12.exam02_move_animation_sample.util.Animation;
 
public class ListController implements Initializable {
    @FXML private Button btnLeft;
    @FXML private Button btnRight;
    @FXML private StackPane listStackPane;    
    @FXML private Button btnHome;
    private int currentPage = 1;
    private int totalPage = 4;
    
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        btnLeft.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                handleBtnLeft(event);
            }
        });
        
        btnRight.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                handleBtnRight(event);
            }
        });
        
        btnHome.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                handleBtnHome(event);
            }
        });        
        
        listView = getList(currentPage);
        listStackPane.getChildren().add(listView);
        showButton();
    }
    
    private ListView listView;
    
    public void handleBtnLeft(ActionEvent event) {
        if(currentPage>1) { 
            currentPage--
            ListView<BorderPane> listView = getList(currentPage);
            listStackPane.getChildren().add(0, listView);
            Animation.slide(listStackPane.getChildren().get(1), 0350new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    listStackPane.getChildren().remove(1);
                }
            });
            showButton();
        }
    }    
    
    public void handleBtnRight(ActionEvent event) {
        if(currentPage<totalPage) {
            currentPage++;
            ListView<BorderPane> listView = getList(currentPage);
            listStackPane.getChildren().add(listView);
            Animation.slide(listView, 3500new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent event) {
                    listStackPane.getChildren().remove(0);
                }
            });
            showButton();
        }
    }
    
    public void handleBtnHome(ActionEvent event) {
        Animation.fade(AppMain.stackPane.getChildren().get(1), 10new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                AppMain.stackPane.getChildren().remove(1);
            }
        });
    }    
    
    private void showButton() {
        if(currentPage == 1) {
            btnLeft.setVisible(false);
        } else {
            btnLeft.setVisible(true);
        }
        if(currentPage == totalPage) {
            btnRight.setVisible(false);
        } else {
            btnRight.setVisible(true);
        }
    }
    
    private ListView<BorderPane> getList(int page) {
        ListView<BorderPane> listView = new ListView<BorderPane>();
        int start = (page-1)*5 + 1;
        int end = page*5;
        for(int i=start; i<=end; i++) {
            BorderPane borderPane = new BorderPane();
            
            Image image = new Image(getClass().getResource("../images/phone" + ((i<10)?("0" + i):i)+ ".png").toString());
            ImageView imageView = new ImageView(image);
            imageView.setFitWidth(50);
            imageView.setFitHeight(75);
            borderPane.setLeft(imageView);
            
            HBox hbox = new HBox();
            hbox.setPadding(new Insets(10));
            hbox.setAlignment(Pos.CENTER_LEFT);
            Label label = new Label("스마트폰 0"+i);
            label.setFont(new Font(15));
            hbox.getChildren().add(label);
            borderPane.setCenter(hbox);
            
            Button button = new Button("상세보기");
            borderPane.setRight(button);
            BorderPane.setAlignment(button, Pos.CENTER);
            
            listView.getItems().add(borderPane);
        }
        return listView;
    }
}
 
cs



main_scenc.fxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.effect.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.input.*?>
<?import javafx.scene.image.*?>
<?import javafx.collections.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Border?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
 
<StackPane fx:id="stackPane" prefHeight="500" prefWidth="350" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sec12.exam02_move_animation_sample.main.MainController">
    <children>
        <VBox alignment="CENTER" spacing="100.0">
            <children>
                   <ImageView fitHeight="250.0" fitWidth="330.0" preserveRatio="true">
                       <image>
                      <Image url="@../images/background1.png" />
                   </image>
                   <VBox.margin>
                      <Insets top="30.0" />
                   </VBox.margin>
                   </ImageView>
                   <Button fx:id="btnList" prefHeight="50.0" prefWidth="200.0" text="폰목록 보기" />
            </children>
        </VBox>
    </children>
</StackPane>
cs



list_scene.fxml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="UTF-8"?>
 
<?import javafx.scene.effect.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.input.*?>
<?import javafx.scene.image.*?>
<?import javafx.collections.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.Border?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Button?>
 
<BorderPane prefHeight="500" prefWidth="350" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sec12.exam02_move_animation_sample.list.ListController">
    <top>
        <BorderPane style="-fx-background-color: #eaeaea;">
            <left>
                <Button fx:id="btnLeft" prefHeight="30" text="이전" />
            </left>
 
            <center>            
                <Label alignment="CENTER" prefWidth="215" text="목록" />
            </center>
            
            <right>
                <Button fx:id="btnRight" prefHeight="30" text="다음" />
            </right>
             
            <padding>
                <Insets topRightBottomLeft="3" />
            </padding>
        </BorderPane>
    </top>
    
   <center>
      <StackPane fx:id="listStackPane" />
   </center>    
   
   <bottom>
        <BorderPane style="-fx-background-color: #eaeaea;">
            <center>            
                <HBox alignment="CENTER">
                    <children>
                        <Button fx:id="btnHome" prefHeight="40" prefWidth="100" text="홈" />
                    </children>
                    <padding>
                        <Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
                    </padding>
                </HBox>
            </center>
        </BorderPane>           
   </bottom>    
</BorderPane>
 
cs


Posted by 너래쟁이
: