[Java-FX] 5. 기본 노드 (1)

2023. 10. 29. 17:10Java언어 공부

GUI 데이터 입력

 

설계할 화면에서 입력받을 데이터를 분석해야 한다. (데이터의 종류와 범위)

 

각 데이터를 어떤 GUI 노드를 이용하여 입력할지 결정해야 한다.

이때 결정 기준은 입력의 편리성을 선택해야 하고 입력 오류의 최소화를 시켜주어야 한다.

 

문자열 입력

 

문자열 입력을 받을 때 사용하는 노드

 

TextField, PasswordField, TextArea

 

가 있다.

 

짧은 문자열 (1줄) 입력을 받을 때는 Textfield나 PasswordField를 쓴다.

긴 문자열 (2줄 이상) 입력을 받을 때는 TextArea를 사용한다.

 

문자열 외에 다른 데이터 타입을 입력 받을 수도 있다.

=>하지만 입력된 데이터는 문자열이기 때문에 기대하는 타입으로

형변환을 시키면 얻을 수 있다.

 

TextField 주요 메소드

 

public String getText()

public void setText (String text)

public boolean isEditable()

public void setEditable (boolean argument)

public void setPromptText (String text)

 

PasswordField, TextArea도 같은 메소드를 가지고 있다.

setEditable을 이용하여 TextField를 입력 노드가 아닌 출력 전용 노드로 사용할 수 있다.

 

TextField 사건 처리

 

TextField는 보통 자체적으로 사건을 처리하기보다는 다른 노드의 사건에 따라

getText를 이용하여 입력한 데이터를 취한다.

 

1. textProberty()에 변화를 감시하는 처리자 연결

idField.textProperty().addListener((obs, oldVal, newVal)->
	loginButton.setDisable(idField.getText().length()==0||
    	pwdField.getText().length()==0));

 

 

2. setOnkeyTyped, setOnKeyPressed 사건에 처리자 연결

pwdField.setOnKeyTyped(e->
	loginButton.setDisable(idField.getText().length()==0||
    	pwdField.getText().length()==0));

 

TextArea

 

다중 라인을 입력할 때 사용한다.

memo.setPrefColumnCount(30);
memo.setPrefRowCount(5);

위의 코드를 통해서 폭의 크기나 줄 수를 설정할 수 있다.

(디폴트 값은 열 40, 행 10이 된다)

 

보여진 영역을 넘어 데이터가 입력이 될 수도 있으므로

ScrollPane과 함께 사용한다.

 

TextArea memo = new TextArea();
ScrollPane scrollPane = new ScrollPane();
scrollPane.setContent(memo);
scrollPane.setHbarPolicy(ScrollBarPolicy.ALWAYS);
scrollPane.setVbarPolicy(ScrollBarPolicy.ALWAYS);

 

TextArea를 이용한 메모 App 만들기

버튼과 메뉴항에 아이콘을 포함 할 수 있다.

Image saveImg = new Image("save.png")
saveBtn.setGraphic(new ImageView(saveImg));
saveMenuItem setGraphic(new ImageView(saveImg));

코드

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Optional;
import java.util.Scanner;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ChoiceDialog;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class Memo extends Application {
	private TextArea memo = new TextArea();
	private Stage mainStage;
	private File currentFile = null;
	private Button saveBtn = new Button("저장");
	private Button clearBtn = new Button("전체 지우기");
	private MenuItem saveMenuItem = new MenuItem("저장");
	private MenuItem clearMenuItem = new MenuItem("전체 지우기");
	
	private void saveAS() {
		FileChooser fileChooser = new FileChooser();
		File file = fileChooser.showSaveDialog(mainStage);
		if(file == null) return;
		try(PrintWriter out = new PrintWriter(file)){
			out.print(memo.getText());
			mainStage.setTitle("메모창: "+file.getName());
			currentFile = file;
		}
		catch(FileNotFoundException ex){
			ex.printStackTrace();
		}
	}
	
	private void openMemo() {
		FileChooser fileChooser = new FileChooser();
		File file = fileChooser.showOpenDialog(mainStage);
		if(file == null) return;
		try(Scanner reader = new Scanner(file)){
			StringBuilder in = new StringBuilder();
			while(reader.hasNextLine()){
				in.append(reader.nextLine()).append("\n");
			}
			memo.setText(in.toString());
			currentFile = file;
			mainStage.setTitle("메모창: "+currentFile.getName());
		}
		catch(FileNotFoundException ex){
			ex.printStackTrace();
		}

	}
	
	private void selectFont() {
		List<String> fonts = Font.getFamilies();
		ChoiceDialog<String> dialog = new ChoiceDialog<>("Arial", fonts);
		dialog.setTitle("폰트 선택");
		dialog.setHeaderText(null);
		dialog.setContentText("폰트를 선택하세");
		Optional<String> result = dialog.showAndWait();
		if(result.isPresent()){
			memo.setFont(Font.font(result.get(),FontWeight.NORMAL,FontPosture.REGULAR,16));
			Platform.runLater( new Runnable() {
			    @Override
			    public void run() {
			        memo.positionCaret(memo.getText().length());
			    }
			});
		}
	}
	
	private MenuBar constructMenuBar(){
		MenuItem openMenuItem = new MenuItem("불러오기");
		saveMenuItem.setGraphic(new ImageView(new Image("save.png")));
		openMenuItem.setGraphic(new ImageView(new Image("load.png")));
		clearMenuItem.setGraphic(new ImageView(new Image("clear.png")));
		
		saveMenuItem.setDisable(true);
		clearMenuItem.setDisable(true);
		
		openMenuItem.setOnAction(e->openMemo());
		saveMenuItem.setOnAction(e->saveAS());
		clearMenuItem.setOnAction(e->memo.setText(""));
		
		MenuItem fontMenuItem = new MenuItem("Select Font");
		fontMenuItem.setOnAction(e->selectFont());
		
		Menu fileMenu = new Menu("File");
		Menu formatMenu = new Menu("Format");
		fileMenu.getItems().addAll(openMenuItem, saveMenuItem,
				new SeparatorMenuItem(), clearMenuItem);
		formatMenu.getItems().add(fontMenuItem);
		MenuBar menuBar = new MenuBar();
		menuBar.getMenus().addAll(fileMenu, formatMenu);
		return menuBar;
	}
	
	private HBox constructButtonPane() {
		HBox buttonPane = new HBox();
		buttonPane.setSpacing(10);
		buttonPane.setAlignment(Pos.CENTER);
		buttonPane.setPadding(new Insets(10));
		Button openBtn = new Button("불러오기");
		buttonPane.getChildren().addAll(saveBtn, openBtn, clearBtn);
		saveBtn.setGraphic(new ImageView(new Image("save.png")));
		openBtn.setGraphic(new ImageView(new Image("load.png")));
		clearBtn.setGraphic(new ImageView(new Image("clear.png")));
		saveBtn.setOnAction(e->saveAS());
		openBtn.setOnAction(e->openMemo());
		clearBtn.setOnAction(e->memo.setText(""));
		saveBtn.setDisable(true);
		clearBtn.setDisable(true);
		return buttonPane;
	}
	
	@Override
	public void start(Stage primaryStage) throws Exception {
		BorderPane mainPane = new BorderPane();
		
		memo.textProperty().addListener((obs, oldVal, newVal)->{
			saveBtn.setDisable(memo.getText().length()==0);
			clearBtn.setDisable(memo.getText().length()==0);
			saveMenuItem.setDisable(memo.getText().length()==0);
			clearMenuItem.setDisable(memo.getText().length()==0);
		});
		
		ScrollPane contentsPane = new ScrollPane(memo);
		contentsPane.setPadding(new Insets(10));
		//contentsPane.setVbarPolicy(ScrollBarPolicy.ALWAYS);
		
		mainPane.setTop(constructMenuBar());
		mainPane.setCenter(contentsPane);
		mainPane.setBottom(constructButtonPane());
		
		mainStage = primaryStage;
		
		primaryStage.setTitle("KoreaTech Memo App");
		primaryStage.setScene(new Scene(mainPane));
		primaryStage.show();
	}

	public static void main(String[] args) {
		Application.launch(args);
	}

}

 

예시) 사용자 등록창

 ID : 문자열 (TextField)

이름 : 문자열 (TextField)

성별 : 단일 선택, RadioButton

생년 월일 : 단일 선택, ComboBox

취미 : 복수 선택, CheckBox