2014-04-06 3 views
0

javafx 가져 오기에서 DatePicker가 있습니다. 그러나 Calendar 속성이 포함되어 있어야합니다. 그래서 DatePicker를 확장하는 사용자 지정 컨트롤을 만들었습니다.사용자 정의 컨트롤을 만들려고 할 때 값이 변경되었을 때 알려야합니다.

그러나 언제나 datepicker가 변경 될 때마다이 속성을 호출해야합니다. 그 이유는 onAction 이벤트가 수행 될 때 .notify 메서드를 사용해야한다는 것입니다. java.lang.IllegalMonitorStateException 예외가 발생합니다.

public class DatePickerControl extends DatePicker 
{ 
    private ObjectProperty<Calendar> calendar; 

    public DatePickerControl() { 
     super(); 
     setValue(LocalDate.now()); 
    } 

    /** 
    * Get the value of calendar 
    * 
    * @return the value of calendar 
    */ 
    public ObjectProperty<Calendar> calendarProperty() {   
     Calendar calendar = new GregorianCalendar(); 
     System.out.println("test"); 
     calendar.set(getValue().getYear(), getValue().getMonthValue(), getValue().getDayOfMonth()); 
     return new SimpleObjectProperty<>(calendar); 
    } 

    /** 
    * Set the value of calendar 
    * 
    * @param calendar new value of calendar 
    */ 
    public void setCalendar(Calendar calendar) { 
     this.calendar.set(calendar); 
     LocalDate ld = LocalDate.now(); 
     ld.withYear(calendar.get(Calendar.YEAR)); 
     ld.withMonth(calendar.get(Calendar.MONTH)); 
     ld.withDayOfMonth(calendar.get(Calendar.DAY_OF_MONTH));   
     setValue(ld); 
    } 

    public Calendar getCalendar() { 
     return calendar.get(); 
    } 
} 

을하고 내가 .notify()를 호출 : 자바 FX의 새로운

dpAgendaRange.setOnAction(new EventHandler<ActionEvent>() { 

    @Override 
    public void handle(ActionEvent t) { 
     t.notify(); 
    } 
}); 

내가 그렇게 내 사과는 IF

내가이 사용자 정의 제어를 위해 사용하고있는 코드입니다 코드는 구조적이지 않습니다.

답변

1

먼저 notify()은 사용자가 생각하는대로 수행하지 않습니다. 저수준 동시성 API의 일부이며 wait() 블로킹 상태에있는 스레드를 깨우는 것과 관련이 있습니다. 이걸 here에서 읽을 수는 있지만 실제로하려는 일과 관련이 없습니다.

내 생각에 당신이하려는 것은 DatePickervalueProperty에있는 날짜 값과 항상 일치하는 ObjectProperty<Calendar>입니다. 즉, 한 번만를 작성하고, 그 가치, 그 값을 가져옵니다 getCalendar() 방법을 설정하는 setCalendar(...) 방법 및 속성 자체를 반환하는 calendarProperty() 방법이 있습니다

그냥 일반적인 방법으로 ObjectProperty<Calendar>을 정의,이 작업을 수행하려면 .

DatePickerObjectProperty<Calendar>valueProperty 사이의 바인딩을 유지하려면 각 수신기에 수신기를 등록하고 둘 중 하나가 변경되면 다른 수신기를 업데이트하십시오.

은 (또한, 달의 번호가 LOCALDATE와 달력과 다릅니다.)이 같은

그래서 뭔가 :

public class DatePickerControl extends DatePicker { 
    private ObjectProperty<Calendar> calendar; 

    private DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_DATE ; 
    private Format calendarFormatter = DateFormat.getDateInstance(); 

    public DatePickerControl() { 
     super(); 
     setValue(LocalDate.now()); 
     calendar = new SimpleObjectProperty<Calendar>(Calendar.getInstance()); 

     calendar.addListener((obs, oldValue, newValue) -> { 
      System.out.println("calendar changed from "+calendarFormatter.format(oldValue.getTime())+" to "+calendarFormatter.format(newValue.getTime())); 
      LocalDate localDate = LocalDate.now() 
       .withYear(newValue.get(Calendar.YEAR)) 
       .withMonth(newValue.get(Calendar.MONTH)+1) 
       .withDayOfMonth(newValue.get(Calendar.DAY_OF_MONTH)); 
      setValue(localDate); 
     }); 

     valueProperty().addListener((obs, oldValue, newValue) -> { 
      System.out.println("Value changed from "+dateFormatter.format(oldValue)+" to "+dateFormatter.format(newValue)); 
      Calendar cal = Calendar.getInstance(); 
      cal.set(getValue().getYear(), getValue().getMonthValue()-1, getValue().getDayOfMonth()); 
      calendar.set(cal); 
     }); 
    } 


    public ObjectProperty<Calendar> calendarProperty() {   
     return calendar; 
    } 

    public void setCalendar(Calendar calendar) { 
     this.calendar.set(calendar); 
    } 

    public Calendar getCalendar() { 
     return calendar.get(); 
    } 
} 

간단한 테스트 :

import java.text.DateFormat; 

import javafx.application.Application; 
import javafx.stage.Stage; 
import javafx.scene.Scene; 
import javafx.scene.control.Label; 
import javafx.scene.layout.VBox; 


public class Main extends Application { 
    @Override 
    public void start(Stage primaryStage) { 
     try { 
      VBox root = new VBox(); 
      Scene scene = new Scene(root,400,400); 

      DatePickerControl datePicker = new DatePickerControl(); 
      Label label = new Label(); 
      final DateFormat calFormatter = DateFormat.getDateInstance() ; 
      datePicker.calendarProperty().addListener((obs, oldValue, newValue) -> label.setText(calFormatter.format(newValue.getTime()))); 
      root.getChildren().addAll(datePicker, label); 
      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

많은 감사를, 이게 정말 도움이되었습니다. 좋은 설명뿐. –

관련 문제