The *args
and **kwargs
is a common idiom to allow arbitrary number of arguments to functions as described in the section more on defining functions in the Python documentation.
The *args
will give you all function parameters as a tuple:
def foo(*args):
for a in args:
print(a)
foo(1)
# 1
foo(1,2,3)
# 1
# 2
# 3
The **kwargs
will give you all
keyword arguments except for those corresponding to a formal parameter as a dictionary.
def bar(**kwargs):
for a in kwargs:
print(a, kwargs[a])
bar(name='one', age=27)
# name one
# age 27
Both idioms can be mixed with normal arguments to allow a set of fixed and some variable arguments:
def foo(kind, *args, **kwargs):
pass
It is also possible to use this the other way around:
def foo(a, b, c):
print(a, b, c)
obj = {'b':10, 'c':'lee'}
foo(100,**obj)
# 100 10 lee
Another usage of the *l
idiom is to unpack argument lists when calling a function.
def foo(bar, lee):
print(bar, lee)
l = [1,2]
foo(*l)
# 1 2
In Python 3 it is possible to use *l
on the left side of an assignment (Extended Iterable Unpacking), though it gives a list instead of a tuple in this context:
first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]
Also Python 3 adds new semantic (refer PEP 3102):
def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
pass
Such function accepts only 3 positional arguments, and everything after *
can only be passed as keyword arguments.
Note:
- A Python
dict
, semantically used for keyword argument passing, are arbitrarily ordered. However, in Python 3.6, keyword arguments are guaranteed to remember insertion order.
- "The order of elements in
**kwargs
now corresponds to the order in which keyword arguments were passed to the function." - What’s New In Python 3.6
- In fact, all dicts in CPython 3.6 will remember insertion order as an implementation detail, this becomes standard in Python 3.7.
There are two typical ways of declaring a function. I prefer the second approach.
function function_name {
command...
}
or
function_name () {
command...
}
To call a function with arguments:
function_name "$arg1" "$arg2"
The function refers to passed arguments by their position (not by name), that is $1
, $2
, and so forth. $0
is the name of the script itself.
Example:
function_name () {
echo "Parameter #1 is $1"
}
Also, you need to call your function after it is declared.
#!/usr/bin/env sh
foo 1 # this will fail because foo has not been declared yet.
foo() {
echo "Parameter #1 is $1"
}
foo 2 # this will work.
Output:
./myScript.sh: line 2: foo: command not found
Parameter #1 is 2
Reference: Advanced Bash-Scripting Guide.
Best Answer
Using MVC
Most of this answer focuses on a direct call to pass a parameter from a calling class to the controller.
If instead, you want to decouple the caller and controller and use a more general architecture involving a model class with settable and listenable properties to achieve inter-controller communication, see the following basic overview:
Recommended Approach
This answer enumerates different mechanisms for passing parameters to FXML controllers.
For small applications I highly recommend passing parameters directly from the caller to the controller - it's simple, straightforward and requires no extra frameworks.
For larger, more complicated applications, it would be worthwhile investigating if you want to use Dependency Injection or Event Bus mechanisms within your application.
Passing Parameters Directly From the Caller to the Controller
Pass custom data to an FXML controller by retrieving the controller from the FXML loader instance and calling a method on the controller to initialize it with the required data values.
Something like the following code:
A new FXMLLoader is constructed as shown in the sample code i.e.
new FXMLLoader(location)
. The location is a URL and you can generate such a URL from an FXML resource by:Be careful NOT to use a static load function on the FXMLLoader, or you will not be able to get your controller from your loader instance.
FXMLLoader instances themselves never know anything about domain objects. You do not directly pass application specific domain objects into the FXMLLoader constructor, instead you:
This blog (by another writer) provides an alternate, but similar, example.
Setting a Controller on the FXMLLoader
You can construct a new controller in code, passing any parameters you want from your caller into the controller constructor. Once you have constructed a controller, you can set it on an FXMLLoader instance before you invoke the
load()
instance method.To set a controller on a loader (in JavaFX 2.x) you CANNOT also define a
fx:controller
attribute in your fxml file.Due to the limitation on the
fx:controller
definition in FXML, I personally prefer getting the controller from the FXMLLoader rather than setting the controller into the FXMLLoader.Having the Controller Retrieve Parameters from an External Static Method
This method is exemplified by Sergey's answer to Javafx 2.0 How-to Application.getParameters() in a Controller.java file.
Use Dependency Injection
FXMLLoader supports dependency injection systems like Guice, Spring or Java EE CDI by allowing you to set a custom controller factory on the FXMLLoader. This provides a callback that you can use to create the controller instance with dependent values injected by the respective dependency injection system.
An example of JavaFX application and controller dependency injection with Spring is provided in the answer to:
A really nice, clean dependency injection approach is exemplified by the afterburner.fx framework with a sample air-hacks application that uses it. afterburner.fx relies on JEE6 javax.inject to perform the dependency injection.
Use an Event Bus
Greg Brown, the original FXML specification creator and implementor, often suggests considering use of an event bus, such as the Guava EventBus, for communication between FXML instantiated controllers and other application logic.
Follow-up Q&A
It is a functional solution to a problem. A stage is returned from the
showCustomerDialog
function so that a reference to it can be stored by an external class which may wish to do something, such as hide the stage based on a button click in the main window, at a later time. An alternate, object-oriented solution could encapsulate the functionality and stage reference inside a CustomerDialog object or have a CustomerDialog extend Stage. A full example for an object-oriented interface to a custom dialog encapsulating FXML, controller and model data is beyond the scope of this answer, but may make a worthwhile blog post for anybody inclined to create one.Additional information supplied by StackOverflow user named @dzim
Example for Spring Boot Dependency Injection
The question of how to do it "The Spring Boot Way", there was a discussion about JavaFX 2, which I anserwered in the attached permalink. The approach is still valid and tested in March 2016, on Spring Boot v1.3.3.RELEASE: https://stackoverflow.com/a/36310391/1281217
Sometimes, you might want to pass results back to the caller, in which case you can check out the answer to the related question: