ADDITIONAL SYSTEM INFORMATION :
Microsoft Windows [Version 10.0.18363.1198]
openjdk version "11.0.15" 2022-04-19
OpenJDK Runtime Environment Temurin-11.0.15+10 (build 11.0.15+10)
OpenJDK 64-Bit Server VM Temurin-11.0.15+10 (build 11.0.15+10, mixed mode)
JavaFX 19-ea+7
A DESCRIPTION OF THE PROBLEM :
Stage showing listener does not fire if the ProgressBar control is used inside scene of Stage which is showing, because the ProgressIndicatorSkin is adding listener inside Stage#showingProperty's invalidate method which causes to reinitialize inner helper and changing current value, so there is no change.
com.sun.javafx.scene.TreeShowingExpression is used in sample only for test purposes to direct you on the right issue.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open ShowingTestSample from provided test case.
2. Click on the "Standard stage" button and close new window.
3. Click on the "ProgressBarStage stage" button and close new window.
4. Click on the "CustomSkin stage 2" button and close new window.
5. Click on the "Property Listener test
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After all, console should print:
Standard stage listener: true
Standard stage listener: false
ProgressBarStage listener: true
ProgressBarStage listener: false
CustomSkin listener: true
CustomSkin listener: false
Should fire listener: true
ACTUAL -
After all, console prints:
Standard stage listener: true
Standard stage listener: false
ProgressBarStage listener: false
CustomSkin listener: false
---------- BEGIN SOURCE ----------
import com.sun.javafx.scene.TreeShowingExpression;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.Skin;
import javafx.scene.control.skin.LabelSkin;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class ShowingTestSample
{
public static void main( String[] args )
{
System.err.println( Runtime.version().toString() );
Application.launch( ShowingTestSample.MainFx.class, args );
}
public static class MainFx extends Application
{
@Override
public void start( final Stage primaryStage ) throws Exception
{
System.err.println( System.getProperty( "javafx.version" ) );
final var standardStageButton = new Button( "Standard stage" );
standardStageButton.setOnAction( aActionEvent -> {
openStandardStage();
} );
final var buggedStageButton = new Button( "ProgressBarStage stage" );
buggedStageButton.setOnAction( aActionEvent -> {
openBuggedListenerStage();
} );
final var buggedStageButton2 = new Button( "CustomSkin stage 2" );
buggedStageButton2.setOnAction( aActionEvent -> {
openBuggedListenerStage_2();
} );
final var buggedPropertyButton = new Button( "Property Listener test" );
buggedPropertyButton.setOnAction( aActionEvent -> {
testPropertyListener();
} );
final var hbox = new HBox( 5d, standardStageButton, buggedStageButton, buggedStageButton2,
buggedPropertyButton );
hbox.setAlignment( Pos.CENTER );
Scene scene = new Scene( new BorderPane( hbox ), 700, 300 );
primaryStage.setScene( scene );
primaryStage.show();
}
private static void testPropertyListener()
{
final var property = new SimpleObjectProperty< Object >( null )
{
@Override
protected void invalidated()
{
this.addListener( ( aObservableValue, aO, aNewValue ) -> {
System.out.println( "Should fire listener2: " + aNewValue );
} );
}
};
property.addListener( ( aObservableValue, aO, aNewValue ) -> {
System.out.println( "Should fire listener: " + aNewValue );
} );
property.set( Boolean.TRUE );
}
private void openBuggedListenerStage()
{
final var stage = new Stage( StageStyle.DECORATED );
final var root = new BorderPane( new ProgressBar( 0.5d ) );
Scene scene = new Scene( root, 300, 300 );
stage.showingProperty().addListener( ( aObservableValue, aBoolean, aT1 ) -> {
System.out.println( "ProgressBarStage listener: " + aT1 );
} );
stage.setScene( scene );
stage.show();
}
private void openBuggedListenerStage_2()
{
final var stage = new Stage( StageStyle.DECORATED );
final var root = new BorderPane( new Label( "sampleLabel2" )
{
@Override
protected Skin< ? > createDefaultSkin()
{
return new LabelSkin( this )
{
{
new TreeShowingExpression( getSkinnable() );
}
};
}
} );
Scene scene = new Scene( root, 300, 300 );
stage.showingProperty().addListener( ( aObservableValue, aBoolean, aT1 ) -> {
System.out.println( "CustomSkin listener: " + aT1 );
} );
stage.setScene( scene );
stage.show();
}
private void openStandardStage()
{
final var stage = new Stage( StageStyle.DECORATED );
final var root = new BorderPane( new Label( "sample label" ) );
Scene scene = new Scene( root, 300, 300 );
stage.showingProperty().addListener( ( aObservableValue, aBoolean, aT1 ) -> {
System.out.println( "Standard stage listener: " + aT1 );
} );
stage.setScene( scene );
stage.show();
}
}
}
---------- END SOURCE ----------
FREQUENCY : always
Microsoft Windows [Version 10.0.18363.1198]
openjdk version "11.0.15" 2022-04-19
OpenJDK Runtime Environment Temurin-11.0.15+10 (build 11.0.15+10)
OpenJDK 64-Bit Server VM Temurin-11.0.15+10 (build 11.0.15+10, mixed mode)
JavaFX 19-ea+7
A DESCRIPTION OF THE PROBLEM :
Stage showing listener does not fire if the ProgressBar control is used inside scene of Stage which is showing, because the ProgressIndicatorSkin is adding listener inside Stage#showingProperty's invalidate method which causes to reinitialize inner helper and changing current value, so there is no change.
com.sun.javafx.scene.TreeShowingExpression is used in sample only for test purposes to direct you on the right issue.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open ShowingTestSample from provided test case.
2. Click on the "Standard stage" button and close new window.
3. Click on the "ProgressBarStage stage" button and close new window.
4. Click on the "CustomSkin stage 2" button and close new window.
5. Click on the "Property Listener test
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
After all, console should print:
Standard stage listener: true
Standard stage listener: false
ProgressBarStage listener: true
ProgressBarStage listener: false
CustomSkin listener: true
CustomSkin listener: false
Should fire listener: true
ACTUAL -
After all, console prints:
Standard stage listener: true
Standard stage listener: false
ProgressBarStage listener: false
CustomSkin listener: false
---------- BEGIN SOURCE ----------
import com.sun.javafx.scene.TreeShowingExpression;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.Skin;
import javafx.scene.control.skin.LabelSkin;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class ShowingTestSample
{
public static void main( String[] args )
{
System.err.println( Runtime.version().toString() );
Application.launch( ShowingTestSample.MainFx.class, args );
}
public static class MainFx extends Application
{
@Override
public void start( final Stage primaryStage ) throws Exception
{
System.err.println( System.getProperty( "javafx.version" ) );
final var standardStageButton = new Button( "Standard stage" );
standardStageButton.setOnAction( aActionEvent -> {
openStandardStage();
} );
final var buggedStageButton = new Button( "ProgressBarStage stage" );
buggedStageButton.setOnAction( aActionEvent -> {
openBuggedListenerStage();
} );
final var buggedStageButton2 = new Button( "CustomSkin stage 2" );
buggedStageButton2.setOnAction( aActionEvent -> {
openBuggedListenerStage_2();
} );
final var buggedPropertyButton = new Button( "Property Listener test" );
buggedPropertyButton.setOnAction( aActionEvent -> {
testPropertyListener();
} );
final var hbox = new HBox( 5d, standardStageButton, buggedStageButton, buggedStageButton2,
buggedPropertyButton );
hbox.setAlignment( Pos.CENTER );
Scene scene = new Scene( new BorderPane( hbox ), 700, 300 );
primaryStage.setScene( scene );
primaryStage.show();
}
private static void testPropertyListener()
{
final var property = new SimpleObjectProperty< Object >( null )
{
@Override
protected void invalidated()
{
this.addListener( ( aObservableValue, aO, aNewValue ) -> {
System.out.println( "Should fire listener2: " + aNewValue );
} );
}
};
property.addListener( ( aObservableValue, aO, aNewValue ) -> {
System.out.println( "Should fire listener: " + aNewValue );
} );
property.set( Boolean.TRUE );
}
private void openBuggedListenerStage()
{
final var stage = new Stage( StageStyle.DECORATED );
final var root = new BorderPane( new ProgressBar( 0.5d ) );
Scene scene = new Scene( root, 300, 300 );
stage.showingProperty().addListener( ( aObservableValue, aBoolean, aT1 ) -> {
System.out.println( "ProgressBarStage listener: " + aT1 );
} );
stage.setScene( scene );
stage.show();
}
private void openBuggedListenerStage_2()
{
final var stage = new Stage( StageStyle.DECORATED );
final var root = new BorderPane( new Label( "sampleLabel2" )
{
@Override
protected Skin< ? > createDefaultSkin()
{
return new LabelSkin( this )
{
{
new TreeShowingExpression( getSkinnable() );
}
};
}
} );
Scene scene = new Scene( root, 300, 300 );
stage.showingProperty().addListener( ( aObservableValue, aBoolean, aT1 ) -> {
System.out.println( "CustomSkin listener: " + aT1 );
} );
stage.setScene( scene );
stage.show();
}
private void openStandardStage()
{
final var stage = new Stage( StageStyle.DECORATED );
final var root = new BorderPane( new Label( "sample label" ) );
Scene scene = new Scene( root, 300, 300 );
stage.showingProperty().addListener( ( aObservableValue, aBoolean, aT1 ) -> {
System.out.println( "Standard stage listener: " + aT1 );
} );
stage.setScene( scene );
stage.show();
}
}
}
---------- END SOURCE ----------
FREQUENCY : always