2015-08-09 3 views

ответ

6

Как указано here, архитектура JavaFX имеет тенденцию способствовать связыванию элементов GUI через классы, реализующие интерфейс Observable. С этой целью Ирина Федорцова адаптировала оригинал Converter к JavaFX в главе 5 JavaFX для разработчиков Swing: Implementing a Swing Application in JavaFX.

image

Я кратко изложил ниже программы, обновления до Java 8 и устраняя зависимость от ныне deprecated builder API. В приведенной ниже вариации,

  • А DoubleProperty имени meters функций как Observableмодель приложения.

  • Экземпляры Control, такие, как TextField, ComboBox и Slider, каждая функция в качестве зрения от модели, а также обеспечивает способ для пользователя, чтобы управления взаимодействия.

  • ВConversionPanel, InvalidationListener добавлен к ComboBox обновляет TextFieldвид из модели по мере необходимости, чтобы отразить текущий выбранный Unit; аналогичный слушатель, добавленный в TextField, обновляет модель сам по себе, как пользователь.

  • То же модели разделяются между экземпляров ConversionPanel по Slider, связывая ползунки и любые элементы управления для прослушивания до модели.

    slider.valueProperty().bindBidirectional(meters); 
    
  • Каждый ComboBox также имеет модель, ObservableList, из которого пользователь может выбрать один из экземпляров Unit.

Код:

/* 
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. 
* 
* Redistribution and use in source and binary forms, with or without 
* modification, are permitted provided that the following conditions 
* are met: 
* 
* - Redistributions of source code must retain the above copyright 
*  notice, this list of conditions and the following disclaimer. 
* 
* - Redistributions in binary form must reproduce the above copyright 
*  notice, this list of conditions and the following disclaimer in the 
*  documentation and/or other materials provided with the distribution. 
* 
* - Neither the name of Oracle or the names of its 
*  contributors may be used to endorse or promote products derived 
*  from this software without specific prior written permission. 
* 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
*/ 
package converter; 

/** 
* @see http://docs.oracle.com/javafx/2/swing/port-to-javafx.htm 
*/ 
public class Unit { 

    String description; 
    double multiplier; 

    Unit(String description, double multiplier) { 
     super(); 
     this.description = description; 
     this.multiplier = multiplier; 
    } 

    @Override 
    public String toString() { 
     String s = "Meters/" + description + " = " + multiplier; 
     return s; 
    } 
} 

/* 
* Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 
*/ 
package converter; 

/** 
* @see http://docs.oracle.com/javafx/2/swing/port-to-javafx.htm 
*/ 
import java.text.NumberFormat; 
import javafx.beans.InvalidationListener; 
import javafx.beans.Observable; 
import javafx.beans.property.DoubleProperty; 
import javafx.collections.ObservableList; 
import javafx.scene.control.*; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.VBox; 
import javafx.util.StringConverter; 

public class ConversionPanel extends TitledPane { 

    private static final int MAX = 10000; 
    private static final int DIGITS = 3; 

    private final TextField textField = new TextField(); 
    private final Slider slider = new Slider(0, MAX, 0); 
    private final ComboBox<Unit> comboBox; 
    private NumberFormat numberFormat = NumberFormat.getNumberInstance(); 
    private DoubleProperty meters; 

    { 
     numberFormat.setMaximumFractionDigits(DIGITS); 
    } 

    private InvalidationListener fromMeters = (Observable o) -> { 
     if (!textField.isFocused()) { 
      textField.setText(numberFormat.format(meters.get()/getMultiplier())); 
     } 
    }; 

    private InvalidationListener toMeters = (Observable o) -> { 
     if (textField.isFocused()) { 
      try { 
       Number n = numberFormat.parse(textField.getText()); 
       meters.set(n.doubleValue() * getMultiplier()); 
      } catch (Exception ignored) { 
      } 
     } 
    }; 

    public ConversionPanel(String title, ObservableList<Unit> units, DoubleProperty meters) { 
     setText(title); 
     setCollapsible(false); 
     comboBox = new ComboBox<>(units); 
     comboBox.getSelectionModel().select(0); 
     comboBox.setConverter(new StringConverter<Unit>() { 

      @Override 
      public String toString(Unit t) { 
       return t.description; 
      } 

      @Override 
      public Unit fromString(String string) { 
       throw new UnsupportedOperationException("Not supported yet."); 
      } 
     }); 
     setContent(new HBox(new VBox(textField, slider), comboBox)); 

     this.meters = meters; 
     meters.addListener(fromMeters); 
     comboBox.valueProperty().addListener(fromMeters); 
     textField.textProperty().addListener(toMeters); 
     slider.valueProperty().bindBidirectional(meters); 
     fromMeters.invalidated(null); 
    } 

    /** 
    * Returns the multiplier for the currently selected unit of measurement. 
    */ 
    public double getMultiplier() { 
     return comboBox.getValue().multiplier; 
    } 
} 

/* 
* Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 
*/ 
package converter; 

import javafx.application.Application; 
import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Scene; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

/** 
* @see https://stackoverflow.com/a/31909942/230513 
* @see http://docs.oracle.com/javafx/2/swing/port-to-javafx.htm 
*/ 
public class Converter extends Application { 

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

    private final ObservableList<Unit> metricDistances; 
    private final ObservableList<Unit> usaDistances; 
    private final DoubleProperty meters = new SimpleDoubleProperty(1); 

    public Converter() { 
     //Create Unit objects for metric distances, and then 
     //instantiate a ConversionPanel with these Units. 
     metricDistances = FXCollections.observableArrayList(
      new Unit("Centimeters", 0.01), 
      new Unit("Meters", 1.0), 
      new Unit("Kilometers", 1000.0)); 

     //Create Unit objects for U.S. distances, and then 
     //instantiate a ConversionPanel with these Units. 
     usaDistances = FXCollections.observableArrayList(
      new Unit("Inches", 0.0254), 
      new Unit("Feet", 0.3048), 
      new Unit("Yards", 0.9144), 
      new Unit("Miles", 1609.34)); 
    } 

    @Override 
    public void start(Stage stage) { 
     stage.setScene(new Scene(new VBox(
      new ConversionPanel("Metric System", metricDistances, meters), 
      new ConversionPanel("U.S. System", usaDistances, meters)))); 
     stage.show(); 
    } 
} 
Смежные вопросы