Details

    • Subcomponent:
    • CPU:
      generic
    • OS:
      generic

      Description

      A DESCRIPTION OF THE REQUEST :
      Given a JFXPanel that has a Canvas component that is drawn on using GraphicContext.strokeLine() etc. methods. Rendering of the panel is visibly inferior in some cases than that of the pure JavaFX counterpart.

      JUSTIFICATION :
      We want to write a component that renders on FX Canvas and can be used in JFXPanel to provide Swing compatibility at the same time.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Rendering quality in JFXPanel should be the same as in the FX-counterpart
      ACTUAL -
      (given in the description)

      ---------- BEGIN SOURCE ----------
      import javafx.application.Platform;
      import javafx.embed.swing.JFXPanel;
      import javafx.scene.Group;
      import javafx.scene.Scene;
      import javafx.scene.canvas.Canvas;
      import javafx.scene.canvas.GraphicsContext;
      import javafx.scene.paint.Color;

      import javax.swing.JComponent;
      import javax.swing.JFrame;
      import javax.swing.SwingUtilities;
      import javax.swing.WindowConstants;
      import java.awt.Dimension;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.io.IOException;

      /**
       *
       */
      public class ImprovedGraphicsExample {
          private JFrame frame;

          private ImprovedGraphicsExample() {
              ImprovedJFXPanel p = new ImprovedJFXPanel();
              frame = createFrame("Improved rendering for JFXPanel", p, 320, 220);

              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                      p.init();
                  }
              });
          }

          private JFrame createFrame(String title, JComponent component, int width, int height) {
              final Dimension dimension = new Dimension(width, height);
              JFrame frame = new JFrame();
              frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
              frame.setPreferredSize(dimension);
              frame.setSize(dimension);
              frame.add(component);
              frame.setTitle(title);

              frame.pack();

              return frame;
          }

          private void show() {
              frame.setVisible(true);
          }

          public static void main(String[] args) throws IOException, InterruptedException {
              ImprovedGraphicsExample app = new ImprovedGraphicsExample();
              SwingUtilities.invokeLater(app::show);
          }

          ///////////////////////////////////////

          private class ImprovedJFXPanel extends JFXPanel {
              private final double internalScale = 1;
              private Canvas canvas;

              ImprovedJFXPanel() {
              }

              void init() {
                  Scene scene = createScene();
                  setScene(scene);
              }

              private Scene createScene() {
                  canvas = new Canvas();
                  canvas.setWidth(getWidth());
                  canvas.setHeight(getHeight());
                  scaleCanvas();

                  Group root = new Group();
                  root.getChildren().add(canvas);
                  drawLine();

                  return new Scene(root);
              }

              private void drawLine() {
                  GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
                  graphicsContext.save();

                  graphicsContext.translate(canvas.getWidth() / 2, canvas.getHeight() / 2);
                  graphicsContext.setStroke(Color.BLACK);
                  graphicsContext.setLineWidth(1.2);

                  double x1 = 0;
                  double y1 = -40;
                  int count = 6;
                  for (int i = 0; i < count; i++) {
                      double d = 2.2 * i;
                      double x2 = 60 * Math.cos(d * Math.PI/(2 * count));
                      double y2 = 60 * Math.sin(d * Math.PI/(2 * count));
                      graphicsContext.strokeLine(x1, y1, x2, y2);
                  }

                  graphicsContext.restore();
              }


              @Override
              public void paintComponent(Graphics g) {
                  double s = 1 / internalScale;
                  // scale-down what was scaled-up in FX graphics
                  ((Graphics2D) g).scale(s, s);
                  super.paintComponent(g);
              }

              // scale up canvas for FX
              private void scaleCanvas() {
                  canvas.setScaleX(internalScale);
                  canvas.setScaleY(internalScale);
              }

          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Above code exemplifies a workaround as well. If internalScale is changed to 2 rendering improves. Essentially, rendering process is the following:
      - scale GraphicsContext
      - draw sample
      - scale-down Graphics2D


        Attachments

        1. ImprovedGraphicsExample.java
          3 kB
          Priyanka Mangal
        2. Rendering_Comparison.png
          113 kB
          Priyanka Mangal
        3. Scaling_Comparison_8u152.png
          17 kB
          Priyanka Mangal
        4. Scaling_Comparison_9.0.1+11.png
          16 kB
          Priyanka Mangal

          Activity

            People

            • Assignee:
              psadhukhan Prasanta Sadhukhan
              Reporter:
              webbuggrp Webbug Group
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated: