javafx setOpacity method doesn't work when repeated for some times - javafx

I use a Thread to change the opacity of an AnchorPane.
I add an onMouseEnter method to raise opacity gradually,and an onMouseExited method to decrease opacity gradually.
I have two panes, if my mouse enter any one of them,both two panes will change opacity.
Then I start my application, I find that after my mouse enter and exit the pane for some times, one will stop at a specific opacity,while the other still change opacity gradually.
I am confused why this happen...
My codes are like:
private double base = 0.5;
private void changeOpacity(boolean increase){
new Thread(()-> {
while((increase && base < 0.9) || ((!increase)&&base > 0.5)){
base += increase?0.01:-0.01;
leftPane.setOpacity(base);
rightPane.setOpacity(base);
Thread.sleep(5);
}
}
}
I am sorry for my poor English.
Thanks.!

You are only allowed to change values of JavaFX components while you are on the JavaFX-Thread (something you are clearly not).
You need to sync yourself back using Platform.runLater(Runnable) but in your case you'd swap the event loop with Runnables which an equally bad idea.
The correct way is:
Use a Timeline with a KeyFrame
Use the already predefined FadeTransition foreach Node (together with a ParallelTransition)

Related

Restore window to normal doesn't work after maximized in qt on ubuntu 18.04

I meet two problems, I searched, but they seems not so easy as I think.
I'm working on ubuntu-18.04 with qt-5.15.x. And my two problems are:
cannot restore my window after maximizing it.
cannot move my window out of my screen with mouse dragging
Can not restore
Firstly, I set my window frameless, and then using a button standing for maximize or restoreoperations to trigger maximization or normal
// set fremeless in contruction
setWindowFlags(Qt::FramelessWindowHint | windowFlags());
// maximaization slot or restore
void WindowTitle::onButtonMaxClicked()
{
QWidget *pWin = window();
if(pWin->isMaximized())
{
pWin->showNormal();
}
else
{
pWin->showMaximized();
}
}
What I expected is when I click button ,window will maximized, and that is true indeed. Then clicking on button again, window will return original position and size again, but that doesn't happen, instead, window's height is correct, but its width is equal screen(getting rid of applications docker bar), x-axis value is wrong too. And I have tried setGeometry after I have stored its value, but failed.
Can not move outside
I can make sure that I have set correct position with
void WindowTitle::mouseMoveEvent(QMouseEvent *event)
{
if (m_isPressed)
{
QPoint movePoint = event->globalPos() - m_startMovePos;
QPoint widgetPos = QApplication::activeWindow()->pos();
m_startMovePos = event->globalPos();
QApplication::activeWindow()->move(widgetPos.x() + movePoint.x(), widgetPos.y() + movePoint.y());
}
return QWidget::mouseMoveEvent(event);
}
function, but the result shows something wrong.
I have searched above two questions. But get nothing. And I'm curious that other applications can do just right both restore and move, suchlike Firefox web browser(which I'm typing on). So, there must be some way to make it work.

Reset infinite JavaFX RotateTransition

Problem
In my application i use an infinite RotateTransition.
Button btnRotating = new Button("I'm rotating");
final RotateTransition rt = new RotateTransition(Duration.millis(2000), btnRotating);
rt.setFromAngle(0);
rt.setToAngle(180);
rt.setInterpolator(Interpolator.LINEAR);
rt.setCycleCount(Timeline.INDEFINITE);
When i stop this transition i want to reset the rotated node to its initial position.
rt.stop();
rt.getNode().setRotate(0);
Problem is that rt.stop() is asynchronous so the transition might not have stopped when i reset the rotation of the node. So occasionally the transition will overwrite my rotation reset.
Unsuccessful solutions
rt.onFinishedProperty().addListener((observable, oldValue, newValue) -> {
rt.getNode().setRotate(0);
});
Executing rt.getNode().setRotate(0) when the onFinishedProperty of the transition changes does not work as stopping the transition manually does not trigger the onFinishedProperty.
rt.statusProperty().addListener((observable, oldValue, newValue) -> {
if(newValue == Status.STOPPED){
rt.getNode().setRotate(0);
}
});
Listening for the statusProperty of the transition has the same problem as resetting the rotation manually. The status property gets set to STOPPED as soon as i call rt.stop() but it does not wait until the transition is terminated.
Question
So how can i safely reset my node to its initial position? How can i determine that the transition has really ended when i reset the node?
When i execute rt.getNode().setRotate(0) on the JavaFX application thread it seems to work reliably as my reset rotation gets queued after the last transition rotation. Is this the best solution? Should rt.stop() and rt.start also be executed on the FX thread?
Another thing i noticed is that in JavaDoc of the rt.stop() function it says: "Stops the animation and resets the play head to its initial position." So the play head gets reset but this reset is not transferred to the node as the transition is stopped. Is there a way to make use of that?
btnRotating.setOnAction(event -> {
if (rt.statusProperty().get() == Animation.Status.RUNNING){
rt.stop();
btnRotating.setRotate(0);
}else{
rt.playFromStart();
}
});
you can stop animation from background thred by use this
Platform.runLater(() -> {
rt.stop();
btnRotating.setRotate(0);
});

disable animation in BrowseFragment when selected item change

I want to disable the default animation on items in a BrowseFragment when they are selected ie scaling animation and the change of position. I want the items to stay where they are and not change their size when selected.
So far I tried various things on my ListRowPresenter object like setting the OnItemViewSelectedListene to null but without successful effect.
How can I achieve this ? (I'm using the version 26 of the leanback library)
You can set the zoom factor for the animation to none by passing in ZOOM_FACTOR_NONE to the constructor of the ListRowPresenter.
There is a constructor for ListRowPresenter to control the animation (focusZoom).
From the documentation:
ListRowPresenter (int focusZoomFactor)
Constructs a ListRowPresenter with the given parameters.
Parameters
focusZoomFactor int: Controls the zoom factor used when an item view is focused. One of ZOOM_FACTOR_NONE, ZOOM_FACTOR_SMALL, ZOOM_FACTOR_XSMALL, ZOOM_FACTOR_MEDIUM, ZOOM_FACTOR_LARGE Dimming on focus defaults to disabled.
Example:
ArrayObjectAdapter adapter =
new ArrayObjectAdapter(new ListRowPresenter(ZOOM_FACTOR_NONE));
setAdapter(adapter);
ArrayObjectAdapter rowAdapter =
new ArrayObjectAdapter(new MyCardViewPresenter(getContext()));
HeaderItem header = new HeaderItem("Header Title");
ListRow row = new ListRow(header, rowAdapter);
for (Video video : videos) {
rowAdapter.add(video);
}
adapter.add(row);

Changing grid column's/row's width/height by storyboard animation in Windows Store App

I'm looking for some method to change grid column's width (or row's height) by animtion defined in Storyboard. I have already found some solutions for WPF apps, but they are all useless in case of Windows Store programming, eg.:
Grid Column changing Width when animating
how to change the height of a grid row in wpf using storyboard
http://www.codeproject.com/Articles/18379/WPF-Tutorial-Part-2-Writing-a-custom-animation-cla
Is such result obtainable by creating a custom class, inheriting from Timeline? If so, which components should be overrode for proper implementation?
You should be able to use a simple DoubleAnimation. Make sure to set EnableDependentAnimation=True, as outline here.
One thing to realize when trying things out is that ColumnDefinitions are a GridLength struct. You can find more information on them here. You will need to have the animation set the Value property.
Here is a sample method to animate a Grid ColumnDefinition MaxWidth.
private void Animate(ColumnDefinition column)
{
Storyboard storyboard = new Storyboard();
Duration duration = new Duration(TimeSpan.FromMilliseconds(500));
CubicEase ease = new CubicEase { EasingMode = EasingMode.EaseOut };
DoubleAnimation animation = new DoubleAnimation();
animation.EasingFunction = ease;
animation.Duration = duration;
storyboard.Children.Add(animation);
animation.From = 1000;
animation.To = 0;
animation.EnableDependentAnimation = true;
Storyboard.SetTarget(animation, column);
Storyboard.SetTargetProperty(animation, "(ColumnDefinition.MaxWidth)");
storyboard.Begin();
}

fragments, android:zAdjustment (z order) and animations

I'm using the support library. Now, I want to have a fragment shifting in from the bottom, moving OVER the previous one.
For this I use this to keep the previous fragment (the one that is being slided over) visible until the new fragment is in its place:
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0" android:toAlpha="1.0"
android:duration="2500"
android:zAdjustment="bottom" />
this is animation used for the new fragment to slide in from bottom:
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromYDelta="100%p" android:toYDelta="0"
android:duration="#android:integer/config_mediumAnimTime"
android:zAdjustment="top"/>
I've put the z adjustment to bottom and top for both, but still the 'bottom' animation is still on top of the new fragment! I have put the duration to 2500 for testing and it stays on top for the whole time.
Does zAdjustment not work for fragment animations?
According to this google group thread Z adjustment only works for window animations.
"The Z adjustment only works for window animations. I thought this was documented, but apparently not."
-- Dianne Hackborn (Android framework engineer)
You can override the onCreateAnimation method and for any animations you can check what animation is currently running and if you need it to be on top, set the Z-axis from there.
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
if (nextAnim == R.anim.enter_from_right || nextAnim == R.anim.exit_to_right) {
ViewCompat.setTranslationZ(view, 1f)
} else {
ViewCompat.setTranslationZ(view, 0f)
}
return super.onCreateAnimation(transit, enter, nextAnim)
}
Recommend implementing this as a base Fragment class for all your fragments.
I've also got stuck with that problem. So instead of using transaction.replace(containerId, newFragment) I've created two containers for fragments and now my code looks like this one
Add first fragment:
transaction.add(containerId1, firstFragment).commit();
Add second fragment with animation over the first one:
findViewById(containerId2).bringToFront();
transaction.setCustomAnimations(R.anim.slide_in_up,
R.anim.stay).remove(oldFragment).add(containerId2, newFragment).commit()
You can use androidx.fragment.app.FragmentContainerView as a fragments container. It automatically handles z order for animations specified in setCustomAnimations()

Resources