2017-08-01 102 views
0

我正在使用此答案中建議的組合框:JavaFx: show DatePicker,但顯示正確的文本時出現問題。如果我從DatePicker中選擇一個日期,我試圖設置編輯器的文本,但它什麼都沒發生。 這是我曾嘗試:JavaFx:組合框編輯器的文本

getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->{ 
    if (newValue != null) { 
     if (MyTupe.DATE.equals(newValue.getType())) { 
      initDatePicker(); 
      datePicker.valueProperty().addListener((obs, oldDate, newDate) -> { 
       newValue.setValue(newDate); 
       getEditor().setText(newDate.toString()); 
       datePopOver.hide(); 
      }); 
      StackPane stackPane = new StackPane(datePicker); 
      stackPane.setPadding(new Insets(10, 10, 10, 10)); 

      datePopOver.setContentNode(stackPane); 
      datePopOver.show(this); 
     } else { 
      datePopOver.hide(); 
     } 
    } 
}); 

嘗試了很多之後,我添加了兩個事件編輯器的textProperty和setOnMouseClicked這樣的:如果我不用手動設置

getEditor().textProperty().addListener((observable, oldValue, newValue) -> { 
    System.out.println("Text changed"); 
}); 
setOnMouseClicked(event -> { 
    System.out.println(getEditor().getText()); 
}); 

首先不會被觸發getEditor().setText();即使我改變了comboBox的值,這對我來說有點奇怪,因爲我認爲這個textField包含了comboBox的文本(也許我錯了)。如果刪除該行,則每次顯示空字符串時都會顯示mouseClick事件。 如果getEditor().setText();行存在,編輯器的getText()將返回正確的文本,但不會顯示在組合框中。

的問題:

  • 在哪裏存儲組合框的文本?
  • 如何更改selectedItemProperty偵聽器中的文本?

我認爲,也許我在某處犯了一個錯誤,所以這是爲什麼這不起作用,但我不知道什麼,你能幫助我嗎?

+0

- ComboBoxes可以有一個StringConverter,將它的值轉換爲顯示的文本。 - 使用onAction替代onMouseClicked來觸發ComboBox和DatePicker上的用戶輸入操作。 –

回答

1

在鏈接代碼

替換:

items.set(0, new ComboBoxNode(newDate, DATE_TYPE)); 

有:

items.set(customComboBox.getSelectionModel().getSelectedIndex(), new ComboBoxNode(newDate, DATE_TYPE)); 

鏈接的代碼只在位置零更改日期。在這個新代碼中,適當位置的日期發生了變化。

全碼:

import java.time.LocalDate; 
import java.time.Month; 
import java.util.Objects; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.DatePicker; 
import javafx.scene.layout.FlowPane; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import org.controlsfx.control.PopOver; 

/** 
* 
* @author blj0011 
*/ 
public class JavaFXApplication155 extends Application 
{ 

    private static final String DATE_TYPE = "DATE"; 

    private class ComboBoxNode { 
     private final Object value; 
     private final String type; 

     private ComboBoxNode(final Object value, final String type) { 
      this.value = value; 
      this.type = type; 
     } 

     @Override 
     public String toString() { 
      return Objects.toString(value); 
     } 
    } 

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

    @Override 
    public void start(Stage primaryStage) { 
     final ObservableList<ComboBoxNode> items = 
       FXCollections.observableArrayList(
         new ComboBoxNode(LocalDate.now(), DATE_TYPE), 
         new ComboBoxNode(LocalDate.of(2017, Month.APRIL, 15), DATE_TYPE),//Added new date to ComboBox 
         new ComboBoxNode("11:35AM", "TIME")); 

     final PopOver datePopOver = new PopOver(); 
     datePopOver.setTitle("Enter new date"); 
     datePopOver.setCornerRadius(10); 
     datePopOver.setHeaderAlwaysVisible(true); 
     //datePopOver.set(true); 
     datePopOver.setAutoHide(true); 

     final ComboBox<ComboBoxNode> customComboBox = new ComboBox<>(items); 


     customComboBox.getSelectionModel().selectedItemProperty().addListener((o, old, newNode) -> { 
      if (newNode != null) { 
       if (newNode.type.equals(DATE_TYPE)) { 
        final DatePicker datePicker = new DatePicker((LocalDate) newNode.value); 
        datePicker.valueProperty().addListener((obs, oldDate, newDate) -> { 
         items.set(customComboBox.getSelectionModel().getSelectedIndex(), new ComboBoxNode(newDate, DATE_TYPE));//Fixed this line of code 
         datePopOver.hide(); 
        }); 

        final StackPane stackPane = new StackPane(datePicker); 
        stackPane.setPadding(new Insets(10, 10, 10, 10)); 

        datePopOver.setContentNode(stackPane); 
        datePopOver.show(customComboBox); 
       } else { 
        datePopOver.hide(); 
       } 
      } 
     }); 

     final FlowPane pane = new FlowPane(customComboBox); 
     pane.setPadding(new Insets(10, 10, 10, 10)); 
     pane.setPrefWidth(400); 
     pane.setPrefHeight(300); 

     // Show Scene 
     final Scene scene = new Scene(pane); 
     primaryStage.setTitle("Popup calendar"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 
} 
+1

它工作,其實我這樣做:'newValue.setDate(newDate);'和'items.set(customComboBox.getSelectionModel()。getSelectedIndex(),customComboBox.getselectionModel()。getSelecteditem());'' – Sunflame

1

關於你的問題:其中存儲組合框的文本? 通常,JavaFX控件基於MVC架構,數據存儲在模型中。控件僅根據定義的轉換器表示模型數據,並自動對模型的任何更改作出反應。

因此,在你的情況下,數據存儲在ObservableList items。要更新組合框,只需用新對象替換相應的項目即可。

請注意,組合框已經聽ObservableList和任何添加/刪除/設置將自動錶示在用戶界面。

爲什麼這個代碼不工作:

newValue.setValue(newDate); 

因爲你改變一個項目的內部狀態和ObservableList items不會對這種變化做出反應。只有更改名單纔有用。 @Sedrick提出了正確的解決方案。請參閱the related question