Details
Description
Swing Nodes are not behaving well, even for simple JPanels.
-A simple test which initializes 8 Swing Nodes on a StackPane will demonstrate varying results.
-Sometimes the JPanels show up black, instead of rendering.
-Sometimes there are black rectangular artifacts between JPanels.
-Sometimes the JPanels appear (black again), but then vanish.
-Sometimes resizing the window brings them back, up other times, they are never seen again.
-Upon resizing the window, the JPanels will continue to render correctly (unless they don't come back).
-Any attempt to resize the primary stage programmatically causes the stage to go black, and components will show up again one by one as you move the mouse over them, or will reappear if you manually resize with your mouse.
I have tries, and have not been able to come up with any workaround for these problems. As such, I cannot progress with my conversion from Swing to JavaFX.
--
Simple, well commented example code below:
--
package fas.testing;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingNode;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test2 extends Application{
//XXX Use these flags to test different aspects of the swing node bugs
private boolean USE_TOP_LEFT = false;
private boolean WAIT_FOR_SWING = true;
// instance variables, to allow configuring of the swing nodes in separate method
private Stage primaryStage;
private Scene scene;
private StackPane root;
// random used to place nodes
private static final Random rand = new Random();
private void initPresentation(){
// add 8 randomly placed swing nodes of identical size
for(int i = 0; i < 8; i++){
// create the swing node
SwingNode swingNode = new SwingNode();
// set the location, randomly
swingNode.setTranslateX(rand.nextDouble()*400);
// IMPORTANT -- this test demonstrates noticeably different behavior when StackPane is TOP_LEFT aligned.
// to compare, change USE_TOP_LEFT to false (we translate y values to be from the bottom in this case)
if(USE_TOP_LEFT)
swingNode.setTranslateY(rand.nextDouble()*400);
else
swingNode.setTranslateY(-rand.nextDouble()*400);
// add the node to the parent
root.getChildren().add(swingNode);
final int myI = i; // we'll use this index to determine if its okay to display the primary stage yet
// invoke all swing stuff on AWT EDT
SwingUtilities.invokeLater(()->{
// create a jpanel
JPanel panel = new JPanel();
// give it a random color
panel.setBackground(new java.awt.Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)));
// set the preferred / max size
panel.setPreferredSize(new Dimension(100, 100));
panel.setMaximumSize(new Dimension(100, 100));
// assign this JPanel to the javafx swing node (method is supposedly safe to call from AWT EDT)
swingNode.setContent(panel);
// if we wait for swing to finish initializing all components before displaying, does this help? A little, but it does not fix the problems sufficiently to serve as workaround.
if(myI == 7 && WAIT_FOR_SWING)
Platform.runLater(()->primaryStage.show());
});
}
}
public void start(Stage primaryStage) throws Exception {
// set our primary stage, and give it a title
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Swing Node Test");
// create our root stack pane, and make it so that nodes in it are top/left aligned
this.root = new StackPane();
if(USE_TOP_LEFT)
this.root.setAlignment(Pos.TOP_LEFT); // align all components to top-left corner. This causes everything to go blank.
else
this.root.setAlignment(Pos.BOTTOM_LEFT); // align all components to bottom-left corner. This works better than TOP_LEFT, but still clearly has problems.
// create a scene, which views our root stack pane. Make it the primaryStage's scene.
this.scene = new Scene(root);
this.primaryStage.setScene(scene);
this.primaryStage.setWidth(400);
this.primaryStage.setHeight(400);
// create the randomly arranged swing nodes.
initPresentation();
// present the stage
if(!WAIT_FOR_SWING)
this.primaryStage.show();
}
public static void main(String... args){
if(!GraphicsEnvironment.isHeadless())
Application.launch(args);
else
System.err.println("Error: could not start TEST: this operating system is console based, and does not provide any means for displaying graphics to the screen.");
}
}
-A simple test which initializes 8 Swing Nodes on a StackPane will demonstrate varying results.
-Sometimes the JPanels show up black, instead of rendering.
-Sometimes there are black rectangular artifacts between JPanels.
-Sometimes the JPanels appear (black again), but then vanish.
-Sometimes resizing the window brings them back, up other times, they are never seen again.
-Upon resizing the window, the JPanels will continue to render correctly (unless they don't come back).
-Any attempt to resize the primary stage programmatically causes the stage to go black, and components will show up again one by one as you move the mouse over them, or will reappear if you manually resize with your mouse.
I have tries, and have not been able to come up with any workaround for these problems. As such, I cannot progress with my conversion from Swing to JavaFX.
--
Simple, well commented example code below:
--
package fas.testing;
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.util.Random;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingNode;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class Test2 extends Application{
//XXX Use these flags to test different aspects of the swing node bugs
private boolean USE_TOP_LEFT = false;
private boolean WAIT_FOR_SWING = true;
// instance variables, to allow configuring of the swing nodes in separate method
private Stage primaryStage;
private Scene scene;
private StackPane root;
// random used to place nodes
private static final Random rand = new Random();
private void initPresentation(){
// add 8 randomly placed swing nodes of identical size
for(int i = 0; i < 8; i++){
// create the swing node
SwingNode swingNode = new SwingNode();
// set the location, randomly
swingNode.setTranslateX(rand.nextDouble()*400);
// IMPORTANT -- this test demonstrates noticeably different behavior when StackPane is TOP_LEFT aligned.
// to compare, change USE_TOP_LEFT to false (we translate y values to be from the bottom in this case)
if(USE_TOP_LEFT)
swingNode.setTranslateY(rand.nextDouble()*400);
else
swingNode.setTranslateY(-rand.nextDouble()*400);
// add the node to the parent
root.getChildren().add(swingNode);
final int myI = i; // we'll use this index to determine if its okay to display the primary stage yet
// invoke all swing stuff on AWT EDT
SwingUtilities.invokeLater(()->{
// create a jpanel
JPanel panel = new JPanel();
// give it a random color
panel.setBackground(new java.awt.Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)));
// set the preferred / max size
panel.setPreferredSize(new Dimension(100, 100));
panel.setMaximumSize(new Dimension(100, 100));
// assign this JPanel to the javafx swing node (method is supposedly safe to call from AWT EDT)
swingNode.setContent(panel);
// if we wait for swing to finish initializing all components before displaying, does this help? A little, but it does not fix the problems sufficiently to serve as workaround.
if(myI == 7 && WAIT_FOR_SWING)
Platform.runLater(()->primaryStage.show());
});
}
}
public void start(Stage primaryStage) throws Exception {
// set our primary stage, and give it a title
this.primaryStage = primaryStage;
this.primaryStage.setTitle("Swing Node Test");
// create our root stack pane, and make it so that nodes in it are top/left aligned
this.root = new StackPane();
if(USE_TOP_LEFT)
this.root.setAlignment(Pos.TOP_LEFT); // align all components to top-left corner. This causes everything to go blank.
else
this.root.setAlignment(Pos.BOTTOM_LEFT); // align all components to bottom-left corner. This works better than TOP_LEFT, but still clearly has problems.
// create a scene, which views our root stack pane. Make it the primaryStage's scene.
this.scene = new Scene(root);
this.primaryStage.setScene(scene);
this.primaryStage.setWidth(400);
this.primaryStage.setHeight(400);
// create the randomly arranged swing nodes.
initPresentation();
// present the stage
if(!WAIT_FOR_SWING)
this.primaryStage.show();
}
public static void main(String... args){
if(!GraphicsEnvironment.isHeadless())
Application.launch(args);
else
System.err.println("Error: could not start TEST: this operating system is console based, and does not provide any means for displaying graphics to the screen.");
}
}
Attachments
Issue Links
- duplicates
-
JDK-8093698 Rendering artifacts when using SwingNode
-
- Closed
-
-
JDK-8093211 Using JavaFX and SwingNode - The Background and the JavaFX Button ist black
-
- Closed
-
- relates to
-
JDK-8088493 Swing content and SwingNode sizes should always be equal
-
- Closed
-