2016-06-23 3 views
0

Я экспериментирую с пользовательскими элементами управления javafx, и у меня есть некоторые проблемы с ScatterChart. Что я хотел бы сделать, так это расширить стандартный ScatterChart, чтобы добавить свойство, которое я позже свяжу с видовым окном ImageView. Прежде чем приступать к связующим вещам (это тоже ново для меня), я попробовал минимальную реализацию, чтобы убедиться, что все правильно. Вот код обычая BindableChartJavaFX: custom ScatterChart

public class BindableChart<X,Y> extends ScatterChart<X,Y> 
    public BindableChart(@NamedArg("xAxis")Axis<X> xAxis,@NamedArg("yAxis")Axis<Y> yAxis){ 
     super(xAxis,yAxis); 
     FXMLLoader fxmlLoader = new FXMLLoader(
     getClass().getResource("/fxml/BindableChart.fxml")); 
     fxmlLoader.setRoot(this); 
     fxmlLoader.setController(this); 

     try { 
      fxmlLoader.load(); 
     } catch (IOException exception) { 
      throw new RuntimeException(exception); 
     } 
    } 
} 

и здесь его FXML код

<fx:root ...> 
    <xAxis> 
     <NumberAxis ... /> 
    </xAxis> 
    <yAxis> 
     <NumberAxis ... /> 
    </yAxis> 
</fx:root> 

Когда я пытаюсь запустить тестовое приложение, которое включает в себя класс BindableChart я получил PropertyNotFoundException о том, что свойство XAxis делает не существует или доступен только для чтения. Любые идеи?

ответ

1

Вы пытаетесь определить оси дважды: один раз в файле FXML и один раз в коде Java. Обратите внимание, что к тому моменту, когда вы вызываете load() на загрузчик FXML (т. Е. К моменту анализа файла FXML), оси уже определены с помощью вызова конструктора суперкласса.

Если вы собираетесь подкласса ScatterChart, вам в значительной степени придется инициализировать оси с помощью кода Java. Если вы хотите, чтобы оси были экземплярами NumberAxis, вы можете сделать это, создав их в вызове super(). Конечно, NumberAxis подкласс Axis<Number>, так что это заставляет BindableChart быть подклассом ScatterChart<Number, Number>, так что вы в конечном итоге с

package bindablechart ; 

import java.io.IOException; 

import javafx.fxml.FXMLLoader; 
import javafx.scene.chart.NumberAxis; 
import javafx.scene.chart.ScatterChart; 

public class BindableChart extends ScatterChart<Number, Number> { 
    public BindableChart(){ 
     super(new NumberAxis(), new NumberAxis()); 
     FXMLLoader fxmlLoader = new FXMLLoader(
       getClass().getResource("BindableChart.fxml")); 
     fxmlLoader.setRoot(this); 
     fxmlLoader.setController(this); 

     try { 
      fxmlLoader.load(); 
     } catch (IOException exception) { 
      throw new RuntimeException(exception); 
     } 
    } 
} 

и FXML становится

<?xml version="1.0" encoding="UTF-8"?> 

<fx:root xmlns:fx="http://javafx.com/fxml/1" type="bindablechart.BindableChart"> 

</fx:root> 

(На данный момент, FXML может стать полностью избыточным, я не знаю, что еще у вас есть, если что-нибудь.)

Тест для этой версии выглядит так:

package bindablechart; 

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.stage.Stage; 

public class BindableChartTest extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Scene scene = new Scene(new BindableChart()); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

Или вы можете включить его в другой файл FXML просто с

<BindingChart /> 

Если вы хотите, чтобы пользователь этого класса задают оси, вы можете сделать это, но вы до сих пор их удалить от FXML (так как пользователь с указанием их ...):

package bindablechart; 
import java.io.IOException; 

import javafx.beans.NamedArg; 
import javafx.fxml.FXMLLoader; 
import javafx.scene.chart.Axis; 
import javafx.scene.chart.ScatterChart; 

public class BindableChart<X,Y> extends ScatterChart<X, Y> { 
    public BindableChart(@NamedArg("xAxis") Axis<X> xAxis, @NamedArg("yAxis") Axis<Y> yAxis){ 
     super(xAxis, yAxis); 
     FXMLLoader fxmlLoader = new FXMLLoader(
       getClass().getResource("BindableChart.fxml")); 
     fxmlLoader.setRoot(this); 
     fxmlLoader.setController(this); 

     try { 
      fxmlLoader.load(); 
     } catch (IOException exception) { 
      throw new RuntimeException(exception); 
     } 
    } 
} 

с тем же файлом FXML, как описано выше.

В этом случае тест выглядит

package bindablechart; 

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.chart.NumberAxis; 
import javafx.stage.Stage; 

public class BindableChartTest extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     Scene scene = new Scene(
      new BindableChart<Number, Number>(new NumberAxis(), new NumberAxis())); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

или вы можете создать в FXML с

<?xml version="1.0" encoding="UTF-8"?> 

<?import javafx.scene.layout.StackPane?> 
<?import javafx.scene.chart.NumberAxis?> 
<?import bindablechart.BindableChart?> 

<StackPane xmlns:fx="http://javafx.com/fxml/1"> 
    <BindableChart> 
     <xAxis><NumberAxis/></xAxis> 
     <yAxis><NumberAxis/></yAxis> 
    </BindableChart> 
</StackPane> 
+0

Спасибо большое, я вижу, что я действительно помчался мое изучение всей FXML части , –

+0

Я играл с кодом, и у меня все еще есть проблемы с xAxis и yAxis. Когда я использую Netbeans для создания FXML и пытаюсь настроить BindableChart (вторая стратегия, предложенная @James_D), IDE правильно подсказывает мне как возможное поле/переменную xAxis и yAxis. Однако, если я выбираю любой из них, я получаю сообщение об ошибке, заявляя, что класс не поддерживает эти свойства. –

+0

Возможно, ваш IDE и/или Scene Builder не понимают @NamedArg. Это довольно новое дополнение к API и не очень хорошо (я вообще-то) документировано. –

Смежные вопросы