Во-первых, вам нужно иметь четкое представление о scope
и поведении ключевого слова this
в контексте scope
.
this
& amp; scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
вкратце, глобальная область относится к объекту window.Variables, объявленные в глобальной области, доступны из любого места. С другой стороны, область функций находится внутри функции .variable, объявленный внутри функции, не может быть доступен из внешнего мира в обычном режиме. this
ключевое слово в глобальной области относится к объекту window. Внутренняя функция this
также относится к объекту window.So this
всегда будет ссылаться на окно до тех пор, пока мы найдем способ манипулировать this
, чтобы указать контекст по собственному выбору.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Различные способы управления this
внутри функций обратного вызова:
Здесь У меня есть функция-конструктор, называемая Person. Он имеет свойство, называемое name
, и четыре метода, называемые sayNameVersion1
, sayNameVersion2
, sayNameVersion3
, sayNameVersion4
. Все четыре из них имеют одну конкретную задачу. Заберите обратный вызов и вызовите его. Обратный вызов имеет конкретную задачу, которая заключается в регистрации свойства имени экземпляра функции конструктора Person.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Теперь давайте создадим экземпляр из конструктора person и вызывать разные версии sayNameVersionX
(X относится к 1,2,3,4) методу с niceCallback
, чтобы увидеть, как много способов управления this
внутри обратного вызова ссылаться на person
.
var p1 = new Person('zami') // create an instance of Person constructor
Что нужно сделать, это создать новую функцию с ключевым словом this
, установленным на предоставленное значение.
sayNameVersion1
и sayNameVersion2
используют bind для управления this
функции обратного вызова.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
сначала связывают this
с обратным вызовом внутри самого метода. для второго обратного вызова передается связанный с ним объект.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
first argument
в call
используется как функция this
внутри функции, которая вызывается с call
, прикрепленной к ней.
sayNameVersion3
использует call
для управления this
], чтобы ссылаться на созданный нами объект person, а не на объект окна.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
и он называется следующим:
p1.sayNameVersion3(niceCallback)
Как и в call
, первый аргумент apply
относится к объекту, который будет обозначен ключевым словом this
.
sayNameVersion4
использует apply
для манипулирования this
для обращения к объекту человека
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
, и он называется следующим. Просто передается обратный вызов,
p1.sayNameVersion4(niceCallback)
класс javafx.scene.Node имеет пару методов setUserData (Object) и Object getUserData ()
, которые вы могли бы использовать для добавления вашей информации в узел.
So , вы можете вызвать page.setUserData (info);
И контроллер может проверить, задана ли информация. Кроме того, вы можете использовать ObjectProperty для пересылки данных назад, если это необходимо.
Соблюдайте документацию здесь: http://docs.oracle.com/javafx/2/api/javafx/fxml /doc-files/introduction_to_fxml.html Перед фразой «В первой версии handleButtonAction () помечен с помощью @FXML, чтобы разрешить разметку, определенную в документе контроллера, вызвать ее. Во втором примере поле кнопки аннотируется, чтобы позволить загрузчику устанавливать его значение. Метод initialize () аналогично аннотируется. "
Итак, вам нужно связать контроллер с узлом и установить пользовательские данные для узла.
Вы должны создать один класс контекста.
public class Context {
private final static Context instance = new Context();
public static Context getInstance() {
return instance;
}
private Connection con;
public void setConnection(Connection con)
{
this.con=con;
}
public Connection getConnection() {
return con;
}
private TabRoughController tabRough;
public void setTabRough(TabRoughController tabRough) {
this.tabRough=tabRough;
}
public TabRoughController getTabRough() {
return tabRough;
}
}
Вам нужно просто установить экземпляр контроллера при инициализации с помощью
Context.getInstance().setTabRough(this);
, и вы можете использовать его из всего приложение только с помощью
TabRoughController cont=Context.getInstance().getTabRough();
Теперь вы можете передать параметр любому контроллеру из всего приложения.
Это WORKS ..
Помните, что в первый раз, когда вы напечатаете передаваемое значение, вы получите нуль, вы можете использовать его после загрузки Windows, то же самое для всего, что вы хотите кодировать для любого другого компонента.
Первый контроллер
blockquote>try { Stage st = new Stage(); FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/inty360/free/form/MainOnline.fxml")); Parent sceneMain = loader.load(); MainOnlineController controller = loader.<MainOnlineController>getController(); controller.initVariable(99L); Scene scene = new Scene(sceneMain); st.setScene(scene); st.setMaximized(true); st.setTitle("My App"); st.show(); } catch (IOException ex) { Logger.getLogger(LoginController.class.getName()).log(Level.SEVERE, null, ex); }
Другой контроллер
blockquote>public void initVariable(Long id_usuario){ this.id_usuario = id_usuario; label_usuario_nombre.setText(id_usuario.toString()); }
Вот пример использования контроллера, введенного Guice.
/**
* Loads a FXML file and injects its controller from the given Guice {@code Provider}
*/
public abstract class GuiceFxmlLoader {
public GuiceFxmlLoader(Stage stage, Provider<?> provider) {
mStage = Objects.requireNonNull(stage);
mProvider = Objects.requireNonNull(provider);
}
/**
* @return the FXML file name
*/
public abstract String getFileName();
/**
* Load FXML, set its controller with given {@code Provider}, and add it to {@code Stage}.
*/
public void loadView() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource(getFileName()));
loader.setControllerFactory(p -> mProvider.get());
Node view = loader.load();
setViewInStage(view);
}
catch (IOException ex) {
LOGGER.error("Failed to load FXML: " + getFileName(), ex);
}
}
private void setViewInStage(Node view) {
BorderPane pane = (BorderPane)mStage.getScene().getRoot();
pane.setCenter(view);
}
private static final Logger LOGGER = Logger.getLogger(GuiceFxmlLoader.class);
private final Stage mStage;
private final Provider<?> mProvider;
}
Вот конкретная реализация загрузчика:
public class ConcreteViewLoader extends GuiceFxmlLoader {
@Inject
public ConcreteViewLoader(Stage stage, Provider<MyController> provider) {
super(stage, provider);
}
@Override
public String getFileName() {
return "my_view.fxml";
}
}
Обратите внимание, что этот пример загружает представление в центр BoarderPane, который является корнем сцены в рабочей области. Это не относится к примеру (деталь реализации моего конкретного варианта использования), но решил оставить его, поскольку некоторые из них могут оказаться полезными.
Вы можете использовать публичный наблюдаемый список для хранения общедоступных данных или просто создать общедоступный метод настройки для хранения данных и получения из соответствующего контроллера
Ниже приведен пример передачи параметров в документ fxml через пространство имен.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1">
<BorderPane>
<center>
<Label text="$labelText"/>
</center>
</BorderPane>
</VBox>
Определить значение External Text
для переменной пространства имен labelText
:
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class NamespaceParameterExampleApplication extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
final FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("namespace-parameter-example.fxml"));
fxmlLoader.getNamespace()
.put("labelText", "External Text");
final Parent root = fxmlLoader.load();
primaryStage.setTitle("Namespace Parameter Example");
primaryStage.setScene(new Scene(root, 400, 400));
primaryStage.show();
}
}
FXMLLoader.CONTROLLER_KEYWORD
, FXMLLoader.LOCATION_KEY
, FXMLLoader.RESOURCES_KEY
и любая строка, используемая как значение для атрибута fx:id
.
– fabian
1 February 2016 в 23:55
Я понимаю, что это очень старое сообщение и уже есть отличные ответы, но я хотел сделать простой MCVE, чтобы продемонстрировать один такой подход и позволить новым кодеру быстро увидеть концепцию в действии.
blockquote>В этом примере мы будем использовать 5 файлов:
- Main.java - просто используется для запуска приложения и вызова первого контроллера.
- Controller1.java - контроллер для первого макета FXML.
- Controller2.java - контроллер для второго макета FXML.
- Layout1.fxml - макет FXML для первого сцена.
- Layout2.fxml - макет FXML для второй сцены.
Все файлы перечислены полностью в нижней части этого сообщения.
Цель: показать переданные значения от
Controller1
доController2
и наоборот.Поток программы:
- Первая сцена содержит
TextField
,Button
иLabel
. Когда щелчокButton
щелкнут, второе окно загружается и отображается, включая текст, введенный вTextField
.- Внутри второй сцены есть также
TextField
,Button
, иLabel
.Label
отобразит текст, введенный вTextField
на первой сцене.- При вводе текста во второй сцене
TextField
и нажатииButton
первая сценаLabel
сцены обновлен, чтобы показать введенный текст.Это очень простая демонстрация и, безусловно, может означать некоторое улучшение, но должна сделать концепцию очень понятной.
Сам код также комментируется некоторые детали того, что происходит и как.
КОД
blockquote>Main.java:
import javafx.application.Application; import javafx.stage.Stage; public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { // Create the first controller, which loads Layout1.fxml within its own constructor Controller1 controller1 = new Controller1(); // Show the new stage controller1.showStage(); } }
Controller1.java:
import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.stage.Stage; import java.io.IOException; public class Controller1 { // Holds this controller's Stage private final Stage thisStage; // Define the nodes from the Layout1.fxml file. This allows them to be referenced within the controller @FXML private TextField txtToSecondController; @FXML private Button btnOpenLayout2; @FXML private Label lblFromController2; public Controller1() { // Create the new stage thisStage = new Stage(); // Load the FXML file try { FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout1.fxml")); // Set this class as the controller loader.setController(this); // Load the scene thisStage.setScene(new Scene(loader.load())); // Setup the window/stage thisStage.setTitle("Passing Controllers Example - Layout1"); } catch (IOException e) { e.printStackTrace(); } } /** * Show the stage that was loaded in the constructor */ public void showStage() { thisStage.showAndWait(); } /** * The initialize() method allows you set setup your scene, adding actions, configuring nodes, etc. */ @FXML private void initialize() { // Add an action for the "Open Layout2" button btnOpenLayout2.setOnAction(event -> openLayout2()); } /** * Performs the action of loading and showing Layout2 */ private void openLayout2() { // Create the second controller, which loads its own FXML file. We pass a reference to this controller // using the keyword [this]; that allows the second controller to access the methods contained in here. Controller2 controller2 = new Controller2(this); // Show the new stage/window controller2.showStage(); } /** * Returns the text entered into txtToSecondController. This allows other controllers/classes to view that data. */ public String getEnteredText() { return txtToSecondController.getText(); } /** * Allows other controllers to set the text of this layout's Label */ public void setTextFromController2(String text) { lblFromController2.setText(text); } }
Controller2.java:
import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.stage.Stage; import java.io.IOException; public class Controller2 { // Holds this controller's Stage private Stage thisStage; // Will hold a reference to the first controller, allowing us to access the methods found there. private final Controller1 controller1; // Add references to the controls in Layout2.fxml @FXML private Label lblFromController1; @FXML private TextField txtToFirstController; @FXML private Button btnSetLayout1Text; public Controller2(Controller1 controller1) { // We received the first controller, now let's make it usable throughout this controller. this.controller1 = controller1; // Create the new stage thisStage = new Stage(); // Load the FXML file try { FXMLLoader loader = new FXMLLoader(getClass().getResource("Layout2.fxml")); // Set this class as the controller loader.setController(this); // Load the scene thisStage.setScene(new Scene(loader.load())); // Setup the window/stage thisStage.setTitle("Passing Controllers Example - Layout2"); } catch (IOException e) { e.printStackTrace(); } } /** * Show the stage that was loaded in the constructor */ public void showStage() { thisStage.showAndWait(); } @FXML private void initialize() { // Set the label to whatever the text entered on Layout1 is lblFromController1.setText(controller1.getEnteredText()); // Set the action for the button btnSetLayout1Text.setOnAction(event -> setTextOnLayout1()); } /** * Calls the "setTextFromController2()" method on the first controller to update its Label */ private void setTextOnLayout1() { controller1.setTextFromController2(txtToFirstController.getText()); } }
Layout1.fxml:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.Insets?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.VBox?> <AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1"> <VBox alignment="CENTER" spacing="10.0"> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> </padding> <Label style="-fx-font-weight: bold;" text="This is Layout1!"/> <HBox alignment="CENTER_LEFT" spacing="10.0"> <Label text="Enter Text:"/> <TextField fx:id="txtToSecondController"/> <Button fx:id="btnOpenLayout2" mnemonicParsing="false" text="Open Layout2"/> </HBox> <VBox alignment="CENTER"> <Label text="Text From Controller2:"/> <Label fx:id="lblFromController2" text="Nothing Yet!"/> </VBox> </VBox> </AnchorPane>
Layout2.fxml:
<?xml version="1.0" encoding="UTF-8"?> <?import javafx.geometry.Insets?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.VBox?> <AnchorPane xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1"> <VBox alignment="CENTER" spacing="10.0"> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/> </padding> <Label style="-fx-font-weight: bold;" text="Welcome to Layout 2!"/> <VBox alignment="CENTER"> <Label text="Text From Controller1:"/> <Label fx:id="lblFromController1" text="Nothing Yet!"/> </VBox> <HBox alignment="CENTER_LEFT" spacing="10.0"> <Label text="Enter Text:"/> <TextField fx:id="txtToFirstController"/> <Button fx:id="btnSetLayout1Text" mnemonicParsing="false" text="Set Text on Layout1"/> </HBox> </VBox> </AnchorPane>