Is there a paint or update method (rendering loop) in JavaFX2 so that I can update the UI in a loop? - javafx-2

In Swing you have paint or update(Graphics g) method for each UI component which executes every frame. You can put your drawing logic in the overrided method and draw whatever you want. What is the paint method for JavaFX2 UI?
What I want to do is my UI receives control information from a socket server (another thread). Whenever a control information is received, I should update the UI.
There are two problems:
1. The control information is received from a different thread, it can not access the rendering thread directly.
2. How to update the UI constantly?
For Q1, I have a solution if I know where the update function is (Q2).
I can declare a List object, and insert the new control command received from the socket into the list. In the rendering loop, I can just observe the List object, retrieve the unprocessed command, and delete the already processed command.
However, where can I find such a rendering loop function? I guess maybe I can also do it with javax.concurrent.Task, but I don't find a way to do it.

I think i find the method, I use the following method and it can work. I don't know if there is a better solution
final Duration oneFrameAmt = Duration.millis(1000/10);
final KeyFrame oneFrame = new KeyFrame(oneFrameAmt,new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
//put UI update here
}
});
TimelineBuilder.create().cycleCount(Animation.INDEFINITE)
.keyFrames(oneFrame)
.build()
.play();

Related

Move view from top to bottom continuously without animation in Android

I want to know how to move a view from top to bottom continuously without animation. I am asking this because I want to get the position of the view at every step so that I can check that if there is any collision between that view and any other view.
With animation you can move (not exactly move) a view from one position to another position (Animator class), but animation produces an illusion to the user that it is moving but it's position is fixed all the time. So this can't be done using animation?
Second approach is incrementing position of view. I applied this method in onCreate(). If I used it without Thread.sleep(50) then the activity doesn't show the view, if I applied it with Thread.sleep(50) then activity doesn't start for some period.
Property animation (subclasses of Animator class) actually move the view, as they update the actual property of the view. It is the view animations (subclasses of Animation class) that don't move the actual view and instead just where it appears to the user.
Source:http://developer.android.com/guide/topics/graphics/prop-animation.html
Quote: With the property animation system, these constraints are completely removed, and you can animate any property of any object (Views and non-Views) and the object itself is actually modified.
You also shouldn't start moving things around in the onCreate method as things are still initializing (onwindowfocuschanged is recommened). Also if you call thread.sleep, you are going the sleep the main UI thread, hence freezing the application for a time.
Solved the problem using ValueAnimator :-
CodeSnippet :-
va=ValueAnimator.ofFloat(0.0f,size.y);
va.setDuration(5000);
va.setRepeatCount(va.INFINITE);
va.setRepeatMode(va.REVERSE);
va.start();
va.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// TODO Auto-generated method stub
bullet[0].setTranslationY((Float) va.getAnimatedValue());
Rect R11=new Rect(bullet[0].getLeft(),bullet[0].getTop()+(int)bullet[0].getTranslationY(),bullet[0].getRight(),bullet[0].getBottom()+(int)bullet[0].getTranslationY());
Rect R21=new Rect(ball.getLeft(), ball.getTop(), ball.getRight(), ball.getBottom());
if(R11.intersect(R21))
va.cancel();
}
});

Creating views inside a worker thread

I have a requirement to generate a bitmap out of an EditText and then perform some manipulations on it.
My main concern is not to call View.buildDrawingCache() method on the UI thread and possibly block it, especially when talking about large screens (i.e. Nexus 10) since the EditText will occupy about 80% of the available screen size.
I execute Runnables inside a ThreadPoolExecutor, those will inflate dummy views on a worker thread and set all the required attributes to them, then simply call buildDrawingCache() & getDrawingCache() to generate a bitmap.
This works perfect on some devices yet recently I have encountered a few devices that crash with the following message:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
I understand why this happens, as some phones must have modified implementation for EditText that creates a Handler and thus requires Looper.prepare() to be called first.
From what I've read online there is no issue with calling Looper.prepare() inside a worker thread though some stated it is highly unrecommended yet I could not find a reason for that.
Other than that, most posts related to this issue state you are not supposed to inflate views inside a background thread, probably due to the following from Android's official documentation (Processes and Threads):
"Do not access the Android UI toolkit from outside the UI thread"
What is the recommended approach to dealing with this problem?
Is there any harm in calling build/get drawingcache from the main thread? (performance-wise)
Will calling Looper.prepare() inside my worker thread solve this problem?
EDIT
Just to elaborate on my specific requirement, I have a user-interface consisting of an ImageView and a custom EditText on top of it, the EditText can change it's font and color according to the user selection, it can be zoomed in/out using "pinch to zoom" gesture and can also be dragged around to allow the user to reposition it on top of the image.
Eventually what I do is create a dummy view inside my worker thread using the exact same values (width, height, position) it currently has on the UI and then generate it's drawingcache, the original image's bitmap is decoded again from a local file.
Once the two bitmaps are ready I merge them into a single bitmap for future use.
So to put it simple, is there anything wrong with executing the following code (from within a background thread):
Call Looper.prepare()
Create a new view with application context, call measure() & layout() manually and then build+get drawingcache from it, i.e.:
Looper.prepare();
EditText view = new EditText(appContext);
view.setText("some text");
view.setLayoutParams(layoutParams);
view.measure(
View.MeasureSpec.makeMeasureSpec(targetWidth, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(targetHeight, View.MeasureSpec.EXACTLY));
view.layout(0, 0, targetWidth, targetHeight);
view.buildDrawingCache();
Bitmap bitmap = view.getDrawingCache();
How does this apply to the restriction with not accessing the Android UI toolkit from outside the UI thread, what could possibly go wrong?
In your case, you can do it of course, but be carefull only reading values from UI data, to avoid synchronizations bug.
Also you should not recreate the EditText from the background thread, it will be more efficient to directly access the already existant one instead:
Looper.prepare();
myEditText.setDrawingCacheEnabled(true);
Bitmap bitmap = myEditText.getDrawingCache();
If your question is : why it is not recommanded by android guidelines, here is a good SO answer to your question.
Calling View.buildDrawingCache() calls Bitmap.nativeCreate which can be a large allocation, so yes, it can be potentially harmful to run on main thread. I don't see a problem with calling Looper.prepare() in your background thread. However, it's unclear what you are trying to achieve and there may be a better solution to your problem.
The reason you are not supposed to the UI toolkit from other threads is that it is not written to be thread safe it is written under the assumption that only one thread runs it. This means it's really hard to tell what can go wrong, the bad effects, if any, will mostly happen in an un-repeatable due to specific timing of threads.
Your description of what you are trying to do it not too clear. In your case, I would just allocate a large bitmap, and draw text into it. Why are you using the EditText in the first place ? It seems like a kind of a hack, and hacks tend to break eventually.
Why View.buildDrawingCache()? What about using View.draw(Canvas canvas) to manually render to a Canvas backed by a Bitmap? Method seems simple enough to not cause problems on background threads.
EditText edit = (EditText)findViewById(R.id.edit);
edit.buildDrawingCache();
ImageView img = (ImageView)findViewById(R.id.test);
img.setImageBitmap(edit.getDrawingCache());
Lalit when you try to build the cache in the onCreate method, the drawing hasn't happened yet so the drawingCache should have nothing. Either put the buildDrawingChache method in the onClick method. Or use the following code in onCreate.
ViewTreeObserver vto = editText.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
editText.buildDrawingCache();
}
});
I also encountered this error a few times already:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
my solution:
new Thread(new Runnable(){
#Override
public void run(){
//add implementations that DOES NOT AFFECT the UI here
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run(){
//manage your edittext and Other UIs here
}
});
}
}).start();
just create a handler inside your worker thread to apply data changes to your UI

Binding changes in model reflect in TableView only after column resizing

First example work fine, if you run the next code you will see table.
Selected row is reflected in text field.
After saving changes their immediately reflecting in tableview due model properties to table cell binding.
In the second sample
after double clicking table view is hiding and edit form opened.
But after saving changes their reflect in table view only after column resizing.
How to fix this issue?
The issue appears to be that the TableView is not updated because it is not part of the Scene graph when the property is changed. (This would be a bug.) It does work fine in JavaFX8 (though you need to modify your code to ensure that the FX Nodes are initialized on the FX Application Thread; i.e. in the initComponents() method).
For a (fairly ugly) workaround to make this work in JavaFX 2.2, try the following:
private void openTable() {
Platform.runLater(new Runnable() {
#Override
public void run() {
table.setItems(FXCollections.<Person>observableArrayList());
vbox.getChildren().setAll(label, table);
table.setItems(data);
}
});
}
(I streamlined your existing code a little; also, the code you posted doesn't need a Platform.runLater(...) here as openTable() is only invoked from the FX Application Thread. However, this may be different in your real application.)

GXT custom event handler code executes multiple times

I have implemented MVP pattern in my GXT project. The system registers customers as part of it function. Also the system user can search for the registered user providing the id.
i have added an OnClick event to the "search customer" button.
/* On click search button */
view.getBtnSearch().addListener(Events.OnClick, new Listener<BaseEvent>() {
#Override
public void handleEvent(BaseEvent be) {
eventBus.fireEvent(new CustomerRegistrationTabSelectionEvent(0, false));
eventBus.fireEvent(new CustomerFetchEvent(view.getValueCustSearchParameter(), view.getValueCustSearchValue(), true));
}
});
The CustomerRegistrationTabSelectionEvent does select the relevant tab and enables other tabs. Thats all it does.
Here is the handler for the custom event CustomerFetchEvent.
eventBus.addHandler(CustomerFetchEvent.TYPE, new CustomerFetchEventHandler() {
#Override
public void fetchCustomer(CustomerFetchEvent event) {
searchCustomer(event.getParameter(), event.getParameterValue(), event.isOpenFirstTab());
}
});
The issue is the search customer method is executed multiple times and if there is a invalid search the error message dialog shows multiple popups. Within the searchCustomer method i call for service which fetch me the customer data or show the popup error message if the search is invalid.
im using GXT 2.2.5 and JRE 1.6.
Could anyone help me in finding out why the code is executed multiple times?
Added Later:
When i run the application first time the code is only executed only once, therefore only 1 popup. Then i logout of the system and log in again (navigating to the same page where the "search customer" button exists.) and the code is executed twice. Likewise equal to the number of times i create/navigate to the particular page, the code executes. Is it actually adding the event handler code without removing the last one every time i recreate the page?
Yes, it seems that 'addHandler' adds handler multiple times, but stores previous context. Your code should add handlers only once, on initialization phase. You can check the number of handlers with 'getHandlerCount' method.
Ya. I fixed it!Here is the solution Unbinding presenters necessary in GWT
U can read more here. http://draconianoverlord.com/2010/11/23/gwt-handlers.html
what happened actually was, the presenter objects where i have registered with HandlerManager to receive events were not garbage collected. Because though i remove the reference to the presenters still the HandlerManager holds a reference to those objects. So every time i kept on creating new presenters on top of the old presenters of the same class. so a event is listened by multiple objects of the same class. so u need to ensure that the unused presenters are garbage collected by removing the registered handlers
in HandlerManager.

How do I restrict keyboard focus to controls within a Node?

I'm trying to implement a reusable method for displaying a node as a lightweight dialog. The node is added to the top of a StackPane while the background is then blurred. There are 2 problems:
1) Controls in the background node of the stackpane are still able to receive focus.
2) How do I give focus to the top-level node. I know there is a requestFocus method on Node, but I need to give it to a control nested within the node. Since this is intended to be a reusable method, I can't reference the controls directly.
(if I can sidestep the whole problem by finding an existing implementation, that would be best, but I haven't found a 3rd party solution yet)
Thanks
For:
1) 3 alternative suggestions,
a- Add a key event handler to the dialogbox pane to catch the Tab key pressings
dialogbox.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(javafx.scene.input.KeyEvent event) {
if (event.getCode() == KeyCode.TAB) {
System.out.println("TAB pressed");
event.consume(); // do nothing
}
}
});
b- Temporarily disable all children of the main StackPane except the lastly added dialogbox child.
// Assuming dialogbox is at last in the children list
for(int i=0; i<mainPane.getChildren().size()-1; i++){
// Disabling will propagate to sub children recursively
mainPane.getChildren().get(i).setDisable(true);
}
c- Same as b but manually disable focusing to controls by node.setFocusTraversable(false) (spot kick). Surely this will not be your choice..
2) Tell the dialogbox which node should take the focus after the dialog is shown (through constructor or setter method).
// init dialogbox and show it then
dialogbox.setFocusTo(node_in_dialogbox);

Resources