Main 변경 없이 바로 Scene Builder로




Boder Center 위에 Pane(400, 400)을 하나 올려줍니다.


그 위에


PieChart : Code : fx:id - pieChart


Button : Code : OnAction - javaSel


Button : Code : OnAction - csSel


Button : Code : OnAction - pySel


Button : Code : OnAction - jsSel


Controller Class 설정



package app;

import java.net.URL;
import java.util.ResourceBundle;

import javax.swing.JScrollBar;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;

public class MainController implements Initializable{
	@FXML private PieChart pieChart;
	// 개별데이터 -> 리스트 -> 파이차트에 set
	int java = 10;
	int cs = 10;
	int py = 10;
	int js = 10;
	
	ObservableList<Data> list = null;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML 완");
		list = FXCollections.observableArrayList();
		list.add(new PieChart.Data("Java",  java));
		list.add(new PieChart.Data("C#",  cs));
		list.add(new PieChart.Data("Python",  py));
		list.add(new PieChart.Data("Java Script",  js));
		pieChart.setTitle("선호 언어"); // 타이틀
		pieChart.setLabelsVisible(true); // 라벨 여부
		pieChart.setData(list); // 데이터 적용
	}
	
	public void javaSel() { // 버튼을 누를 때 파이 값 증가
		java++;
		list.set(0, new Data("Java", java));
	}
	
	public void csSel() {
		cs++;
		list.set(1, new Data("C#", cs));
	}
	
	public void pySel() {
		py++;
		list.set(2, new Data("Python", py));
	}
	
	public void jsSel() {
		js++;
		list.set(3, new Data("Java Script", js));
	}
	
}



이번에는 Main을 Parent로 바꾼다.


Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));


primaryStage.setTitle("Progress 예제");




Border를 지워주고 Pane을 추가

Pane(400, 400) 위에

Label : Code : fx:id - result

ProgressBar : Code : fx:id - bar

ProgressIndicator : Code : fx:id - pi

Button(+) : Code : OnAction - plus

Button(auto) : Code : OnAction - auto

Button(-) : Code : OnAction - minus

Controller Class 설정을 마치고 코딩

다음 코드는 버튼을 누를 경우 +, - 가 되고 그 값을 Label에 띄우고 Progress bar, Indicator에도 띄운다.

또한 auto에 Thread를 적용하여 자동으로 증가하게끔 코딩





package app;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;

public class MainController implements Initializable{

	@FXML private Label result;
	@FXML private ProgressBar bar;
	@FXML private ProgressIndicator pi;
	private int percent = 0;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML 완");
	}
	
	public void plus() {
		if(percent<100) {
			percent++;
		}else {
			percent = 0;
		}
		print(percent);
	}
	
	public void minus() {
		if(percent > 0) {
			percent--;
		}else {
			percent = 100;
		}
		print(percent);
	}
	
	public void print(int num) {
		result.setText(num + "%");
		bar.setProgress(num*0.01); // 1을 100%로 잡으므로 0.01을 곱한다.
		pi.setProgress(num*0.01);
	}
	
	public void auto() {
		// 스레드로 pi의 % 채우기
		Thread th = new Thread() {
			@Override
			public void run() {
				// 방법 1 (충돌 발생)
//				while(true) { // 스레드를 임의로 만들면 작동은 되지만 예외를 발생
//								// FX등록 스레드만 쓰라는것
//					try { // 코드 안의 값들은 상관없는데 UI도 하나의 스레드로 서로 간섭이 일어나 충돌
//						plus(); // 코드 안의 값들은 상관없는데 UI도 하나의 스레드로 서로 간섭이 일어나 충돌
//						Thread.sleep(100);
//					} catch (InterruptedException e) {
//						e.printStackTrace();
//					}
//				}
				
				// 방법 2, 1의 해결법
				while(true) {
					Platform.runLater(()->{ // 자바 8버젼부터 사용가능, UI 충돌이 예상되는 지점에 사용
						plus();
					});
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		};
		th.start();
		
	}
}


'JavaFX > 01.Node 추가' 카테고리의 다른 글

[JAVA FX]01-12.Line Chart, Random  (0) 2018.09.11
[JAVA FX]01-11.PieChart  (0) 2018.09.11
[JAVA FX]01-09.속성 감시, 속성 바인딩  (0) 2018.09.10
[JAVA FX]01-08.Menu 바 추가  (0) 2018.09.10
[JAVA FX]01-07.TreeView  (0) 2018.09.10

Stream이란 사전적 의미로는 '줄줄 흐르다', 즉 흘러가는 흐름을 말하는데


Input Output도 마찬가지다.


데이터를 불러오는데 읽어들어오는 흐름과 내보내는 흐름이라고 이해하면 쉽다.




C:\temp\data.dat


위의 파일을 inputStream으로 불러온다고 하면


C:\temp\data.dat 이 경로에서 나의 작업 공간으로 데이터가 흘러온다.


현실에 비유한다면


산(C:\temp\data.dat)에서 강물이 도시(작업 공간)로 흘러 들어온다.


Output도 역으로 생각하면 된다.





이 흐름은 Byte, 바이트 형식으로 흘러오거나 Character, 문자 형식으로 흘러온다.


Byte형식은 InputStream, OutputStream이고


Character형식은 Reader와 Writer로 사용한다.





InputStream은 Byte 형식의 흐름의 최상위 객체로 FileInputStream, BufferedInputStream, DataInputStream 등


각각 용도에 특화된 InputStream의 자식 객체가 있다.


다음 게시글을 통해 다양한 스트림의 활용을 확인해보자




1.람다


람다식은 익명객체를 선언 할 경우 자주 쓰이는 형식을 간략화 시킨 식을 말한다.


자주 쓰이는 방법은 3가지의 방법이 있으며 람다를 사용하면 코드수가 줄어들고 오버라이드 할 메소드가 생략되어


좀 더 깔끔해진다.


다음 예제를 통해 일반 익명객체와 람다식을 비교해보자



package chap13.exam01.basic;

public class Main {
// 람다식은 다른 환경에서는 잘 쓰이지만 java에서는 잘 쓰이고 있지 않음
	public static void main(String[] args) {
		// 일반적인 익명객체 사용
		Runnable task1 = new Runnable() {
			
			@Override
			public void run() {
				for(int i = 1; i <= 3; i++) {
					System.out.println("익명 객체 스레드 실행");
				}
			}
		};
		// 1번 방법
		Thread th = new Thread(task1);
		th.start();
		
		// 2번 방법 (간소화)
		new Thread(task1).start();
		
		// 람다식 익명객체 사용 -> 강제하는 오버라이드 메소드 생략, 코드 수 절약
		// 강제 생략 할 메소드가 여러개면 안된다.
		// 3번 방법
		Runnable task2 =()->{
			for(int i = 1; i <= 3; i++) {
				System.out.println("람다식 객체 스레드 실행");
			}
		};
		
		new Thread(task2).start(); // 간소화
		
	}

}


람다식 인터페이스도 있는데 람다식의 특징으로 한 방식 정해진 방법을 강제하는 식이므로


메소드가 많으면 안되어 제한하는 코드를 따로 명시하며 메소드는 하나밖에 안쓰이기 때문에


왠만하면 잘 안쓰인다.


package chap13.exam02.lambdaInter;
@FunctionalInterface // 람다식 인터페이스를 만들 때 선언하여 1인터페이스 - 1메소드를 강제시킴
							   // 람다식을 사용 할 때에 메소드가 많으면 사용하기 애매하니 제한하는 코드
public interface LambdaInter {
	
	int operation(int a , int b); // 하나밖에 없기 때문에 사용 시 매개변수에 들어오는 값은
										 // 정해져 있어 자료형을 생략
	
//	void sayMsg(String msg);
}


람다식의 사용법은 3가지인데 객체화시


= new XXXX();


------------------------


= (a, b) -> { 내용 }


= a -> { 내용 }


= ( ) -> { 내용 }


과 같이 사용된다. 다음 예제를 확인해보자

package chap13.exam03.usage;

public class Main {

	public static void main(String[] args) {
		// 생략이 가능한 이유는 이미 인터페이스 내 메소드가 선언되어 있어서
		
		// 매개변수가 여러개 일 경우(매개변수 타입 생략 가능)
		OperationA lambdaA = (a, b)-> {
			int result = a + b;
			System.out.println("답은 : " + result);
		};
		lambdaA.plus(3, 4);
		
		// 매개변수가 하나일 경우(괄호와 타입이 생략)
		OperationB lambdaB = a ->{
			System.out.println("a의 제곱은 : " + (a * a));
		};
		lambdaB.square(50);
		
		// 매개변수가 없을 경우(생략 X) 기본 형태
		// 람다식 자체를 자주 사용하지 않기 때문에 일반적인 사용법인 이것정도만 기억하면 된다.
		OperationC lambdaC = () ->{
			System.out.println("매개변수 없이 실행");
		};
		lambdaC.process();
		
		//실험내용이 반환문 만 있을 경우(코드블록 생략, Return도 생략해주어야 함)
		OperationD lambdaD = msg -> msg;
		System.out.println(lambdaD.echo("반환만 한다."));

	}
	// 사용할 인터페이스 (내부 선언)
//	@FunctionalInterface // 써도 되고 안써도 된다.
	interface OperationA{ void plus(int a, int b); }
	interface OperationB{ void square(int a); }
	interface OperationC{ void process( ); }
	interface OperationD{ String echo(String msg); }
}


- 1 -


Main은 따로 변경할 사항이 없다.



BorderPane - Center에 Pane 추가


Pane위에 위와같이


Label (fx:id - label)


Slider (fx:id - slider)


TextArea (fx:id - area1)


TextArea (fx:id - area2)



Controller class 설정, 저장 후 코드


슬라이더의 콩을 움직일 때 글자의 크기도 바로바로 늘어나고


텍스트 area 1, 2의 글자가 동시에 입력되게끔



package app;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextArea;
import javafx.scene.text.Font;

public class MainController implements Initializable{

	@FXML private Label label;
	@FXML private Slider slider;
	@FXML private TextArea area1;
	@FXML private TextArea area2;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML Load Complete");
		// 실시간 감시, 값을 확인
		// 슬라이더 변경시 값을 확인
		// 아래는 그대로 쓰되 대부분 자동생성
		slider.setValue(12); // 글자 기본값 12랑 맞춰주기
		slider.valueProperty().addListener(new ChangeListener<Number>() {
		// 스스로를 감시하여 값이 변경 될 때마다 특정 이벤트 발생
			@Override
			public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
				label.setFont(new Font(newValue.doubleValue()));
			}
		});
		/*
		 * 단방향 바인딩
		 * 대상1에 변경된 내용을 대상 2에 적용
		 * 대상2.xxxProperty().bind(대상1.XXXProperty))
		 * 양방향 바인딩
		 * 대상2. xxxProperty().bindBidrictional(대상1.xxxProperty)
		 */
		Bindings.bindBidirectional(area1.textProperty(), area2.textProperty());
	}
	
}





















- 2 -


Main의 Scene scene = new Scene(root,200,200); 부분에 숫자를 200, 200로 하여 창 크기를 줄이고





Border의 Center에 Pane을 올리고


Pane 위에 Slider와 Text Field를 올린다.


Slider - fx:id : slider


TextField - fx:id : field


그리고 Controller class를 설정 후 코딩


이 프로그램은 슬라이더를 움직이면 그에 알맞은 텍스트가 출력되는 프로그램


Bindings를 통해서 하나로 묶는것

package app;

import java.net.URL;
import java.text.NumberFormat;
import java.util.ResourceBundle;

import javafx.beans.binding.Bindings;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;

public class MainController implements Initializable {

	@FXML private Slider slider;
	@FXML private TextField field;
	
	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		System.out.println("FXML Load Complete");
		slider.setValue(50);
//		field.setText("50");
		field.setText(new Double(50).toString());
		Bindings.bindBidirectional(field.textProperty(), slider.valueProperty(), NumberFormat.getNumberInstance());
		// field, slider를 인자로 받음
	}
	
}








Menu바는 정말 간단한 작업


Main에는 건드릴게 따로 없고 Scene Builder에서 디자인과 Controller만 하면 된다.





BorderPane Top - MenuBar 추가 - Menu 포함 - MenuItem 포함


   - Menu 추가 - MenuItem 포함


    - MenuItem 추가


   - MenuItem 추가


   - SeparatorMenuItem 추가


   - MenuItem 추가 (Close로 명명)


   - Menu 포함 - MenuItem 포함


   - Menu 포함 - MenuItem 포함


Center - Pane 추가


추가는 Library에서 검색하여 넣은것. 포함은 기본값


처음 MenuBar을 추가하면 3가지 Menu가 들어있고


Library에서 Menu 항목 안에 Menu를 추가하면 위의 실행 이미지와 같이 하위 항목이 하나 더 생긴다.


이미지에서 Menu 옆에 흐른 글씨로 File과 같이 써있는데 더블 클릭하여 내용을 변경할 수 있다.


그 중 Close로 명명한 MenuItem의 Code 부분의 On Action을 closeApp으로  설정


Controller 클래스 등록 후 저장


그리고 등록한 클래스를 작성



package app; import javafx.application.Platform; public class MainController { // initialize는 따로 초기화할 것이 없으므로 안씀 public void closeApp() { Platform.exit(); // 앱 종료(main Thread) System.exit(0); // Jvm을 완전 종료 } }



위와같이 코드를 작성하고 실행하면 아까 디자인한 창이 나오는데


상단 메뉴바에서 Close를 선택하면 프로그램이 종료된다.

이번에는 BorderPane을 그대로 사용합니다.


BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("main.fxml"));


primaryStage.setTitle("Directories");




BorderPane의 Center 부분에 Pane을 추가하고 TreeView를 사진과 같이 배치


TreeView : Code, fx:id - treeView


Mouse - On Mouse Clicked - selectTree


Controller class 등록


이제 폴더 구조를 만들기 위한 폴더 아이콘 이미지를 올려 줍니다.


위 이미지를 우클릭 다른 이름으로 저장


그리고 img 패키지를 새로 만든 후 드래그 앤 드롭으로 복사하고





Controller class 등록 후 클래스를 작성합니다.



package app;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;

public class MainController implements Initializable{
	// 폴더 명을 받기 때문에 String
	@FXML private TreeView<String> treeView;
	// 프로젝트의 src폴더 절대경로
	// "img/icon.png" 맨 앞에 슬래시가 없으면 app.img 패키지, 없으면 app 아래까지 절대경로를 지정
	// "/img/icon.png" 맨 앞에 슬래시가 있으면 img 패키지
	Image img = new Image(getClass().getResourceAsStream("/img/icon.png"));
	
	@SuppressWarnings("unchecked")
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML Load Complete");
		// 트리뷰의 구조를 먼저 설정해야함
		/*
		 * - 영화
		 * 		- 코메디
		 * 			- 한국
		 * 			- 미국
		 * 			- 영국
		 * 		- 로맨스
		 * 		- 액션
		*/
		// 폴더 : 7개 - 이미지 7개
		ImageView[] iv = new ImageView[7];
		for(int i = 0; i < 7; i++) {
			iv[i] = new ImageView(img);
			iv[i].setFitHeight(25); // 픽셀을 의미
			iv[i].setFitWidth(25);
		}
		
		// 1단계 트리 아이템 추가
		TreeItem<String> movie = new TreeItem<String>("영화", iv[0]);
		
		// 2단계 트리뷰에 추가
		TreeItem<String> comedy = new TreeItem<String>("comedy", iv[1]);
		TreeItem<String> romance = new TreeItem<String>("romance", iv[2]);
		TreeItem<String> action = new TreeItem<String>("action", iv[3]);
		// 1단계 밑에 추가
		movie.getChildren().addAll(comedy, romance, action);
		
		// 3단계 아이템 생성
		TreeItem<String> korea = new TreeItem<String>("한국", iv[4]);
		TreeItem<String> america = new TreeItem<String>("미국", iv[5]);
		TreeItem<String> english = new TreeItem<String>("영국", iv[6]);
		// 2단계 밑에 추가
		comedy.getChildren().addAll(korea, america, english);
		
		//한국 밑에 코메디 영화 2가지 추가(이미지 X)
		TreeItem<String> movie1 = new TreeItem<String>("영화1");
		TreeItem<String> movie2 = new TreeItem<String>("영화2");
		korea.getChildren().addAll(movie1, movie2);
		
		// 트리뷰에 추가
		treeView.setRoot(movie);
	}
	public void selectTree(MouseEvent evt) {
		// 더블클릭하면 그 값을 가져옴
		// get Click Count는 연속 클릭 횟수를 세는 메소드
		System.out.println(evt.getClickCount());
		
		if(evt.getClickCount() == 2) {
			TreeItem<String> item = treeView.getSelectionModel().getSelectedItem();
			System.out.println(item.getValue());
		}
	}
	
}



이번에는 BorderPane을 그대로 사용합니다.


BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("main.fxml"));


primaryStage.setTitle("주소록 작성");


실행 시 창 크기의 가로를 조금 늘려주겠습니다.


primaryStage.setWidth(615);





BorderPane을 지우지 않고 그대로 사용하겠습니다.


Library에 Pane을 검색하여 좌측 아래의 Hierarchy Border의 Top부분에 끌어다 놓고 안에 TextField 4가지, Button 2가지


TableView는 Center에 끌어다가 배치합니다.


TableColumn은 아래와 같이 추가합니다.




컬럼 이름에 오른쪽 클릭해서 Copy & Paste, Duplicate 둘 중 마음에 드는걸 사용.





Pane : Layout : Pref Width : 600, Pref Wifth : 80


TextField : Properties : Prompt Text - 이름


   Code : fx:id - nameField


TextField : Properties : Prompt Text - 주소


   Code : fx:id - addrField


TextField : Properties : Prompt Text - 폰번호


   Code : fx:id - phoneField


TextField : Properties : Prompt Text - 이메일


   Code : fx:id - mailField


Button : Properties : Prompt Text - 등록


Code : fx:id - regist


Button : Properties : Prompt Text - 초기화


Code : fx:id - init


TableView : Code : fx:id - table


TableColumn : Properties : Prompt Text - Name


   Code : fx:id - name


TableColumn : Properties : Prompt Text - Address


   Code : fx:id - address


TableColumn : Properties : Prompt Text - Phone


   Code : fx:id - phone


TableColumn : Properties : Prompt Text - E-mail


   Code : fx:id - email



package app;

import java.net.URL;
import java.util.ResourceBundle;

import app.model.TableRowModel;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;

public class MainController implements Initializable {
	// 필드
	@FXML private TextField nameField;
	@FXML private TextField addrField;
	@FXML private TextField phoneField;
	@FXML private TextField mailField;

	// 테이블&컬럼
	@FXML private TableView<TableRowModel> table;
	@FXML private TableColumn<TableRowModel, String> name;
	@FXML private TableColumn<TableRowModel, String> address;
	@FXML private TableColumn<TableRowModel, String> phone;
	@FXML private TableColumn<TableRowModel, String> email;


	ObservableList<TableRowModel> list = null;
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML Load Complete");
		list = FXCollections.observableArrayList();
		// Model 객체가 list에 추가
		// lee, seoul, 010-1234-5678, email
		list.add(new TableRowModel("lee", "seoul", "no phone", "email"));

		// 각 필드를 CellData 인터페이스에
		name.setCellValueFactory(cellData -> cellData.getValue().getName());
		address.setCellValueFactory(cellData -> cellData.getValue().getAddress());
		phone.setCellValueFactory(cellData -> cellData.getValue().getPhone());
		email.setCellValueFactory(cellData -> cellData.getValue().getEmail());

		table.setItems(list);
	}
	public void regist() {
		list.add(new TableRowModel(nameField.getText(), addrField.getText(), phoneField.getText(), mailField.getText()));
		name.setCellValueFactory(cellData -> cellData.getValue().getName());
		address.setCellValueFactory(cellData -> cellData.getValue().getAddress());
		phone.setCellValueFactory(cellData -> cellData.getValue().getPhone());
		email.setCellValueFactory(cellData -> cellData.getValue().getEmail());
		// setItems는 자동으로 감지됨

		// 사용자 편의성을 위해 초기화
		nameField.setText("");
		addrField.setText("");
		phoneField.setText("");
		mailField.setText("");
		
		// 리스트의 모든 값 출력 하기
		// TableRowModel을 새로 list를 넣어 향상된 for문으로 출력
		for(TableRowModel model : list) {
			System.out.println(
					model.getName().get()+" | "+
					model.getAddress().get()+" | "+
					model.getPhone().get()+" | "+
					model.getEmail().get()
			);
		}
	}
	public void init() {
		list.clear();
		// 리스트를 직접 핸들링 한 경우는 이 부분이 필요
		table.setItems(list);
	}

}
package app.model;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class TableRowModel {
	private StringProperty name;
	private StringProperty address;
	private StringProperty phone;
	private StringProperty email;
	// 생성자 (Alt + Shift + S 로 쉽게 등록(Constructor))
	public TableRowModel(String name, String address, String phone, String email) {
		this.name = new SimpleStringProperty(name);
		this.address = new SimpleStringProperty(address);
		this.phone = new SimpleStringProperty(phone);
		this.email = new SimpleStringProperty(email);
	}
	// 게터세터 (Alt + Shift + S 로 쉽게 등록)
	public StringProperty getName() {
		return name;
	}
	public void setName(StringProperty name) {
		this.name = name;
	}
	public StringProperty getAddress() {
		return address;
	}
	public void setAddress(StringProperty address) {
		this.address = address;
	}
	public StringProperty getPhone() {
		return phone;
	}
	public void setPhone(StringProperty phone) {
		this.phone = phone;
	}
	public StringProperty getEmail() {
		return email;
	}
	public void setEmail(StringProperty email) {
		this.email = email;
	}
	
}





Main.java 설정


Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));


primaryStage.setTitle("image view");


fxml파일의 Border pane 삭제





AnchorPane위에


ImageView : Layout은 원하시는대로 사이즈를 잘 맞춰보세요.


Code : fx:id - imgView


Button : Code : On Action - fileChoose


먼저 Controller로 설정한 java파일이 시작(initialize)될 때 이미지를 웹에서 끌어와 기본 이미지로 띄울 것이고


그리고 이미지 선택 버튼을 누르면 윈도우 파일 선택창이 나오고 그 파일을 InputStream으로 받아서 ImageView에 띄우는것.



package app;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;

public class MainController implements Initializable {
	@FXML private ImageView imgView;
	
	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		System.out.println("FXML Load Complete");
		// 기본 이미지(웹 이미지)
		// http://img.hani.co.kr/imgdb/resize/2017/0623/00502643_20170623.JPG , 치킨주의!!
		String url = "http://img.hani.co.kr/imgdb/resize/2017/0623/00502643_20170623.JPG";
		Image img = new Image(url);
		// 선택한 이미지의 사이즈 조절이 가능하다.
		imgView.setFitHeight(372);
//		imgView.setFitHeight(img.getHeight()/2);
		imgView.setFitWidth(372);
		imgView.setImage(img);
	}
	
	public void fileChoose() {
		// 사진 선택 창
		FileChooser fc = new FileChooser();
		fc.setTitle("이미지 선택");
		fc.setInitialDirectory(new File("C:/")); // default 디렉토리 설정
		// 선택한 파일 정보 추출
		// 확장자 제한
		ExtensionFilter imgType = new ExtensionFilter("image file", "*.jpg", "*.gif", "*.png");
//		fc.getExtensionFilters().add(imgType);
		ExtensionFilter txtType = new ExtensionFilter("text file", "*.txt", "*.doc");
		fc.getExtensionFilters().addAll(imgType, txtType);
		
		File selectedFile =  fc.showOpenDialog(null); // showOpenDialog는 창을 띄우는데 어느 위치에 띄울건지 인자를 받고
																// 그리고 선택한 파일의 경로값을 반환한다.
		System.out.println(selectedFile); 				// 선택한 경로가 출력된다.
		
		// 파일을 InputStream으로 읽어옴
		try {
			// 파일 읽어오기
			FileInputStream fis = new FileInputStream(selectedFile);
			BufferedInputStream bis = new BufferedInputStream(fis);
			// 이미지 생성하기
			Image img = new Image(bis);
			// 이미지 띄우기
			imgView.setImage(img);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		
	}
	
}














전과 같이 먼저 Main.java


Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));


primaryStage.setTitle("ListView Example");


추가 수정하고 


fxml파일을 열자.




이번에는 BorderPane을 사용하는데 기본 BorderPane을 좌측 아래에서 선택해 delete를 눌러 지워주고 다시 리스트에서


BorderPane을 검색하여 추가하자


BorderPane은 영역을 Top Left Right Center Bottom으로 나뉜다.


탑에는 Label, 센터에는 ListView, 바텀에는 ComboBox를 추가하자


Label : Properties : Text - SELECT, Font - 34px, Node Alignment - CENTER(Text Alignment가 아니고 아래의 Node)


          Code fx:id - msg


ListView : fx:id - listView


Prompt Text : Properties : Text - --선택하세요--


                   Code : fx:id - combo, On Action : choose

이번에는 리스트를 초기화 하고 콤보박스에서 선택한 것을 리스트에 추가해본다.


그리고 Controller class 설정을 잊지말자


Observable이란 리스트를 사용한다. 거의 ArrayList랑 비슷한 기능을 가지고 있다.


package app;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.SelectionMode;

public class MainController implements Initializable {
	@FXML private Label msg;
	@FXML private ListView listView;
	@FXML private ComboBox combo;
	
	@Override
	public void initialize(URL location, ResourceBundle resources) {
		System.out.println("FXML Load Complete");
		// 콤보 박스
		ObservableListitem = FXCollections.observableArrayList("a", "b", "c");
		combo.setItems(item);
		// 리스트 뷰
		item = FXCollections.observableArrayList();
		item.add("Java FX 8");
		item.add("Java FX 9");
		item.add("AWT");
		item.add("SWING");
		item.add("GWT");
		item.add("FRONT-END");
		listView.setItems(item);
		// 리스트 여러개 선택할 수 있게 활성화
		listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
//		listView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
	}
	
	// 콤보박스에 선택한 내용을 msg Label에 표현
	ObservableList list = FXCollections.observableArrayList(); // 전역 변수로 선언한다면
																					  // 기존의 리스트 자리를 유지하고 값이 추가됨
	public void choose() {
//		msg.setText(combo.getValue());
		// 콤보박스에 선택한 내용을 listView에 추가
		list.add(combo.getValue());
		listView.setItems(list);
	}
	
	public void selected() {
//		String item = listView.getSelectionModel().getSelectedItem();
//		System.out.println(item);
		
		// 복수, multi select 구현
		ObservableList list = listView.getSelectionModel().getSelectedItems();
		for(String selecteditem : list) {
			System.out.println(selecteditem);
		}
		// 원래는 복수 선택시 별도 버튼 필요
	}
}
//







+ Recent posts