Skip to content

an Application Framework for implementing the MVVM Pattern with JavaFX

License

Notifications You must be signed in to change notification settings

danielwinter/mvvmFX

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

#mvvm(fx)#

mvvm(FX) is an application framework for implementing the MVVM pattern with JavaFX.

MVVM is a WPF ( .NET ) specific pattern. WPF and JavaFX does have parallels like Databinding and descriptive UI declaration (FXML/XAML). That is the reason I tried to adopt best practices of the development with WPF.

#####Short overview##### You have 2 options to implement MVVM with JavaFX. It depents whether you want to use JavaFX-Properties in your model or not.

If no, you should go for the first image.

Drawing

Drawing

If yes go for the second image. If you use Properties in your model, you have the benefit of using their databinding and the observer mechanism.

#####Further information#####

Short description

Long description

#The Framework# ##How to implement## Drawing

##Parts## ###2 new Custom Application Type### ####MvvmGuiceApplication instead of javafx.Application for Guice support####

public class Starter extends MvvmGuiceApplication {

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

	@Override
	public void start(final Stage stage) throws Exception {
	}

	@Override
	public void initGuiceModules(List<Module> modules) throws Exception {
		//add Guice Modules if you want
	}

}

####MvvmCdiApplication instead of javafx.Application for CDI-Weld support####

public class Starter extends MvvmCdiApplication{
	
	public static void main(String...args){
		launch(args);
	}
}

in addition you have to provide an App class, which receives the StartUp Event of the weld-container

	public class App {

	// Get the MVVM View Loader
	@Inject
	private ViewLoader viewLoader;

	/**
	 * Listen for the {@link StartupEvent} and create the main scene for the
	 * application.
	 */
	public void startApplication(@Observes StartupEvent startupEvent) {
		Stage stage = startupEvent.getPrimaryStage();

		final ViewTuple tuple = viewLoader
				.loadViewTuple(MainContainerView.class);
		// Locate View for loaded FXML file
		final Parent view = tuple.getView();

		final Scene scene = new Scene(view);
		stage.setScene(scene);
		stage.show();
		}
	}
}

MVVM Base Classes

de.saxsys.jfx.mvvm.base

This package contains the base classes for a View and a ViewModel. The View is the code behind (Controller class) of a FXML file and implements the interface javafx.fxml.Initializable. Every View does have a reference to exactly one ViewModel which is declared by using generics.

Example for a View and the belonging ViewModel

public class PersonView extends View<PersonViewModel>{
...
}

If you create View the belonging ViewModel will be created automatically. You can get the instance by using getViewModel() on the View Class

public class PersonViewModel implements ViewModel{
...
}

de.saxsys.jfx.mvvm.base.viewmodel.util

de.saxsys.jfx.mvvm.base.viewmodel.util.itemlist

This class provides a ItemList which maps from an Object representation to a String. You can use this to map lists from the model to the view on an abstract way. In addition there is a SelectableItemList which provides an addition funcitonality to select an index by setting the index value OR an object in the object list. __ incomplete documentation __

Extended FXML Loader

de.saxsys.jfx.mvvm.viewloader

The ViewLoader loads tuples of a given FXML file. The tuple carries the code behind part (controller class) and the loaded node which is represented by the FXML.

You have two options to use the ViewLoader

Use ViewLoader with resource path#####
@Inject
private ViewLoader viewLoader;

[…]

viewLoader.loadViewTuple("resource/path/to/FXML")
Use ViewLoader by a given code behind class#####

The FXML File which is related to the code behind part has to be in the corresponding resource folder and has to have the same name like the code behind!

If the code behind class is de.saxsys.PersonView the FXML has to be in the resource folder de/saxsys and has to be named PersonView.fxml.

@Inject
private ViewLoader viewLoader;

[…]

viewLoader.loadViewTuple(CodeBehind.class);

Notifications

de.saxsys.jfx.mvvm.notifications

This package provides an observer mechanism that you can use to send notifications which are identified by a string throught all of the application. You can pass objects with an notification.

#####Listen for a notification####

@Inject
private NotificationCenter notificationCenter;

[...]

notificationCenter.addObserverForName("someNotification",
			new NotificationObserver() {
			
			@Override
			public void receivedNotification(String key, Object... objects) {
				System.out.println("Received Notification: "+ key + "With object count:" +objects.length);
			}
		}
	);
Send a notification
@Inject
private NotificationCenter notificationCenter;

[...]

notificationCenter.postNotification("someNotification");

notificationCenter.postNotification("someNotification","arg1",new CustomArgTwo());

SizeBindings

de.saxsys.jfx.mvvm.utils.SizeBindings

We often had the case, that an element should have the same size or at least the width of another element. You would have to do it on this way:

a.minWidthProperty().bind(b.widthProperty());
a.minheightProperty().bind(b.heightProperty())
a.maxWidthProperty().bind(b.widthProperty());
a.maxheightProperty().bind(b.heightProperty())

With the SizeBindings class you can do instead things like

SizeBindings.bindSize(a,b);

ListenerCleaner

de.saxsys.jfx.mvvm.utils.ListenerCleaner

This class is used for housekeeping of listeners. If you have an element which registers Listeners to a long living Property you have to remove the listener by hand when you want to throw the element away.

You can use the Interface ICleanable to make your element cleanable. You should call the clean function of the element, when you remove it from the scene graph / throw it away.

public class CustomPane extends Pane implements ICleanable{

@Inject
ListenerCleaner cleaner;

	public CustomPane(SomeLongLiving longLiving){
		ChangeListener<Double> listener = new ChangeListener().......
	
		longLiving.fooProperty().addListener(listener);
		cleaner.put(longLiving.fooProperty(),listener);
	}
	
	@Override
	public void clean(){
		//Kills all Listeners
		cleaner.clean();
	}

}

About

an Application Framework for implementing the MVVM Pattern with JavaFX

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published