javafx - list View , tableView, media, chart
public class ViewController implements Initializable {
@FXML
private ListView<String> listView;
@FXML private TableView<PhoneVO> tableView;
@FXML private ImageView imageView;
@FXML private TextField txtName;
@FXML private Button btnUpdate;
@Override
public void initialize(URL location, ResourceBundle resources) {
// ListView에 출력 항목을 items 라고 함.
// 항목을 전달하는 class로 ObservableArrayList를 사용
String[] strs = new String[] {
"갤럭시S1","갤럭시S2","갤럭시S3","갤럭시S4",
"갤럭시S5","갤럭시S6","갤럭시S7"
};
List<String> strList = Arrays.asList(strs);
//ObservableList : Listener를 추가할 수 있는 List. new연산자로 생성불가. 정적메소드 써서 생성
ObservableList<String> list
= FXCollections.observableArrayList(
//"갤럭시S1","갤럭시S2","갤럭시S3","갤럭시S4","갤럭시S5","갤럭시S6","갤럭시S7"
strList
);
listView.setItems(list);
// listView 에 선택 항목을 지정 - 0번째 인덱스 번호를 선택항목으로 지정
listView.getSelectionModel().select(0);
// listView에 선택 항목 변경 감지
listView.getSelectionModel()
.selectedIndexProperty().addListener(new ChangeListener<Number>() {
// index번호는 숫자니까 Number로 제네릭 지정함.
@Override
public void changed(
ObservableValue<? extends Number> observable,
Number oldValue, Number newValue) {
// 나열된 항목 중 사용자가 선택한 항목이 새로 변경이 되었을 때
// 변경된 index 번호를 전달
System.out.println(oldValue);
System.out.println(newValue);
int index = newValue.intValue();
System.out.println(list.get(index));
tableView.getSelectionModel().select(index);
tableView.scrollTo(index);
}
});
// tableView - 항목 초기화 - PhoneVO
// tableView List정보를 저장할 List 생성
ObservableList<PhoneVO> phoneList = FXCollections.observableArrayList();
// phone01.png ~ phone.07.png
for(int i = 1; i<=7; i++) {
PhoneVO phone = new PhoneVO("갤럭시S"+i,"phone0"+i+".png");
phoneList.add(phone);
}
System.out.println(phoneList);
/*
TableColumn<PhoneVO,?> tColumnName = tableView.getColumns().get(0);
tColumnName.setCellValueFactory(new PropertyValueFactory<>("name")); //필드이름 가져옴
TableColumn<PhoneVO,?> tColumnPath = tableView.getColumns().get(1);
tColumnPath.setCellValueFactory(new PropertyValueFactory<>("path"));
*/
Field[] fields = PhoneVO.class.getDeclaredFields();
for(int i = 0; i < fields.length; i++) {
String fieldName = fields[i].getName();
System.out.println(fieldName);
TableColumn<PhoneVO,?> tColumn = tableView.getColumns().get(i);
tColumn.setCellValueFactory(new PropertyValueFactory<>(fieldName));
}
tableView.setItems(phoneList);
// tableView에 항목 변경 감지 Listener 추가
// 선택된 항목을 관리하는 Model class
// JavaFx에서 다양한 데이터를 관리하기 위해 모델 이라는 개념을 도입
// Model은 동적으로 조작하는 데이터를 관리하기 위한 객체
tableView.getSelectionModel()
.selectedItemProperty()
.addListener(new ChangeListener<PhoneVO>() {
@Override
public void changed(ObservableValue<? extends PhoneVO> observable,
PhoneVO oldValue,
PhoneVO newValue) {
System.out.println(oldValue);
System.out.println(newValue);
String path = "/images/"+newValue.getPath();
URL url = getClass().getResource(path);
imageView.setImage(new Image(url.toString()));
// 이름 정보 수정을 위해서
// TextField의 값을 선택된 행의 name 필드 정보로 변경
txtName.setText(newValue.getName());
}
});;
// tableView에서 항목을 선택하면 동일항목의 listView항목도 같이 선택되게
// listener추가
tableView.getSelectionModel().selectedIndexProperty()
.addListener((obj,o,n)->{
int index = n.intValue();
listView.getSelectionModel().select(index);
listView.scrollTo(index); // 해당되는 위치를 스크롤 최상단으로 이동
});
// UPDATE Button Action event
// TextField에 수정된 이름으로 스마트폰 이름 변경
btnUpdate.setOnAction(e->{
String name = txtName.getText();
//선택된거 가지고 오는 방법1
PhoneVO phone = tableView.getSelectionModel().getSelectedItem();
System.out.println(phone);
//선택된거 가지고 오는 방법2
int index = tableView.getSelectionModel().getSelectedIndex();
System.out.println(index);
// ListView list
list.set(index, name);
// TableView phoneList
phone.setName(name);
System.out.println(list);
System.out.println(phoneList);
// 새로고침
tableView.refresh();
listView.refresh();
});
// MediaView를 통해 재생되는 resource를 제어하는 객체
private MediaPlayer mediaPlayer;
// 재생해야할 resource 정보를 저장하는 객체
private Media media;
public class MediaController implements Initializable {
@FXML private Button btnPlay, btnPause, btnStop;
@FXML private ProgressBar progressBar;
@FXML private ProgressIndicator progressIndicator;
@FXML private Slider sliderVolume, sliderPlay;
@FXML private Label lblTime;
// Media 재생할 공간
@FXML private MediaView mediaView;
// MediaView를 통해 재생되는 resource를 제어하는 객체
private MediaPlayer mediaPlayer;
// 재생해야할 resource 정보를 저장하는 객체
private Media media;
@Override
public void initialize(URL location, ResourceBundle resources) {
// slider min = 0, max = 100
// media에서 volume을 0 ~ 1.0
sliderVolume.setValue(0.5);
// progress == 0~ 1.0으로 수치 표현
progressBar.setProgress(0.5);
progressIndicator.setProgress(0.5);
media = new Media(
getClass().getResource("/media/video.m4v").toString()
);
init();
} // end initialize
// 재생할 resource가 등록이 되면
// mediaPlayer를 초기화하는 method
public void init() {
if(mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer = null;
}
mediaPlayer = new MediaPlayer(media);
mediaView.setMediaPlayer(mediaPlayer);
// 새로운 미디어가 추가되면 프로그레스바, 인디케이터, 레이블을 초기화
setProgress(0.0,"0/0 sec");
// 미디어 플레이어 상태에 따른 부가 기능 초기화
setMediaPlayer();
// sliderPlay를 이용하여 미디어 재생 위치 제어
sliderPlay.valueProperty().addListener((t,o,n)->{
Duration totalDuration = mediaPlayer.getTotalDuration();
// sliderPlay 지정된 현재 수치
// 0 ~ 100 - 0 ~ 1.0
double value = sliderPlay.getValue() / 100.0;
// value = newValue
// 전체 재생시간을 1/1000 단위로 반환
double totalValue = totalDuration.toMillis();
// 재생 위치를 slider의 현재 조작 값으로 계산
double now = totalValue * value;
// 계산된 재생 시간 위치 정보로 Duration 객체 생성
Duration duration = new Duration(now);
// 미디어 플레이어에 재생 위치를
// 전달받은 duration 객체에 시간으로 변경
mediaPlayer.seek(duration);
mediaPlayer.play();
});
//mediaPlayer volume 조절
sliderVolume.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable,
Number oldValue,
Number newValue) {
// 0 ~ 1.0
double volume = newValue.doubleValue();
System.out.println("volume : " + volume);
// 미디어 플레이어 볼륨 정보 변경
// 0 ~ 1.0 까지의 실수값으로 조정
mediaPlayer.setVolume(volume);
}
});
// 재생 일시정지 멈춤 버튼 이벤트 초기화
btnPlay.setOnAction((e)->{
//미디어 재생
mediaPlayer.play();
// 미디어 플레이어 의 재생 시간 변경을 감지하여 변경 시간정보로
// progress를 변경
// 재생하고 있는 현재 시간 속성
mediaPlayer.currentTimeProperty()
// javafx.util.Duration == 시간 간격을 나타내는 클래스
// 특정 시간 단위를 기반으로 지속시간(duration)을 나타내는데 사용
.addListener(new ChangeListener<Duration>() {
@Override
public void changed(ObservableValue<? extends Duration> observable,
Duration oldValue,
Duration newValue) {
System.out.println(newValue);
// 현재 재생중인 파일의 전체 재생시간을 초단위로 읽어옴.
Duration duration = mediaPlayer.getTotalDuration();
double totalTime = duration.toSeconds();
System.out.println(duration);
System.out.println(totalTime);
double currentTime = newValue.toSeconds();
String lblTxt = (int)currentTime+"/"+(int)totalTime+" sec";
double progress = currentTime / totalTime;
lblTime.setText(lblTxt);
setProgress(progress,lblTxt);
}
});
});
btnPause.setOnAction(e->{
//일시정지
mediaPlayer.pause();
});
btnStop.setOnAction(e->{
//재생 중지
mediaPlayer.stop();
});
} // end init
// progress, Label 작성 초기화
public void setProgress(double p, String lblText) {
// 프로그래스 바 or 이디케이터는 0 ~ 1.0으로 진행 상황을 표현
progressBar.setProgress(p);
progressIndicator.setProgress(p);
lblTime.setText(lblText);
}
// 미디어 플레이어 상태에 따라 호출되는 method 지정
public void setMediaPlayer() {
// 재생 준비가 완료되었을 때
// 각 method들은 미디어 제어와 독립적으로 수행되어야 될 부가적인 기능을
// 전달 받기 때문에 독립적인 작업을 수행할 수 있도록 Runnable interface
// 구현 객체로 작업을 전달 받음.
mediaPlayer.setOnReady(new Runnable() {
@Override
public void run() {
// disable == 비활성화 - 사용자와 상호작용 불가능
btnPlay.setDisable(false);
btnPause.setDisable(true);
btnStop.setDisable(true);
}
});
// play 상태일 경우
mediaPlayer.setOnPlaying(()->{
btnPlay.setDisable(true);
btnPause.setDisable(false);
btnStop.setDisable(false);
});
// 일시 정지 상태
mediaPlayer.setOnPaused(()->{
btnPlay.setDisable(false);
btnPause.setDisable(true);
btnStop.setDisable(false);
});
// stop - 중지 상태
mediaPlayer.setOnStopped(()->{
//mediaPlayer에 등록된 Media의 재생 시작 시간을 가져옴
Duration duration = mediaPlayer.getStartTime();
mediaPlayer.seek(duration);
btnPlay.setDisable(false);
btnPause.setDisable(true);
btnStop.setDisable(true);
});
// 등록 미디어의 재생이 완료된 상태
mediaPlayer.setOnEndOfMedia(()->{
btnPlay.setDisable(false);
btnPause.setDisable(true);
btnStop.setDisable(true);
mediaPlayer.stop();
});
} // end setMediaPlayer
// Media 교체 이벤트 처리 - 재생 파일 변경
public void changeResource(ActionEvent e) {
Button btn = (Button)e.getTarget();
String text = btn.getText();
System.out.println(text);
String path = "";
switch(text) {
case "영상1" :
path="/media/video.m4v";
break;
case "영상2" :
path="/media/video.mp4";
break;
case "음악1" :
path="/media/audio.mp3";
break;
case "음악2" :
path="/media/audio.wav";
break;
} //end switch
System.out.println(path);
URL url = getClass().getResource(path);
System.out.println(url);
media = new Media(url.toString());
init();
}
}
// pie chart에 추가될 data를 observableList로 전달
// chart 지정되는 Data는 제네릭 타입에 맞게 Data class로 생성
ObservableList<PieChart.Data> list
= FXCollections.observableArrayList();
public class ChartController implements Initializable {
@FXML private PieChart pieChart;
@FXML private BarChart<String, Integer> barChart;
@FXML private AreaChart<String, Integer> areaChart;
@FXML private BubbleChart<Integer, Integer> bubbleChart;
@Override
public void initialize(URL location, ResourceBundle resources) {
// pie chart에 추가될 data를 observableList로 전달
// chart 지정되는 Data는 제네릭 타입에 맞게 Data class로 생성
ObservableList<PieChart.Data> list
= FXCollections.observableArrayList();
list.add(new PieChart.Data("AWT",5)); // data명, 적용될 수치(double)
list.add(new PieChart.Data("Swing", 25));
list.add(new PieChart.Data("SWT", 30));
list.add(new PieChart.Data("JavaFX", 60));
pieChart.setData(list);
// barChart
barChart.setTitle("평균 키");
// 막대 별로 어떤 정보를 저장하고 있는지를 표현
Series<String,Integer> series1 = new Series<>();
series1.setName("남성");
Series<String,Integer> series2 = new Series<>();
series2.setName("여성");
ObservableList<Data<String,Integer>> listBar = FXCollections.observableArrayList();
listBar.add(new Data<>("2019",173));
listBar.add(new Data<>("2020",173));
listBar.add(new Data<>("2021",174));
listBar.add(new Data<>("2022",176));
series1.setData(listBar);
listBar = FXCollections.observableArrayList();
listBar.add(new Data<>("2019", 160));
listBar.add(new Data<>("2020", 159));
listBar.add(new Data<>("2021", 163));
listBar.add(new Data<>("2022", 165));
series2.setData(listBar);
barChart.getData().add(series1);
barChart.getData().add(series2);
areaChart.setTitle("평균 온도");
Series<String,Integer> series3 = new Series<>();
series3.setName("서울");
ObservableList<Data<String,Integer>> listChart = FXCollections.observableArrayList();
listChart.add(new Data<>("2016",26));
listChart.add(new Data<>("2017",24));
listChart.add(new Data<>("2018",28));
listChart.add(new Data<>("2019",29));
listChart.add(new Data<>("2020",27));
series3.setData(listChart);
areaChart.getData().add(series3);
Series<String, Integer> series4 = new Series<>();
series4.setName("부산");
listChart = FXCollections.observableArrayList();
listChart.add(new Data<>("2016",29));
listChart.add(new Data<>("2017",30));
listChart.add(new Data<>("2018",31));
listChart.add(new Data<>("2019",24));
listChart.add(new Data<>("2020",32));
series4.setData(listChart);
areaChart.getData().add(series4);
// BubbleChart
// 체류 시간 별 상품 구매수와 판매 금액
// x : 체류시간 y : 금액, 구매수를 범위로 표현
Series<Integer,Integer> seriesA = new Series<>();
seriesA.setName("40대");
// x y scale
seriesA.getData().add(new Data<>(5,0,0));
seriesA.getData().add(new Data<>(10,5,5));
seriesA.getData().add(new Data<>(20,4,7));
seriesA.getData().add(new Data<>(30,3,2));
bubbleChart.getData().add(seriesA);
}
}