I have a java application with old vector graphics editor written in pure Java Swing and Java2D.
Now I want to migrate the whole application to Javafx toolkit, except graphics editor. Graphics editor remains Swing/Java2D - based to avoid long rewriting of graphical event handling to Javafx. The only way i know to do this is the use of JavaFX SwingNode component.
The problem is with mouse painting on Swing component located inside JavaFX SwingNode: mouse events are handling well, but there is no graphical changes visible. The same component located in Swing JFrame is painting well. (Note that painting MUST be performed without full repaint of the swing component).
Does anyone know any way to achieve the same behavour in SwingNode as in JFrame?
The test class TestPaintOnSwingNode.java below do the work:
package x;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
public class TestPaintOnSwingNode extends Application {
private Scene scene;
private Stage stage;
@Override
public void start(Stage stage) throws Exception {
stage.setTitle("Swing PaintPanel on JavaFX Stage with SwingNode");
stage.setWidth(1200);
stage.setHeight(800);
AnchorPane rootPane = new AnchorPane();
scene = new Scene(rootPane);
createPaintPaneOnFXSwingNode(rootPane);
SwingUtilities.invokeLater(()->
createPaintPaneOnJFrame()
);
stage.setScene(scene);
stage.show();
}
private void createPaintPaneOnJFrame() {
JFrame frame = new JFrame();
frame.setTitle("Swing PaintPanel on Swing JFrame");
frame.setSize(new Dimension(1200, 800));
frame.add(new PaintPanel());
frame.setVisible(true);
}
private void createPaintPaneOnFXSwingNode(AnchorPane pane) {
SwingNode swingNode = new SwingNode();
SwingUtilities.invokeLater(() -> swingNode.setContent(
new PaintPanel()
));
pane.getChildren().add(swingNode);
AnchorPane.setLeftAnchor(swingNode, 0D);
AnchorPane.setRightAnchor(swingNode, 0D);
AnchorPane.setTopAnchor(swingNode, 0D);
AnchorPane.setBottomAnchor(swingNode, 0D);
}
}
class PaintPanel extends JPanel implements MouseListener, MouseMotionListener {
private int lastX = 0;
private int lastY = 0;
PaintPanel() {
addMouseListener(this);
addMouseMotionListener(this);
setBackground(Color.ORANGE);
}
@Override
public void mouseClicked(MouseEvent e) {
lastX = e.getX();
lastY = e.getY();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
if (lastX > 0) {
System.out.println(e);
Graphics2D graphics = (Graphics2D) getGraphics();
graphics.drawLine(lastX, lastY, e.getX(), e.getY());
lastX = e.getX();
lastY = e.getY();
}
}
}
Results after running the test class and some mouse motion over a component are shown below. The test simply draws a line from previuos mouse coordinate to current. Painting starts after first click on a PaintPanel. Events are printing well in console when mouse is moved on each of both dialogs. But painting results are visible only in native Swing window.

getGraphics(). That is not how Swing custom painting works. Instead, you need to overridepaintComponentand make sure the first line of code in the method body issuper.paintComponent. See docs.oracle.com/javase/tutorial/uiswing/painting.