JavaFx Canvas:如何进行XOR绘图?

时间:2014-01-12 13:52:19

标签: java javafx-2 javafx-8

我正在寻找像GraphicsContext .setMode( GraphicsContextMode.XOR )这样的方法,但我还没找到。

SSCCE下方绘制一些形状(实际上仅限于线条),有两种方法:在每次鼠标拖动事件或XOR绘图(不工作)时完成重绘:

public class XorApp extends Application {

   private static final boolean HAVE_XOR = false;

   private final Canvas       canvas   = new Canvas( 800, 600 );
   private final List< Line > segments = new LinkedList<>();
   private /* */ Line         segment  = null;

   private static void draw( GraphicsContext g, Line line ) {
      g.strokeLine(
         line.getStartX(), line.getStartY(), line.getEndX(), line.getEndY());
   }

   private void redrawAll( GraphicsContext g ) {
      g.clearRect( 0, 0, canvas.getWidth(), canvas.getHeight());
      for( final Line line : segments ) {
         draw( g, line );
      }
   }

   protected void started( double x, double y ) {
      if( segment != null ) {
         ended( segment.getEndX(), segment.getEndY());
      }
      segment = new Line( x, y, -1.0, -1.0 );
   }

   protected void dragged( double x, double y ) {
      if( segment == null ) {
         return;
      }
      final GraphicsContext g = canvas.getGraphicsContext2D();
      if( segment.getEndX() > -1.0 ) {
         if( HAVE_XOR ) {
            // Redraw the last segment erase it, thanks to XOR mode
            draw( g, segment );
         }
         else {
            redrawAll( g );
         }
      }
      segment.setEndX( x );
      segment.setEndY( y );
      draw( g, segment );
   }

   protected void ended( double x, double y ) {
      dragged( x, y );
      segments.add( segment );
      redrawAll( canvas.getGraphicsContext2D());
      segment = null;
   }

   @Override
   public void start( Stage stage ) throws Exception {
      if( HAVE_XOR ) {
         //-- SET XOR MODE HERE --
      }
      final BorderPane bp = new BorderPane();
      bp.setCenter( canvas );
      stage.setScene( new Scene( bp ));
      stage.centerOnScreen();
      stage.show();
      canvas.setOnMousePressed( new EventHandler<MouseEvent>() {
         @Override public void handle( MouseEvent event ) {
            started( event.getX(), event.getY()); }});
      canvas.setOnMouseDragged( new EventHandler<MouseEvent>() {
         @Override public void handle( MouseEvent event ) {
            dragged( event.getX(), event.getY()); }});
      canvas.setOnMouseClicked( new EventHandler<MouseEvent>() {
         @Override public void handle( MouseEvent event ) {
            ended( event.getX(), event.getY()); }});
   }

   public static void main( String[] args ) {
      launch( args );
   }
}

1 个答案:

答案 0 :(得分:0)

我刚刚遇到了同样的问题,开发了一个交互式绘图程序,希望XORmode在鼠标移动事件期间提供绘图反馈(这是我在其他库中完成它的方式,包括Swing)。我发现了两个解决方案第一个(不推荐)是嵌入Swing JPanel并通过调用SwingNode.setContent()强制它在需要时更新的因素,因为invalidate()在这种情况下不起作用。这也需要覆盖paintComponent。

更好的解决方案是在StackPane中使用两个JavaFX Canvas对象。一个(在底部)用于在鼠标移动期间绘制临时形状。在绘制临时形状之前,我只需清除它(在背景颜色中绘制一个大矩形)。完成形状后(MouseReleased事件),我再次清除临时画布并将永久对象绘制到顶部画布中。顶部Canvas保留其默认透明背景,以便可以看到临时形状。