티스토리 뷰
TabPane을 이용해 TextViewer 만들기
이번 시간에는 JavaFX의 TabPane을 활용해서 TextViewer를 한번 만들어보겠습니다.
바로 아래와 같이 생긴 TextViewer를 만들어 보겠습니다.
이건 제가 만든 것을 보여 드리는 형식이기 때문에 한번 보시고 필요한 부분이 있으면 사용하셔도 됩니다.
물론 별로 도움이 안 될수도 있으니 그냥 가볍게 봐주시길 바랍니다 ^^
TabPane
일단 위 디자인을 구현하기 위해서는 TabPane이 중심이라고도 할 수 있습니다.
그래서 먼저 할 작업은 저대로 TabPane의 디자인을 입히는 일이죠.
CSS 파일은 미리 다 만들어 놨습니다. 여깄습니다. textviewer.css
TabPane은 Tab 객체를 TabPane에 add 하는 방식으로 이루어져 있습니다. 그리고 만약 tab에 contents를 넣고 싶다고 하면
Tab 객체에 setContent 라는 메소드로 집어 넣을수가 있습니다.
즉 TabPane을 사용하려면 저 디자인 전체가 TabPane으로 이루어져 있다는 것이죠.
FXML 작성
그럼 이제 FXML 을 작성해보도록 하겠습니다.
위에서 말했듯이 저 디자인의 전체가 TabPane입니다. 그럼 상단의 button 들이 있는 bar는 어떻게 만들까요?
저도 고민을 많이 했는데... JavaFX에는 StackPane이라는 컨테이너가 있습니다.
이 StackPane은 안에 Contents들을 겹치는 방식으로 배치를 할 수 있습니다.
그렇다면 TabPane을 제일 아래에 깔고 그 위에 bar를 붙이면 되지 않을까요?
저는 그 생각으로 구현을 했습니다. 그렇게 작성한 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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | <VBox xmlns="http://javafx.com/javafx/8" fx:controller="sample.Controller" xmlns:fx="http://javafx.com/fxml/1" stylesheets="@textviewer.css"> <padding> <Insets top="10" left="10" right="10" bottom="10"/> </padding> <StackPane style="-fx-border-color:#868E95" fx:id="viewerPane"> <TabPane styleClass="maintab" fx:id="mainTab"> </TabPane> <HBox style="-fx-background-color:linear-gradient(#F1F5F9, #DFE5EC); -fx-border-width:1; -fx-border-color:#868E95;" maxHeight="35" StackPane.alignment="TOP_LEFT" alignment="CENTER_LEFT"> <Button fx:id="newFileButton" styleClass="viewer_button"> <graphic> <ImageView> <Image url="@ui/image/newFile.png"/> </ImageView> </graphic> <HBox.margin> <Insets> <left>10</left> </Insets> </HBox.margin> </Button> <Button fx:id="saveButton" styleClass="viewer_button"> <graphic> <ImageView> <Image url="@ui/image/save.png"/> </ImageView> </graphic> <HBox.margin> <Insets> <left>10</left> </Insets> </HBox.margin> </Button> <Button fx:id="printButton" styleClass="viewer_button"> <graphic> <ImageView> <Image url="@ui/image/print.png"/> </ImageView> </graphic> <HBox.margin> <Insets> <left>10</left> </Insets> </HBox.margin> </Button> <HBox alignment="CENTER_RIGHT"> <Button fx:id="newWindowButton" styleClass="viewer_button"> <graphic> <ImageView> <Image url="@ui/image/newWindow.png"/> </ImageView> </graphic> <HBox.margin> <Insets> <right>10</right> </Insets> </HBox.margin> </Button> <HBox.hgrow> <Priority fx:constant="ALWAYS"/> </HBox.hgrow> </HBox> <StackPane.margin> <Insets> <top>30</top> </Insets> </StackPane.margin> </HBox> <VBox.vgrow> <Priority fx:constant="SOMETIMES"/> </VBox.vgrow> </StackPane> </VBox> | cs |
저의 경우는 VBox를 전체 Container로 깔고 그 위에다 StackPane을 깔았습니다.
그 위에 TabPane을 깔고 그 다음에 Button이 있는 Bar인 HBox를 추가 해줍니다. 그리곤 HBox에 Button 들을 넣기만 하면 됩니다.
아 참 Button에 들어갈 이미지는 여기 있습니다.
적절한 경로에 넣어주시면 아래와 같은 결과를 볼 수 있습니다.
그럼 이제는 기능을 넣어볼 차례입니다.
기능 구현
기능은 간단하게 Controller.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 | public class Controller implements Initializable { @FXML Button saveButton; @FXML Button printButton; @FXML Button newFileButton; @FXML Button newWindowButton; @FXML TabPane mainainTab; @FXML StackPane viewerPane; private TextViewerEventHandler handler; @Override public void initialize(URL location, ResourceBundle resources) { handler = new TextViewerEventHandler(viewerPane, mainainTab); newFileButton.addEventHandler(MouseEvent.MOUSE_CLICKED, handler); saveButton.addEventHandler(MouseEvent.MOUSE_CLICKED, handler); printButton.addEventHandler(MouseEvent.MOUSE_CLICKED, handler); newWindowButton.addEventHandler(MouseEvent.MOUSE_CLICKED, handler); } } | cs |
Controller에서 모든 동작을 처리 해줘도 되지만
나중에 재사용 할 것을 대비해서 EventHandler 클래스를 따로 구현했습니다.
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 | public class TextViewerEventHandler implements EventHandler<MouseEvent> { private TabPane tabPane; private Pane context; public TextViewerEventHandler(Pane context, TabPane tabPane) { this.tabPane = tabPane; this.context = context; } @Override public void handle(MouseEvent event) { switch (event.getPickResult().getIntersectedNode().getId()) { case "newFileButton": FileChooser newFileChooser = new FileChooser(); File newFile = newFileChooser .showOpenDialog(context.getScene().getWindow()); openNewTab(newFile.getPath()); break; case "saveButton": if (isTabExist()) { if (isTabExist()) { FileChooser saveFileChooser = new FileChooser(); File saveFile = saveFileChooser.showSaveDialog(context.getScene().getWindow()); if (saveFile != null) { saveFile(saveFile); } } } break; case "printButton": if (isTabExist()) { PrinterJob printerJob = PrinterJob.createPrinterJob(); if (printerJob.showPrintDialog(context.getScene().getWindow())) { boolean success = printerJob.printPage(tabPane.getSelectionModel().getSelectedItem().getContent()); if (success) { printerJob.endJob(); } } } break; case "newWindowButton": if (isTabExist()) { Stage stage = new Stage(); stage.setTitle(tabPane.getSelectionModel().getSelectedItem().getText()); HBox hBox = (HBox) tabPane.getSelectionModel().getSelectedItem().getContent(); TextArea textArea = (TextArea) hBox.getChildren().get(0); TextArea newArea = new TextArea(textArea.getText()); newArea.setEditable(false); stage.setScene(new Scene(newArea, 1000, 800)); stage.show(); } break; } } /** * TabPane에 Tab이 존재하는지 검사 * @return */ private boolean isTabExist() { return tabPane.getSelectionModel().getSelectedItem() != null; } /** * 지정된 경로에 현재 Focus 된 Tab의 Text file 저장 * @param file */ private void saveFile(File file){ HBox hBox = (HBox) tabPane.getSelectionModel().getSelectedItem().getContent(); TextArea textArea = (TextArea) hBox.getChildren().get(0); try{ FileWriter writer = null; writer = new FileWriter(file); writer.write(textArea.getText().replaceAll("\n", "\r\n")); writer.close(); } catch (IOException e) { e.printStackTrace(); } } /** * Txt File을 읽어 Tab으로 생성 * @param txtFile * @return */ private Tab addTabFromFile(File txtFile){ Tab tab = new Tab(); tab.setText(txtFile.getName()); TextArea textArea = new TextArea(); textArea.setEditable(false); HBox hBox = new HBox(); hBox.setStyle("-fx-background-color:white"); HBox.setHgrow(textArea, Priority.ALWAYS); //상단의 메뉴 바 하단에 배치 hBox.setMargin(textArea, new Insets(35, 3, 3, 3)); BufferedReader br = null; try{ br = new BufferedReader(new InputStreamReader(new FileInputStream(txtFile))); String line; while((line = br.readLine()) != null){ textArea.appendText(line + "\n"); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } hBox.getChildren().add(textArea); tab.setContent(hBox); return tab; } public void openNewTab(String path){ tabPane.getTabs().add(addTabFromFile(new File(path))); } } | cs |
그 후 Main에서는 fxml을 로드 시켜주기만 하면 됩니다. 아래 처럼 말이죠,
1 2 3 4 5 6 7 8 9 10 11 | public class Main extends Application { @Override public void start(Stage primaryStage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("textviewer.fxml")); root.setStyle("-fx-background-color:white"); primaryStage.setTitle("TextViewer Test"); primaryStage.setScene(new Scene(root, 800,800)); primaryStage.show(); } } | cs |
결과 화면
그럼 결과적으로 다음과 같은 화면을 얻을수 있습니다.
물론 디자인적으로 수정이 필요할 것 같긴 합니다 ...
읽어주셔서 감사합니다 :)
반응형
'프로그래밍 > JavaFX' 카테고리의 다른 글
[JavaFX] resources 폴더의 CSS 파일 적용하기 (0) | 2017.02.14 |
---|---|
[JavaFX] Button 마우스 커서를 갖다 댔을 때 커서 모양 변경하기 (0) | 2017.02.13 |
[JavaFX] FileChooser를 이용해 txt 파일 저장하기 (0) | 2017.02.07 |
[JavaFX] File Chooser를 이용해 txt 파일 불러와 출력하기 (3) | 2017.02.07 |
[JavaFX] GridPane을 이용한 상대적 레이아웃 작성 방법(비율을 이용한 사이즈 조정) (0) | 2017.02.02 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 배낭 여행
- JavaFX Window Close
- JavaFX 테이블뷰
- effective java
- springboot
- 스프링부트
- 텐트
- 이펙티브자바
- 방통대 과제물
- 자전거 여행
- Java UI
- 일본 배낭여행
- TableView
- 일본여행
- 자전거
- 자바
- 이펙티브
- 배낭여행
- java
- 이펙티브 자바
- intelij
- JavaFX Table View
- 인텔리제이
- git
- 일본 자전거 여행
- JavaFX
- 일본 여행
- JavaFX 종료
- effectivejava
- windows
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
글 보관함