JavaFX z Arią - powrót do strony głównej

Użycie JavaFXBuilderFactory

Domyślna JavaFXBuilderFactory

Jeżeli klasy, które tworzymy, spełniają wymagania JavaBean – setters i getters oraz obecność konstruktora bezparametrowego, to z obiektami tych klas nie mamy żadnych problemów.

Klasa User.java
package codes;
public class User{
	private String nick;
	private Integer pesel;
	public User(String nick, Integer pesel){
		this.nick = nick;
		this.pesel = pesel;
	}
	//domyślny konstruktor
	public User(){
		this(null, null);
	}
	public String getNick() {
		return nick;
	}
	public void setNick(String nick) {
		this.nick = nick;
	}
	public Integer getPesel() {
		return pesel;
	}
	public void setPesel(Integer pesel) {
		this.pesel = pesel;
	}
	@Override
	public String toString() {
		return "nick=" + nick + ", pesel=" + pesel;
	}
}

Powyższa klasa ma settersy i gettersy oraz bezparametrowy konstruktor. Obiekty tej klasy mogą być użyte w plikach FXML.

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

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import codes.User?>
<?import javafx.collections.FXCollections?>

<VBox xmlns:fx="http://javafx.com/fxml">
	<Label fx:id="lab1" text="Lista użytkowników." />
	<ListView>
		<items>
			<FXCollections fx:factory="observableArrayList">
				<User nick="Jacek" pesel="52" />
				<User nick="Ula" pesel="83" />
				<User nick="Mirka" pesel="53" />
			</FXCollections>
		</items>
	</ListView>

</VBox>

Utworzyliśmy obiekty klasy User i dodaliśmy je do kolekcji.

Listing10_creating_user.java

Klasa uruchamiająca.

package codes;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.net.URL;
public class Listing10_creating_user extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        try {
            URL fxmlUrl = this.getClass().getClassLoader()
                    .getResource("resources/listing10_creating_user.fxml");
            VBox root = fxmlUrl != null ? FXMLLoader.load(fxmlUrl) : new VBox();
            Scene scene = new Scene(root, 150, 150);
            stage.setScene(scene);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Po uruchomieniu zobaczymy:

Widok kontrolki po uruchomieniu klasy
Widok kontrolki po uruchomieniu klasy

Implementacja BuilderFactory

Gdy nasza klasa nie spełnia wymogów JavaBean, a w szczególności nie ma domyślnego konstruktora albo jest typową klasą immutable, domyślna JavaFXBuiderFactory nie poradzi sobie z utworzeniem obiektu. Przykładem takiej klasy jest User2.

Klasa User2.java
package codes;
public class User2 {
	private String nick;
	private Integer pesel;
	public User2(String nick, Integer pesel){
		this.nick = nick;
		this.pesel = pesel;
	}
	public String getNick() {
		return nick;
	}
	public Integer getPesel() {
		return pesel;
	}

	@Override
	public String toString() {
		return "nick=" + nick + ", pesel=" + pesel;
	}
}

Teraz musimy implementować interfejs Builder aby pokazać jak zbudować obiekt klasy User2 oraz implementować interfejs BuilderFactory, aby wykorzystać budowniczego do budowy obiektów.

Klasa User2BuilderFatory.java
package codes;

import javafx.fxml.JavaFXBuilderFactory;
import javafx.util.Builder;
import javafx.util.BuilderFactory;

public class User2BuilderFactory implements BuilderFactory {

	private final JavaFXBuilderFactory defaultBuilderFactory = new JavaFXBuilderFactory();

	@Override
	public Builder<?> getBuilder(Class<?> type) {
		return (type==User2.class ? new User2Builder() : defaultBuilderFactory.getBuilder(type));
	}

	public static class User2Builder implements Builder<User2> {
		private String nick;
		private Integer pesel;
		public void setNick(String nick) {
			this.nick = nick;
		}
		public void setPesel(Integer pesel) {
			this.pesel = pesel;
		}
		public String getNick() {
			return nick;
		}
		public Integer getPesel() {
			return pesel;
		}
		@Override
		public String toString() {
			return "nick=" + nick + ", pesel=" + pesel;
		}
		@Override
		public User2 build() {
			return new User2(nick, pesel);
		}
	}
}
listing10_creating_user2.fxml

Tworzymy plik FXML używający obiektu User2.

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

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import codes.User2?>
<?import javafx.collections.FXCollections?>

<VBox xmlns:fx="http://javafx.com/fxml">
	<Label fx:id="lab1" text="Lista użytkowników." />
	<ListView>
		<items>
			<FXCollections fx:factory="observableArrayList">
				<User2 nick="Jacek" pesel="52" />
				<User2 nick="Ula" pesel="83" />
				<User2 nick="Mirka" pesel="53" />
			</FXCollections>
		</items>
	</ListView>

</VBox>

Chociaż analizator IntelliJ IDEA podkreśli atrybuty na czerwono sygnalizując, że coś jest nieprawidłowo, to wszystko jest prawidłowo i kod uruchomi się bez problemów.

Listing10_creating_user2.java
package codes;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.net.URL;

public class Listing10_creating_user2 extends Application {
    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage stage) {
        try {
            URL fxmlUrl = this.getClass().getClassLoader()
                   .getResource("resources/listing10_creating_user2.fxml");
            VBox root = fxmlUrl != null ? FXMLLoader.load(fxmlUrl,null, new User2BuilderFactory()) : new VBox();
            Scene scene = new Scene(root, 150, 150);
            stage.setScene(scene);
            stage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Po uruchomieniu zobaczymy (tak jak poprzednio):

Widok kontrolki po uruchomieniu klasy
Widok kontrolki po uruchomieniu klasy