Why use JavaFX properties? - java

Pardon my question if it may seem stupid but I'm curious. I am making a program in Java of which will have a GUI, and am curious about the whole idea of properties. Why use them when we can just add data to a class? For example:
class myButton extends Button {
private boolean booleanProperty = false;
myButton(args...) {
// Do something with the property
}
public void setProperty(boolean value) {
this.booleanProperty = value;
}
public boolean getProperty() {
return this.booleanProperty;
}
}
Seems to work just fine for storing additional information on the custom implementation of the button. But what about:
class myButton extends Button {
private SimpleBooleanProperty booleanProperty = new SimpleBooleanProperty(false);
myButton(args...) {
// Do something with the property
}
public void setProperty(boolean value) {
this.booleanProperty.set(value);
}
public boolean getProperty() {
return this.booleanProperty.get();
}
}
The only real difference, I am seeing (correct me if I'm wrong) is that that you can attach listeners to the property values, but I feel as if there has to be more than just that. Ideas?

The power of JavaFX's properties is that they can be bound in ways that will automatically update the UI when a change occurs.
As an example consider an element you want to hide if a textField contains no value:
TextField tf = ...
Node container = ...
container.visibleProperty.bind(tf.textProperty.isNotEmpty());
Now as you change the text in tf, you will see container switching whether its visible based on the presence of text.

They really are useful in a lot of ways I even started them using in non UI related stuff. But look at this example: You habe an undomanager class
public class UndoManager {
BooleanProperty canUndo = ...;
BooleanProperty canRedo = ...;
...
}
And you have 3 places from where you can invoke undo/redo.
MenuButton menuUndo;
Button toolbarUndo;
MenuButton contextMenuUndo;
You basically only beed to do this:
menuUndo.disabledProperty().bind(undoManager.undoProperty()):
toolbarUndo.disabledProperty().bind(undoManager.undoProperty());
contextMenuUndo.disabledProperty().bind(undoManager.undoProperty());
and you dont ever have to worry about it again. If you add a new place where an undo can happen you just have to bind it too.

In this case you don't have a benefit, since you do not allow access to the property object itself. Usually this is done.
This allows you to add listeners to the property and be notified, when it changes.
Bindings are using this possibility to keep values the same and properties as well as the Bindings class provide methods for simple conversions of properties.
BooleanProperty booleanProperty = new SimpleBooleanProperty();
booleanProperty.addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
System.out.println("property changed form "+oldValue +" to "+newValue);
}
});
booleanProperty.set(true);
booleanProperty.set(true);
booleanProperty.set(false);
booleanProperty.set(false);
booleanProperty.set(false);
booleanProperty.set(true);
booleanProperty.set(false);
booleanProperty.set(true);
booleanProperty.set(false);
Furthermore it allows you to pass an object representing the property. E.g. code that has to write/read booleanProperty does not need information about the myButton to write/read the property; you can just pass the property.
TableView is an example of a class that makes use of propertys. The columns used with TableView get a property from the items in the TableView and TableView registers a listener to that property. This allows it to change the values displayed in the cells even if the changes are triggered somewhere else in the code. Also for editable cells the properties of the items can be automatically modified.

The use of a javafx property for a pre-made object to hold an arbitrary value for later use. So you can set values to a text field or some other object that doesn't directly effect the shown value

Imagine programming a robot that would take care of resturant customers. How would it respond to customers or any other tasks that would have to be taken care of without using something like property listeners.
The benefit of using property listeners is that you can make your program become Concurrent. If there are no customers coming the next 1 hour your otherwise Sequentially made program would stand and do nothing for the next hour. Maybe switching the word Concurent with flexible in this example would be better, but you should look up Concurent programming and Sequence programming. Those properties allow you to customly make your program concurent.
You should also know that the gui you are using are already use built-in (event listening) features which build on the same principle.
Now what if you made that robot - instead of handing 1 customer at a time - respond depending upon what had to be done instead. Ask customers what the food tasted like (if customers have eaten), take new order(if called upon - by ANYBODY), take dishes(When any customer has paid and there is dish on a table), handle payment(When called upon by anybody). And ofcours handling a new customer arriving at the resturant.
The concurrently made program will handle any task needed by any customer. The sequencly made robot would only handle one customer at a time. Maybe it only then also has to be limited to greeting customers and placing them on seats to be anyhow useful. (You cannot have 1 robot for each customer).
Some people think it is easier to program sequencially can also be said. This is beacuse it can be difficult to keep track of subtasks that has to be done in a particular order. For instance that robot should not look for dishes when there haven´t arrived any customers. And what happens if it receives a payment call - while carrying dish? So it´s hard to prioritize and sort out the different tasks. However when succesfully doing it you program becomes so much more effective. It will be able to mutli task vs just solo-tasking.
And yes the sole purpose of properties is indeed that you can add listeners to them.

Related

Java: How can I "bundle" GUI elements into groups and listen to multiple groups cleanly?

I am not skilled in GUI design. After much thought, research and experimentation I've developed several design ideas but still none that seems efficient. One design has a Session god object register a listener on every UI element when created, and every object that cares about any action registers a listener on the Session object. This seems simple and robust, as all messaging goes through a central location so it's less likely that anything is lost. It's brute force though, and seems cumbersome and inefficient.
Another design attempts to create subgroups of objects that speak to each other. This avoids the huge top-level Session and seems more efficient, but also seems error prone.
I'm trying to implement a framework for reuse where I group buttons with related purposes into toolbars and have a hierarchical approach to listening for actions performed by toolbars with relevant operations to the listener. I've gotten to this so far:
public class EditorToolBar extends JToolBar {
public static enum Command {
ZOOMIN,
ZOOMOUT,
FINER,
COARSER,
RESET
}
private ButtonCommandListener listener = new ButtonCommandListener();
public EditorToolBar() {
super("Editor Commands");
JButton button;
for (final Command cmd : Command.values()) {
button = new JButton(cmd.toString());
button.setEnabled(true);
button.setToolTipText(cmd.toString() + " Command");
button.setActionCommand(cmd.toString());
button.addActionListener(listener);
add(button);
}
}
public void addActionListener(ActionListener pNewListener) {
listener.cActionNotifier.addListener(pNewListener);
}
private class ButtonCommandListener implements ActionListener {
private NotifierImp<ActionListener> cActionNotifier = new NotifierImp<ActionListener>();
public void actionPerformed(ActionEvent pEvent) {
for (ActionListener listener : cActionNotifier) {
listener.actionPerformed(pEvent);
}
}
}
} // class EditorTooBar
and the listeners implement something like this:
public void actionPerformed(ActionEvent pEvent) {
switch (EditorToolBar.Command.valueOf(pEvent.getActionCommand())) {
case ZOOMIN:
// do something
break;
case ZOOMOUT:
// do something
break;
case FINER:
// do something
break;
case COARSER:
// do something
break;
case RESET:
// do something
break;
default:
System.out.println("Unknown EditorToolBar Command: "+pEvent.getActionCommand());
return;
}
I can enhance the instructor for the enum to also include tooltip text, images, etc. I'd like to reuse this design with just a different enum describing other toolbars. Listeners will distinguish different button actions using ActionEvent.getActionCommand() and use Command.toValue(String). I'd like this to extend to a hierarchy of classes that are listening: a superclass may implement a listener for one type of toolbar, and subclass add to that by listening for a different toolbar type. If the event is not from the toolbar the subclass is interested in, it can forward the event to the superclass. To make this work, I need a way to distinguish between one toolbar and another, but preferably without having to check for every button event possible from that toolbar. Ideally I'd like to have a toolbar factory, and just specifying an enum would be enough to fully describe a toolbar. Not being able to subclass an enum adds to the challenge here.
Is this a promising design pattern to pursue? I've not seen it anywhere else yet. Is there a better way that I should be using rather than inventing something that is inferior? A link to other options would be welcome.
Edit: Based on the answer from yash ahuja I should clarify that when I mention hierarchy I mean similar to the way that key bindings are handled (i.e. do you have a binding? No, then does your container have a binding? ... until someone consumes the key event) not the actual class hierarchy.
As a way to encapsulate functionality, consider combining JToolBar, discussed in How to Use Tool Bars, with Action, discussed in How to Use Actions. The example cited here exports a single tool bar. In contrast, the StyledEditorKit, illustrated here, exports families of Action subtypes that apply to the current selection of a text component.
The design is pretty good but if you create a hierarchy of Tool bars then, in a situation where a particular button is clicked on particular tool bar the corresponding action performed for that button may not be accurate. Also at times multiple events can be triggered.
Also there are some tool bars for which it is difficult to identify that under which super class they should belong or if they are implementing features from multiple tool bars you need multiple inheritance which Java does not supports.
Possibly a combination of Strategy Pattern and Factory Pattern could solve these issues. Please rethink on this and design your solution, sorry I don't have exact design or source for your question , I have just put my thoughts for your solution.
Regards,
Yash

Requesting user input from outside the GUI code, do I need Events or Action to communicate with the GUI in this case?

I'm writing a 2D polygon and physics editor, one functionality is to set a rotation limit for joints.
To use this functionality, the user clicks and drags a line between the joint points which need to receive the limit.
The logic of determining if the pick is valid happens outside of the GUI code.
If a pick is found, I wanted to pop up a JOptionPane.showInputDialog where the user can input the limit.
Thing is, if I do it directly, the program becomes unresponsive, I figure it's because of threading.
I's there a way to define an event listener the GUI can use that doesn't require an actual GUI component?
I want to send an event that also contains a reference to the target object to that component, then telling it that a valid pick has been made and user input is required, and then send the value back via a method of the target object.
I am very inexperienced with Swing.
My hunch is that I might be able to add an ActionListener to the main window, but I don't know how I could address that listener specifically.
As in, how would I need to define an Action that only gets processed by that particular listener?
If that is actually possible, of course.
So far I have only used listeners to let the GUI talk to the logic, not the other way around...
Edit:
The program becomes unresponsive the movement I call
result = JOptionPane.showInputDialog(this,"Enter Limit.");
That just breaks it. Can't even enter anything into the textbox, nor close it, etc.
I figure it's because it spawns a modal dialog that pauses some thread, and calling it from somewhere in the bowels of non GUI code is just not the thing I should do, but I'm too inexperienced to know another way...
Edit2:
I should add that I can use JOptionPane.showInputDialog without any problems if I spawn it, for example, after clicking a button or choosing a popup menu option.
In fact that's how I rename the items I am working with.
But I assume at that point, the dialog is being spawned inside the GUI thread, or this Event Dispatcher queue thing.
The problem with this though is, that this takes visible, interactive GUI components that fire that event.
What I'd like, however, is some sort of component that would spawn JOptionPane.showInputDialog just like a clicked button or context menu would, but without having to be interacted with by the user, but instead by the code.
I guess I could use invisible buttons and emulate mouseclick events, but that's pretty hacky...
Also, I tried spawning Threads and Runnables which spawned the JOptionPane.showInputDialog, but that didn't help either.
Unless I spawn the JOptionPane from a GUI source, everything stalls, and the dialog won't work.
The publisher will have a public add/remove listener, where the subscriber will add itself or be added via another channel to the EventListenerList in the publisher.
You can create your own listener interface that extends EventListener and a function to shoot an event. Below is an example:
import java.util.EventListener;
public interface MyEventListener extends EventListener {
public void myEventOccurred(MyEvent event);
}
You can then create your custom event class, "MyEvent" in the example above like:
import java.util.EventObject;
public class MyEvent extends EventObject {
// customer fields and methods here
public MyEvent(Object source) //more possible args here {
super(source);
//other things here to do what you want
}
}
Now you can have your subscriber implement MyEventListener and override the myEventOccurred(..) method.
Another approach would be to use the SwingWorker class to execute the logic of determining the pick in a dedicated thread without blocking the GUI dispatch thread, and use its callback method to execute the GUI action (open the input dialog).
See : http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
(This page has a better explanation of concept than I could write.)
It should be possible for your background thread to spawn a dialog with invokeAndWait():
final double[] result = new double[1];
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
result[0] = Double.parseDouble(
JOptionPane.showInputDialog("Enter value:"));
} catch(NumberFormatException e) {
result[0] = -1;
}
}
}
// ... do something with result[0]
Here I made the result an array just so that it can be final (accessible to the anonymous class) and also mutable.

JTree refreshing after setting new jtree model

I'm trying to use dynamically JTree component.
Under root node I have four nodes and one of them ("Operations") can have 0 to many children. This is set by user via editable list in separate window opened on users request. After editing this list user hits button 'Save' and then magic should happen. Edited list is sent to server(on the same machine actually, so it doesn't take to long), the window with list is closed but right before that the main window (with jtree) is told to refresh itself, and I can see that it does what is told in log output, but the changes don't show on the screen.
I am using DefaultTreeModel, this method is called to create model at the beginning(when first opening the window) and after the change to update the new model with new structure.
with dmtn.getLeafCount() I can see that newly downloaded structure from server is the right one with the changed number of leaves under 'Operations'
public DefaultTreeModel getDataStructure() {
int dataID = task.getData().getId();
LoggerUtility.logger.info("Data ID: " + dataID);
DefaultMutableTreeNode dmtn = Manager.manager.getDataStructure(task.getId());
LoggerUtility.logger.info("DTMN created "+dmtn.getLeafCount());
return new DefaultTreeModel(dmtn);
}
the method used to refresh the jtree looks like this (it's very messy):
public void updateTree(){
taskDataTree.setModel(getDataStructure());
((DefaultTreeModel)taskDataTree.getModel()).reload();
this.revalidate();
this.repaint();
taskDataTree.revalidate();
taskDataTree.repaint();
taskDataTree.updateUI();
taskDataTree.setVisible(false);
taskDataTree.setVisible(true);
jScrollPane2.setViewportView(taskDataTree);
}
It's very messy because I have tried to put in there every possible solution to my problem that I have found on forums,
I also tried with my own treemodel implementation which would call fireTreeStructureChanged(...) but it also didn't change.
I should probably also add that I'm using Netbeans GUI Builder to build my gui although I don't know if it has anything to do with that.
I would be very grateful for any help with that
BR
Lucja
EDIT!!!
I also tried puting it in another thread like that:
public void updateTree() {
SwingWorker sw = new SwingWorker() {
#Override
protected Object doInBackground() throws Exception {
taskDataTree.setModel(getDataStructure());
((DefaultTreeModel) taskDataTree.getModel()).reload();
taskDataTree.revalidate();
taskDataTree.repaint();
taskDataTree.updateUI();
taskDataTree.setVisible(false);
taskDataTree.setVisible(true);
jScrollPane2.setViewportView(taskDataTree);
return null;
}
};
sw.execute();
}
but it also didn't help.
tree.setModel( anotherModel );
Is the only line of code that you need.
If it doesn't work then it means that the tree variable does not contain a reference to the tree that was added to the GUI. Maybe you have a class variable and a local variable of the same name.
From my point of view the own TreeModel implementation was a good approach. But I know that creating an TreeModelEvent with the correct data isn't that simple.
I would suggest to update your question with your TreeModel implementation so that we can find the problem with it.
In principle it should work this way (when you set a new Model, the tree reloads itself). (This is not the most efficient way, better let the model send appropriate events when it changes.)
If this does not work, make sure you are calling the setModel method in the AWT Event Dispatch Thread (with EventQueue.invokeLater (or SwingUtilities.invokeLater, which is the same), for example. I think you should not need all your revalidate(), repaint() etc. calls (and updateUI should only be done if you changed the look-and-feel configuration).

JButton updating its own isEnabled value

I'm trying to create a sub-class of the JButton component that will enable or disable itself based on a condition (which looks like below)
public interface Condition {
public static final Condition TRUE = new Condition() {
public boolean test() {
return true;
} };
public static final Condition FALSE = new Condition() {
public boolean test() {
return false;
} };
public boolean test();
}
However, the JButton code is all based on the actual boolean value stored privately in the JButton class. My question is: which method of JButton can be overridden to update its stored isEnabled boolean (via setEnabled(boolean))? Would it be update(Graphics)? or repaint()? OR some other function?
Edit: Realized that what I'm trying to create is actually impossible, unless you have a separate thread that waits short periods of time and forces the button to check its status (which is gross and I don't want to do that). The fact is, buttons are reactive only. It would be possible to accomplish this with some overhead by whoever uses the button class, but at that point it'd be easier to just write listeners on whatever is actually changing and toggle the button at that point. Woops.
The DefaultButtonModel, for example, maintains a stateMask, which includes a bit for the enabled state. You could implement the ButtonModel interface accordingly.
Addendum: As an alternative, and as noted in the article Key Bindings, "Another advantage of Actions is that they have an enabled state which provides an easy way to disable the action without having to track which component it is attached to." See How to Use Actions for more.
I strongly suggest using Actions to implement such a feature.
You should enable/disable action attached to your button. In Swing same action can be associated with many types of components such as buttons, menu items etc. By disabling a specific action you will automatically disable all associated components.
This becomes very convenient when you have toolbars, context menus etc with the same set of actions.

action listeners and event sources in Swing

OK, so if I add an ActionListener to a GUI element, and it's the only element I use that ActionListener with, does it matter which of the following lines (a,b) I use to get the checkbox selected state?
final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick");
checkbox.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent event){
boolean bChecked =
// (a) checkbox.isSelected();
// (b) ((JCheckBox)event.getSource()).isSelected();
model.setPrintDebugOn(bChecked);
}
});
It makes sense to me that if I add the ActionListener object to multiple GUI elements, then I should use (b).
And in (b), is it OK to blindly cast event.getSource() to JCheckBox, since I'm the one who added the action listener, or should I program defensively and do an instanceof check?
note: this question is in the context of event listeners in general; kdgregory has some good points below specifically re: checkboxes which I had neglected to consider.
I'd do neither.
If clicking the checkbox is going to start some action, I'd attach an ItemListener, then just look at the selection state in the ItemEvent.
However, checkboxes don't normally invoke actions, they manage state. So a better approach is to examine all of your checkboxes in response to whatever does kick off the action.
Edit: some commentary about the larger issues that the OP raised.
First, it's important to realize that large parts of Swing represent implementation convenience rather than a coherent behavior model. JCheckBox and JButton have nothing in common other than the fact that clicking within their space is meaningful. However, they both inherit from AbstractButton, which provides implementation details such as the button's label. It also assumes that buttons are "pressed", and that pressing a button will initiate some meaningful behavior (the action). In the case of JCheckbox, however, the button press is not important, the change in state is. That state change is signaled to the ItemListener -- which is also defined on AbstractButton even though state changes are meaningless to other button types (the JavaDoc even says "checkbox").
One of the things that Swing did get right -- if hard to use -- is the idea of that an Action is separate from the control initiating that action. An Action object can be invoked from multiple controls: a menu item, a pushbutton on a dialog, a keystroke, whatever. More important from a design perspective is that it takes you away from the idea of a generic "listener" that tries to figure out what needs to happen. I've seen apps where a single listener receives input from the entire menu system, for example, and then runs through a big if/else chain to figure out which menu item was pressed. Using Actions means you have more classes, but in the long run gives you a more maintainable app.
Finally, from a usability perspective, there's a difference between controls that maintain state, such as JCheckbox and JTextArea, and those that initiate actions, such as JButton and JMenuItem. I have seen a (web) app where clicking on a radio button takes you to a different page. That's bad. Even if you're planning to use listeners internally, to update the state of some model, you should ask yourself why the collection of GUI elements do not in themselves provide you with a model.
For the case where the listener is exclusive (such as an anon listener), I use (a).
If the listener will be reused (eg, this is an instance of ActionListener) I'll write it as:
#Override
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (src == checkbox) {
boolean bChecked = checkbox.isSelected();
// ...
}
}
If you have several checkboxes and they are processed the same way, then instanceof makes sense.
in (b) to be rigourous, you should indeed do a instanceof check, but it's not that important. I would think both these lines are fine and acceptable, though (b) would be "better code"
Although, what is usually done in an action listener is simply call another method customized to your checkbox. So it would look like something like this:
#Override public void actionPerformed(ActionEvent event) {
//your treatment would be in this method, where it would be acceptable to use (a)
onCheckBoxActionPerformed(event)
}
I'd program with b defensively as it's the best-practice option. But if only you are ever going to use the code then there is no reason why you can't do a. However, imagine how happy you will be with yourself if you come back to it at some future point, change something and find you wrote good code which you can directly reuse...

Categories