adambien / afterburner.fx Goto Github PK
View Code? Open in Web Editor NEWThe Opinionated Un-Framework For Java FX Applications
Home Page: http://afterburner.adam-bien.com
The Opinionated Un-Framework For Java FX Applications
Home Page: http://afterburner.adam-bien.com
Hi Adam,
in my Apps I use InjectionProvider.setModelOrService to use Mocks of Presenter-Attributes in my TestFX tests.
But now I want to release my App, so I need an afterburner.fx release which includes InjectionProvider.setModelOrService.
Is it possible to make an release of afterburner.fx containing this feature and upload it to maven central?
Best regards
Andreas
Hi Adam,
another week, another idea ;)
This week we try to use the "import custom control from JAR" feature of Scene Builder 2.
This works for e.g. the ControlsFX controls. But it's not possible for an afterburner.fx module .
Scene Builder scans all class-files in a selected jar, and checks if it is a sub-class of Node (e.g. Node, Parent or AnchorPane) and if no Exception is thrown when invoking the default-constructor. This feature is stil a little bit buggy, but basically very useful.
The following afterburner.fx-module "wrapper" works but can't be imported via JAR-Importer in Scene Builder 2.0 due to a Bug in Scene Builder:
public class TimeChartControl extends AnchorPane {
TimeChartControlView view;
public TimeChartControl() {
view = new TimeChartControlView();
AnchorPane.setBottomAnchor(view.getView(), 0.0);
AnchorPane.setLeftAnchor(view.getView(), 0.0);
AnchorPane.setRightAnchor(view.getView(), 0.0);
AnchorPane.setTopAnchor(view.getView(), 0.0);
getChildren().setAll(view.getView());
}
public TimeChartControlPresenter getPresenter() {
return (TimeChartControlPresenter) view.getPresenter();
}
}
This wrapper can be used as custom control in any fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import de.fhg.iwes.javafx.vpp.frontend.module.timechartcontrol.*?>
<?import javafx.scene.layout.*?>
<?scenebuilder-stylesheet powerplantdetails.css?>
<AnchorPane maxHeight="-1.0" maxWidth="-1.0" minHeight="-1.0" minWidth="-1.0" prefHeight="-1.0" prefWidth="-1.0" xmlns:fx="http://javafx.com/fxml/1"
xmlns="http://javafx.com/javafx/2.2" fx:controller="de.fhg.iwes.javafx.vpp.frontend.module.details.powerplantdetails.PowerPlantDetailsPresenter">
<children>
<TimeChartControl fx:id="timeChartControl" />
</children>
</AnchorPane>
Scene Builder stil opens the fxml but shows a little warning at the custom control (TimeChartControl in my case). I think this will be solved in a new Scene Builder version.
In the application the custom control is loaded properly.
Now my idea:
Actually the wrapper which I implemented is basically the FXMLView and also the view in the meaning of MVP. The difference is that FXMLView does not is the view but provides the view (via getView).
So what do you think about making FXMLView to the view instead of using it as a view-provider?
FXMLView could extend e.g. AnchorPane like in my example. The getView method could stil return the root-Node of the loaded fxml. So there is no API-break.
The result will be, that everybody will be able to include afterburner.fx-module-views as a custom control in fxml without using a wrapper.
I am trying to instantiate a view
Criterium newValue = ...;
ValueView valueView = new ValueView (s ->
{
if ("criterium".equals (s))
{
return newValue;
}
return null;
});
with provided injection context. ValuePresenter
has a member Criterium criterium
wgich should be injected the instance supplied by the context. But instead I get an exception, because Criterium
has no no-args-constructor. Instead of using the injection context
public static <T> T instantiatePresenter(Class<T> clazz, Function<String, Object> injectionContext) {
Object presenter = registerExistingAndInject(instanceSupplier.apply(clazz));
...
tries an injection of the presenter and subsequently an injection of members. All without usage of the context.
Later instantiatePresenter(Class<T>, Function<String, Object>)
loops over the members again and then (but too late) uses the injection context.
I can work around by using setters on the presenter, or supplying a no-args-constructor for Criterium
, that way criterium would be replaced by the supplied instance later (but that feels wrong).
Is it working as intended?
Hello Adam,
I like your approach, with the automatic loading of FXML etc.
I started with the Spring-Boot with FX Integration Example from Thomas Darimont, a Spring Developer.
See: https://github.com/thomasdarimont/spring-labs/tree/master/spring-boot-javafx
But we have the need in my project to separate our controller, view etc. by *.fxml and *.css files. Because then we can give out the layout tasks to our specialised UI/UX team.
But I completely dislike to write for every view, and subviews a own XML Loader. Your afterburner.fx project has solved this already in the FXMLView class. So I would love to combine it and make an example project out of it.
Could you please give me a hint how I can combine that!? Because I at the moment haven't found any way. And the examples which I saw only from you are the way over your own DI @Inject implemenetation.
Thanks in advanced
Tommy Ziegler
Hi Adam,
playing arround with creating Views I found out that slow initialize methods (Thread.sleep(xxx)) in the view classes block the Platform Thread.
I assume that the getViewAsync(Consumer consumer) methode should build the node in background and only add the Parent in the Platform Thread. Therfore I changed the methode to:
public void getViewAsync(Consumer<Parent> consumer) {
PARENT_CREATION_POOL.execute(() -> {
Parent v = getView();
Platform.runLater(() -> consumer.accept(v));
});
}
Right?
Hi Adam,
I have following understanding of one goal of the afterburner.fx framework:
-> The complete information of a presentation-module is gathered in one package (View, Presenter, FXML, StyleSheet, Localization)
--> No influence of external files is needed for the View respectively no influence of external files is wanted... (except model or services)
There is one thing that still influences the view implicit, the CSS Inheritance:
http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html#introinheritance
https://javafx-jira.kenai.com/browse/RT-22622
-> Affects: Font, Effects, Text-Alignment and Cursor
Do you think that there is need for explicit inheritance prevention to ensure that the presentation-module look similar in every parent-module or style?
Is is possible to have groovy compatible version of afterburner.fx?
Is it still wip? See #29. Would make developing much faster.
There is a problem that occurs only when running jar app.
If an .fxml file name is CamelCase, e.g. "myView.fxml" - file (resource) will not be found and null will be returned.
Class FXMLView, init method, line:
this.resource = clazz.getResource(conventionalName);
I extend my view class from additional class that extends FXMLView, but I do not know if this is relevant.
Best regards :)
Ernest
Hi Adam,
I think it would be interesting a provider of instances with qualifier (@qualifier).
In this way, we could also inject in interfaces with choosing an implementation.
In my experimental project, I did an implementation of it, but do not know how it would implement the afterburner.fx
My experimental project: https://github.com/jean-merelis/coffeepot-fx-di
Do you have an updated sample application or is the one on the homepage still correct?
Furthermore, I've got a question concerning the example on the homepage: Where does NotesStore store;
come from? The comment above that line says it would be automatically injected, but from where? I cannot see a single line of code which registers such a dependency.
I would be grateful for any hints you are able to provide.
Hi Adam,
the current implementation of the InjectionProvider does not Inject fields in superclasses. I added an 'addSuperclasses' method and a -for each- for the classes in the 1.4-SNAPSHOT (in my eclipse) and then it worked for me.
...This is only my personal hotfix ;)
static void injectMembers(final Object instance) {
List<Class<?>> clazzes = new ArrayList<Class<?>>();
addSuperclasses(clazzes, instance.getClass());
for (Class<?> iClazz : clazzes) {
Field[] fields = iClazz.getDeclaredFields();
for (final Field field : fields) {
if (field.isAnnotationPresent(Inject.class)) {
Class<?> type = field.getType();
if (type.isAssignableFrom(String.class)) {
String key = field.getName();
String value = System.getProperty(key);
String configuration = getProperty(iClazz, key);
if (configuration != null) {
value = configuration;
}
injectIntoField(field, instance, value);
} else {
final Object target = instantiateModel(type);
injectIntoField(field, instance, target);
}
}
}
}
}
static List<Class<?>> addSuperclasses(final List<Class<?>> clazzes, final Class<?> clazz) {
clazzes.add(clazz);
Class<?> superclass = clazz.getSuperclass();
if (superclass != null) {
addSuperclasses(clazzes, superclass);
}
return clazzes;
}
Hi,
the injection of the resource bundle only works if I add the following line to the pom:
<include>*/.properties</include>
This should be added to the pom of afterburner.fx and followme.fx
I´ve finished my app and everything is running as it should via eclipse. I´m using an ant script to build the app, but whenever i try to run it, i got: exception in application start method. And exception is cused by: Location is not set. (Probably an FXML load error)
Is there a way to log the the entire exception so i can find out what is causing it and fix it? Or maybe there is a step that i´m not doing to deploy it???
Insofar as you can't call root presenter from other presenters without new instance my issue is following:
class RootPresenter implements Initializable {
@FXML MediaView logo;
@FXML StackPane content;
ProfileView profileView;
public void initialize(URL location, ResourceBundle resources) {
profileView = new ProfileView();
profileView.getPresenter() //Magic thing to call Presenter's constructor o_0
//other stuff
}
public handleProfileButton() {
content.getChildren().add(profileView.getView());
}
}
class ProfilePresenter {
//@FXML fields...
public handleOtherNewSceneButton() {
how to replace this stuff in the RootPresenter.content to new scene????
}
}
Or any other ways to manipulate screens?
I really do not want to use DataFX because of its broken IoC feature
A few controls currently does not allow their instantiation outside the FXApplication Thread (e.g. Tooltip and WebView) (https://javafx-jira.kenai.com/browse/RT-25127).
So the asynchronous FXML loading should be optional.
In the release 1.7.0, I noticed the presence of the following packages:
Both packages only contain .css/.fxml/.properties files. I think they were wrongly pushed because they seem to contain nothing "interesting" for us, users of the Afterburner.fx library.
Am I right? If so, they should be removed.
Regards
Hi,
I'm new to JavaFX and right at the beginning I found your Framework. Very clean and easy to use, thanks for that.
To test my views with a framework like TestFX I would like to mock my backend services. What I miss is a method to add a mock to the static list of modelsAndServices. Something like:
public static void addModelOrService(Class realClass, Object anObject) {
modelsAndServices.put(realClass, anObject);
}
Regards
Christian
I don't like to have the fully qualified name of the Presenter within the fxml file.
How about letting the FXMLView set the Controller / Presenter automatically?
foo.fxml
FooView.java
FooPresenter.java
That would make moving / renaming much easier.
Hi Adam,
our Control System UI is a continuous operating UI (24/7). So we tested our UI in continuous operation. The memory usage increases ongoing.
After investigating the memory leak we found the reason:
The presenters attribute in InjectionProvider stores every ever created presenter (and hence all JavaFX components referenced within the presenter). But we have a dynamic UI with popus, tooltips, details and so forth. In our application every of the UI-components is based on afterburner.fx so all of the temporary UI-components are stored forever.
Currently the only possible solution at runtime is to call InjectionProvider.forgetAll() ... but that is no option for us, because we need the modelsAndServices continuously.
Two suggestions for a solution:
Best regard
Andreas
I have he following code:
public class MainWindowPresenter implements Initializable {
...
@Inject
PedidoPresenter pedPresenter;
ObservableList<Pedido> pedidosAbertos = FXCollections.observableArrayList();
...
public void listPedidosClickEvent() {
lstPedidosAbertos.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
pedPresenter.abrirTela();
pedPresenter.carregaPedidoDaLista(newValue.getId());
});
}
With method abrirTela() from PedidoPresenter, its open a new window as expected but every class attribute marked with @FXML annotation, is null. This also happens if i instantiate PedidoPresenter manually.
Hi Adam,
I have a little improvement suggestion for the method instantiateModelOrService:
public static <T> T instantiateModelOrService(Class<T> clazz) {
With the current API there has to be a cast:
MyClassToInject myClassToInject = (MyClassToInject) Injector.instantiateModelOrService(MyClassToInject.class);
With the suggested API the call is a little bit shorter:
MyClassToInject myClassToInject = Injector.instantiateModelOrService(MyClassToInject.class);
Best regards
Hi,
I have a lot of lines in my console, coming from the system-property injection:
System property: x X
Key: x X
System property: y Y
Key: y Y
and so forth...
Could the console outputs be removed?
I may be wrong but it seems to me that the code in the getView() method could be replaced by:
/**
* Initializes the view synchronously and invokes and passes the created
* parent Node to the consumer within the FX UI thread.
*
* @param consumer - an object interested in received the Parent as callback
*/
public void getView(Consumer<Parent> consumer) {
//Current code
//Supplier<Parent> supplier = this::getView;
//Executor fxExecutor = Platform::runLater;
//CompletableFuture.supplyAsync(supplier, fxExecutor).thenAccept(consumer);
// Simpler version
Platform.runLater(() -> pConsumer.accept(mGetRoot()));
}
It would have exactly the same behaviour but feels much simpler...
Hi Adam,
I have some code in my View and I need access to the ResourceBundle of the View. My workaround is to get it via a getter from the Presenter.
It would be nice if the ResourceBundle of the FXMLView could directly be accessed via e.g.
FXMLView.getResourceBundle()
PS: What I'm doing is exposing a showInDialog() method in my View which shows the getView() Parent in a customized ControlsFX Dialog...
The loader.load(); in line 81 of FXMLView is invoked outside the FX-Thread.
This is only possible if JavaFX components are in the View and Presenter which are allowed to be instantiated outside the FX-Thread.
For example Tooltip and WebView are not allowed to be instantiated outside the FX-Thread (see Stacktrace below: WebEngine.checkThread).
I would recommend that the asynchronous loading should be optional and is only used if the developer triggers it. Example API:
public Parent getView() {
return getView(false);
}
public Parent getView(boolean loadAsynchronous) {
// TODO
}
Stacktrace of the IllegalStateException:
java.lang.IllegalStateException: Not on FX application thread; currentThread = pool-2-thread-1
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:210)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:393)
at javafx.scene.web.WebEngine.checkThread(WebEngine.java:1170)
at javafx.scene.web.WebEngine.<init>(WebEngine.java:808)
at javafx.scene.web.WebEngine.<init>(WebEngine.java:797)
at javafx.scene.web.WebView.<init>(WebView.java:249)
at javafx.scene.web.WebViewBuilder.build(WebViewBuilder.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
at javafx.fxml.JavaFXBuilder$ObjectBuilder.build(JavaFXBuilderFactory.java:272)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:757)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2839)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at com.airhacks.afterburner.views.FXMLView$3.run(FXMLView.java:81)
at com.airhacks.afterburner.views.FXMLView.loadAsynchronously(FXMLView.java:91)
at com.airhacks.afterburner.views.FXMLView$1.call(FXMLView.java:62)
at com.airhacks.afterburner.views.FXMLView$1.call(FXMLView.java:58)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
riccardo@bigSuse:~/Tmp/followme> $JAVA_8_HOME/bin/java -jar target/followme-app.jar
X Error of failed request: BadWindow (invalid Window parameter)
Major opcode of failed request: 154 (NV-GLX)
Minor opcode of failed request: 4 ()
Resource id in failed request: 0x3e00002
Serial number of failed request: 35
Current serial number in output stream: 35
System information:
riccardo@bigSuse:~/Tmp/followme> uname -a
Linux bigSuse 3.11.6-4-desktop #1 SMP PREEMPT Wed Oct 30 18:04:56 UTC 2013 (e6d4a27) x86_64 x86_64 x86_64 GNU/Linux
riccardo@bigSuse:~/Tmp/followme> kde4-config --version
Qt: 4.8.5
Piattaforma di sviluppo KDE: 4.11.3
kde4-config: 1.0
riccardo@bigSuse:~/Tmp/followme> $JAVA_8_HOME/bin/java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b121)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b63, mixed mode)
Its good to have a community discussion group (may be google group) where many things can be discussed...
Hi Adam,
I really appreciate your work with this small but very relevant DI plugin. I am working with internationalized strings both with Netbeans 8.1 and SceneBuilder. My app has many users and each user would want the Views display in his native language, but I don't know how to attach user-specific Locales to ResourceBundles which in turn can be injected into the Views.
With the standard javafx, I could change the language like this:
private void loadView(Locale locale) {
try {
FXMLLoader fxmlLoader = new FXMLLoader();
// Here, just the resource bundles name is mentioned. You can add support for more languages
// by adding more properties-files with language-specific endings like
// "E_13_Internationalization_fr.properties".
fxmlLoader.setResources(ResourceBundle.getBundle("E_13_Internationalization", locale));
Pane pane = (BorderPane) fxmlLoader.load(this.getClass().getResource("/E_13_Internationalization.fxml").openStream());
borderPane.setCenter(pane);
} catch (IOException ex) {
ex.printStackTrace();
}
}
Is there an option to set resources within the View or any other solution would be greatly appreciated!
Thank you for your time,
Cheng
Nice idea of community should have a Organisation... its a good idea to move this to a Git Organisation so its easy to manage and maintain the project.
Today we had a discussion about the injection mechanism of afterburner.fx
At the moment there are to ways of injection:
But what about injection of any Object (not only singletons ... maybe simple objects or numbers and so forth).
-> A new method could be added e.g. setModelOrService(String, Object). And whenever there is an Inject-annotated attribute whose name matches one given String, the given Object is injected.
PS: This could complement (or even replace) the system-property-injection.
The example can be taken from goto1134/javafx-frameworks-comparation#afterburner-failing-injection branch.
My presenter class:
class AfterburnerPresenter : Initializable {
override fun initialize(location: URL?, resources: ResourceBundle?) {
sayHelloButton.setOnAction { helloLabel.text = helloUserServiceImpl.getHelloStringForUser(User(nameTextField.text, surnameTextField.text)) }
}
@Inject lateinit var helloUserServiceImpl: HelloUserServiceImpl
@FXML lateinit var nameTextField: TextField
@FXML lateinit var surnameTextField: TextField
@FXML lateinit var helloLabel: Label
@FXML lateinit var sayHelloButton: Button
}
I try to inject spring beans in a presenter, using this code:
val view: AfterburnerView = AfterburnerView({ name -> context.getBean(name) })
And works fine until I use HelloUserService
interface instead of HelloUserServiceImpl
. This stacktrace appears after crash:
Caused by: java.lang.IllegalStateException: Cannot instantiate view: interface com.github.goto1134.fxframeworks.HelloUserService
at com.airhacks.afterburner.injection.Injector.lambda$getDefaultInstanceSupplier$9(Injector.java:228)
at com.airhacks.afterburner.injection.Injector.instantiateModelOrService(Injector.java:111)
at com.airhacks.afterburner.injection.Injector.injectMembers(Injector.java:144)
at com.airhacks.afterburner.injection.Injector.injectMembers(Injector.java:129)
at com.airhacks.afterburner.injection.Injector.injectAndInitialize(Injector.java:122)
at com.airhacks.afterburner.injection.Injector.registerExistingAndInject(Injector.java:103)
at com.airhacks.afterburner.injection.Injector.instantiatePresenter(Injector.java:56)
at com.airhacks.afterburner.views.FXMLView.lambda$loadSynchronously$1(FXMLView.java:85)
at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:929)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 15 more
Caused by: java.lang.InstantiationException: com.github.goto1134.fxframeworks.HelloUserService
at java.lang.Class.newInstance(Class.java:427)
at com.airhacks.afterburner.injection.Injector.lambda$getDefaultInstanceSupplier$9(Injector.java:226)
... 28 more
Caused by: java.lang.NoSuchMethodException: com.github.goto1134.fxframeworks.HelloUserService.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.newInstance(Class.java:412)
... 29 more
The problem is in the logic of initialization with its injection and postinjection steps, where on regular injection step the Injector creates an object for the class of the parameter.
The situation when you create and inject object which already exists and should be injected on postinjection step is incorrect and should be fixed. Also doing injection this way may cause unpredictable behaviour in some (bad designed) applications.
Moreover, I don't see any reason to use two-step injection. If an object exists in injectionContext
, it should be injected on the only injection step immediately.
Correct me if I'm wrong.
Hi there,
I'm using a custom injection context for one of my presenters. The context contains a fully initialized instance of a non-primitive non-string type that should be injected into the presenter. Currently, this works only if the type is default-constructable. I'm using the latest release 1.6.1.
It seems that per view DI interferes with model/service injection as the field to inject will first be assigned a value from instantiateModelOrService before the custom injection context applies. The flow is roughly as follows:
instantiatePresenter(c, ic) -> registerExistingAndInject(i) -> injectAndInitialize(i) -> injectMembers(i) -> injectMembers(c, i)
In injectMembers(c, i), instantiateModelOrService will be called as the field's type is neither primitive nor string. After all fields have been injected, post-injection will kick in -- and overwrite the default-constructed instance with the one from the custom injection context.
Is this intended? If instantiateModelOrService was allowed to return null (which will never happen with the default instance supplier but can happen with a custom one) or could otherwise be skipped if no appropriate model or service can be found, unneeded instantiations would be prevented. Maybe this would cause trouble in other places, though.
I am talking about the Executor
used by the FXMLView
.
Executor
is a very limited interface, and since a ExecutorService
is returned by the Executors.newCachedThreadPool(...)
anyways, we could use ExecutorService
, which would then offer more functionality. This also does not break any existing programs, since ExecutorService
is a supertype of Executor
.
Hi Adam, will you be doing a 1.6.3 release to maven central for the topgun branch?
Hi Adam,
the FXMLView loads it's content when calling the constructor.
It would be nice if this could be triggered as an asynchronous operation to keep the FXApplication thread working during loading.
The getView() could return a container (e.g. Region) which will be filled with the loaded content when finished.
BG, Andreas
Hi,
Your Injector class uses javax.inject
annotation and also dagger2 using the same one.
So is it possible to ignore your injector and use dagger2 ?
Hi I very much like your little framework, it makes developing JavaFX a lot of fun :), but one issue I have at the moment is your convention of naming the fxml files.
I do not like the “all-lowercase” naming. It makes some longer names very hard to read. So I would like to change it to allow CamelCaseNames by sub-classing FXMLView, but the getConventionalName() method is currently package protected and there is no other way to hook into the name resolution process.
Hi Adam,
here is another idea for an extension of afterburner.fx :)
Currently it is not possible to instantiate a presenter with construction arguments.
So we implemented setters in our presenters wich replace the missing presenter-constructor.
But the problem is, that you have to manage repeated calls of that setter even if you know that the parameters actually are only set onetime. Another problem is, that it is not possible to use those parameters in the initialize-method.
It would be nice if afterburner.fx would provide a solution for that problem.
Two suggestions for possible solutions:
The second solution is a little bit easier for the user, because you do not have to implement a custom ControllerFactory. But it's more difficult to implement in afterburner.fx.
The first solution is easy to implement in afterburner.fx. But the user has to know that he has to call Injector.registerExistingAndInject(constructedPresenter) in the custom ControllerFactory.
A working example for code-change in FXMLView:
public FXMLView() {
this.init(getClass(), getFXMLName(), (Class<?> p) -> Injector.instantiatePresenter(p));
}
public FXMLView(Callback<Class<?>, Object> controllerFactory) {
this.init(getClass(), getFXMLName(), controllerFactory);
}
private void init(Class clazz, final String conventionalName, Callback<Class<?>, Object> controllerFactory) {
final URL resource = clazz.getResource(conventionalName);
String bundleName = getBundleName();
this.bundle = getResourceBundle(bundleName);
this.fxmlLoader = loadSynchronously(resource, bundle, conventionalName, controllerFactory);
}
FXMLLoader loadSynchronously(final URL resource, ResourceBundle bundle, final String conventionalName, Callback<Class<?>, Object> controllerFactory)
throws IllegalStateException {
final FXMLLoader loader = new FXMLLoader(resource, bundle);
loader.setControllerFactory(controllerFactory);
try {
loader.load();
} catch (IOException ex) {
throw new IllegalStateException("Cannot load " + conventionalName, ex);
}
return loader;
}
An example for a custom ControllerFactory:
public class ConnectionProfileFormPresenterFactory implements Callback<Class<?>, Object> {
String text;
public ConnectionProfileFormPresenterFactory(String text) {
this.text = text;
}
@Override
public Object call(Class<?> param) {
ConnectionProfileFormPresenter presenter = new ConnectionProfileFormPresenter(this.text);
Injector.registerExistingAndInject(presenter);
return presenter;
}
}
Hi, and thanks for the powerful little framework.
From my Application instance (App.java), I want to keep the application-parameters, so they can be used in any of the views. Let's say I want to keep them in a singleton called ApplicationStates. In the views I want to @Inject ApplicationStates.
The problem I have is that the method static Object instantiateModel(Class clazz) in InjectionProvider is not public.
Can you make it public (for such cases)?
Thanks
PS: Thanks for the great air workshop in Munich!
Is there a way to use constructor injection?
I'm not talking about presenters but other components, e.g. I have component A that depends on component B and my presenter depends on A component. So in order to inject A I have to inject B into A first. It all works well with @Inject
annotation on fields, but what would be really nice to have is the possibility to explicitly specify B dependency on A constructor.
I know I can use mockito @InjectMocks
annotation in my unit tests but still I prefer the old-fashioned way to see class dependencies.
When changing the default locale of a vm, a JavaFX-AfterburnerFX powered application is running in, the Method "protected String getConventionalName()" within FXMLView uses String clazz = this.getClass().getSimpleName().toLowerCase();
For example: If the name of the class starts with 'i' - let's say iHelp - and the locale is changed to Turkish (tr), then 'toLowerCase()' returns ıHelp => Turkish 'ı' and not 'i'.
A fix could be to use toLowerCase(Locale.ENGLISH); or to give a possibility to specify the Locale, the class- and file-names are written in.
(Some background info taken from java.lang.String.toLowerCase(Locale locale) docu:
Examples of lowercase mappings are in the following table: Language Code of Locale Upper Case Lower Case Description tr (Turkish) \u0130 \u0069 capital letter I with dot above -> small letter i tr (Turkish) \u0049 \u0131 capital letter I -> small letter dotless i (all) French Fries french fries lowercased all chars in String (all) lowercased all chars in String )
The current implementation of method
public static T instantiatePresenter(Class clazz, Function<String, Object> injectionContext)
in class "Injector" does not apply the injectionContext to superclasses of the passed controller-class "clazz".
Maybe it is possible to also inject superclass-fields like has been implemented in method
public static void injectMembers(Class<? extends Object> clazz, final Object instance) ????
Regards
Axel
Hi Adam,
it's possible to remove this output to the console? Located in FXMLView#getResourceCamelOrLowerCase(boolean mandatory, String ending): String.
In my application 'Lib-Tile-Demo' I have no '.css' file for my views in the ListView. After starting I see following output in the console (I loaded over 400 ItemCells for the ListView).
--- exec-maven-plugin:1.2.1:exec (default-cli) @ lib-tile-demo ---
2016-09-13 19:23:24,446 DEBUG Load properties: /com/github/naoghuman/lib/tile/demo/application/application.properties [LibProperties]
2016-09-13 19:23:24,447 INFO
Start Lib-Tile-Demo v0.3.0-SNAPSHOT.
2016-09-13 19:23:24,449 DEBUG Init preferences file [LibPreferences]
2016-09-13 19:23:24,544 INFO Initialize ApplicationPresenter [ApplicationPresenter]
2016-09-13 19:23:24,544 INFO Initialize Background image [ApplicationPresenter]
2016-09-13 19:23:24,544 INFO Initialize menu About [ApplicationPresenter]
2016-09-13 19:23:24,572 INFO Initialize AboutPresenter [AboutPresenter]
2016-09-13 19:23:24,572 INFO Initialize label Version [AboutPresenter]
File: about.css not found, attempting with camel case
2016-09-13 19:23:24,573 INFO Initialize menu Background [ApplicationPresenter]
2016-09-13 19:23:24,610 INFO Initialize BackgroundPresenter [BackgroundPresenter]
2016-09-13 19:23:24,610 INFO Initialize Background parameters [BackgroundPresenter]
2016-09-13 19:23:24,610 INFO Initialize Color components [BackgroundPresenter]
2016-09-13 19:23:24,611 INFO Initialize ColorPicker for background color [BackgroundPresenter]
2016-09-13 19:23:24,611 INFO Initialize TextField for background image [BackgroundPresenter]
2016-09-13 19:23:24,648 DEBUG Register actions in BackgroundPresenter [BackgroundPresenter]
File: background.css not found, attempting with camel case
2016-09-13 19:23:24,648 INFO Initialize menu Tile [ApplicationPresenter]
2016-09-13 19:23:24,672 INFO Initialize TilePresenter [TilePresenter]
2016-09-13 19:23:24,673 INFO Initialize CustomizedExamples [TilePresenter]
2016-09-13 19:23:24,674 INFO Initialize TransparentTextures [TilePresenter]
2016-09-13 19:23:24,675 DEBUG Register actions in TilePresenter [TilePresenter]
2016-09-13 19:23:24,675 DEBUG Register on Action switch Selection [TilePresenter]
2016-09-13 19:23:24,676 DEBUG Register action: ON_ACTION__SWITCH_SELECTION [ILibAction]
File: tile.css not found, attempting with camel case
2016-09-13 19:23:24,677 INFO Initialize TitledPane tile [ApplicationPresenter]
2016-09-13 19:23:24,677 DEBUG Register actions in ApplicationPresenter [ApplicationPresenter]
2016-09-13 19:23:24,677 DEBUG Register on Action reset Background color [ApplicationPresenter]
2016-09-13 19:23:24,677 DEBUG Register action: ON_ACTION__RESET_BACKGROUND_COLOR [ILibAction]
2016-09-13 19:23:24,678 DEBUG Register on Action reset Background image [ApplicationPresenter]
2016-09-13 19:23:24,678 DEBUG Register action: ON_ACTION__RESET_BACKGROUND_IMAGE [ILibAction]
2016-09-13 19:23:24,678 DEBUG Register on Action reset Tile background [ApplicationPresenter]
2016-09-13 19:23:24,678 DEBUG Register action: ON_ACTION__RESET_TILE_BACKGROUND [ILibAction]
2016-09-13 19:23:24,678 DEBUG Register on Action show Background SingleColor [ApplicationPresenter]
2016-09-13 19:23:24,679 DEBUG Register action: ON_ACTION__SHOW_BACKGROUND_SINGLECOLOR [ILibAction]
2016-09-13 19:23:24,679 DEBUG Register on Action show Background XyGradient [ApplicationPresenter]
2016-09-13 19:23:24,679 DEBUG Register action: ON_ACTION__SHOW_BACKGROUND_XY_GRADIENT [ILibAction]
2016-09-13 19:23:24,679 DEBUG Register on Action show Background image [ApplicationPresenter]
2016-09-13 19:23:24,679 DEBUG Register action: ON_ACTION__SHOW_BACKGROUND_IMAGE [ILibAction]
2016-09-13 19:23:24,680 DEBUG Register on Action show Tile background [ApplicationPresenter]
2016-09-13 19:23:24,680 DEBUG Register action: ON_ACTION__SHOW_TILE_BACKGROUND [ILibAction]
File: transparenttexturesitem.css not found, attempting with camel case
File: customizedexamplesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: customizedexamplesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: customizedexamplesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
2016-09-13 19:23:25,084 INFO Initialize ApplicationPresenter after window is showing [ApplicationPresenter]
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
File: transparenttexturesitem.css not found, attempting with camel case
If I compile my afterburner.fx project in Java 9 und start it with Java 9 i get the following error:
Caused by: java.lang.NoClassDefFoundError: javax/annotation/PostConstruct
at com.airhacks.afterburner.injection.Injector.initialize(Injector.java:176)
at com.airhacks.afterburner.injection.Injector.injectAndInitialize(Injector.java:123)
at com.airhacks.afterburner.injection.Injector.instantiateModelOrService(Injector.java:111)
at com.airhacks.afterburner.injection.Injector.injectMembers(Injector.java:144)
at com.airhacks.afterburner.injection.Injector.injectMembers(Injector.java:129)
at com.airhacks.afterburner.injection.Injector.injectAndInitialize(Injector.java:122)
at com.airhacks.afterburner.injection.Injector.registerExistingAndInject(Injector.java:103)
at com.airhacks.afterburner.injection.Injector.instantiatePresenter(Injector.java:56)
at com.airhacks.afterburner.views.FXMLView.lambda$loadSynchronously$1(FXMLView.java:85)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:933)
at javafx.fxml/javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:975)
at javafx.fxml/javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:222)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:747)
at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2718)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2547)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2461)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2430)
at com.airhacks.afterburner.views.FXMLView.loadSynchronously(FXMLView.java:87)
at com.airhacks.afterburner.views.FXMLView.initializeFXMLLoader(FXMLView.java:96)
at com.airhacks.afterburner.views.FXMLView.getView(FXMLView.java:108)
That's because javax.xml.ws.annotation, the module that contains the @PostConstruct annotation is deprecated for removal.
there is a work around: You can start the app with the following vm arg: --add-modules java.xml.ws.annotation
Hi Adam,
I'm currently integrating afterburner.fx in our R&D software front-end for energy-management (virtual power plant).
We use this front-end in different R&D projects which have different CI colors, fonts and so forth. But this is an issue in many other cases (E.g. use different skins depending on OS or User-Role and so forth)
The basic idea is similar to the -Default Locale- and the properties-files:
-> There are parameters affecting the View.
-> But in contrast to changing the label-text based on the language via properties-files the skin is changed via css-stylesheet(s).
It would be nice, if afterburner.fx would provide skinning via css similar to internationalization via properties.
This maybe could be realized as follows:
-> Set the default style via a style-code (e.g. "custom1") for the whole VM:
[new method]
public static void FXMLView.setDefaultStyle(String styleCode)
-> When reading the stylesheet-name this style-code is added (resulting filename e.g. "myclazz.css" if no custom default style was set or "myclazz_custom1.css" if style-code is "custom1"):
[changed method]
getStyleSheetName() return getConventionalName(getStyleSheetNameSuffix() + ".css");
A package-content could now look like as follows:
MyClazzView.java
MyClazzPresenter.java
myclazz.css
myclazz_custom1.css
myclazz.fxml
myclazz.properties
myclazz_de.properties
UPDATE: I fix error, is not related with afterburner.fx. Solution is in StackOverflow question below.
I try to load a resource from an Injected object, exactly I try to load an image from resources folder into Presenter instance using getClass().getResourceAsStream() method, but always get null pointer exceptions.
Also, I tried but not works:
imgLogo.setImage(new Image(Injector.instantiatePresenter(LoginPresenter.class).getClass().getResourceAsStream("/img/logo.png")));
Note: I also create a question in StackOverflow about this question (https://stackoverflow.com/questions/27132257/afterburner-fx-fail-load-resource-from-object-injected)
[afterburner.fx version : 1.4.2]
Hi Adam,
the FXML is not loaded in the FX-Application Thread. I get:
java.lang.IllegalStateException: Service must only be used from the FX Application Thread
I think line 89 and line 91 has to be swapped:
88 if (Platform.isFxApplicationThread()) {
89 Platform.runLater(runnable);
90 } else {
91 runnable.run();
92 }
Platform.runLater is only called if you are already in the FX-Application Thread.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.