Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4204551

XOR mode for shapes broken in swing components but not AWT

XMLWordPrintable

    • 2d
    • beta
    • generic, x86
    • generic, windows_95, windows_nt

      Name: gsC80088 Date: 01/20/99


      // This program draws two ellipses by the SAME
      // operators:
      // g2D.draw( new Ellipse2D.Double( r, r, 3 * r, 3 * r ) );
      // One of them in PINT mode, another in XOR.
      // As the result you can see one ellipse and one
      // RECTANGLE?!
      //
      // I guess something wrong with scale calculation
      // in XOR mode.

      import java.awt.*;
      import java.awt.geom.*;
      import javax.swing.*;


      class TestComponent extends JComponent
      {
      public void paint( Graphics g )
      {
      Graphics2D g2D = ( Graphics2D ) g;

      double scale = 10000.;
      float r = 0.007f;

      g2D.setColor( Color.white );
      g2D.fill( new Rectangle2D.Double( 0., 0., 500., 500. ) );

      g2D.setColor( Color.red );
      g2D.scale( scale, scale );

      g2D.setStroke( new BasicStroke( ( float )( 1. / scale ) ) );

      g2D.draw( new Ellipse2D.Double( r, r, 3 * r, 3 * r ) );

      g2D.setXORMode( Color.green );

      g2D.draw( new Ellipse2D.Double( r, r, 3 * r, 3 * r ) );
      }
      }


      public class test
      {
      static public void main( String [] args )
      {
      JFrame frame = new JFrame();
      frame.setContentPane( new TestComponent() );


      frame.setSize( 500, 500 );
      frame.show();
      }
      }
      (Review ID: 52396)
      ======================================================================

      Name: gsC80088 Date: 02/18/99


      D:\Users\Jolif\Support\UK>java -fullversion
      java full version "JDK-1.2-V"

      When drawing a Component in a JInternalFrame, the Graphics used is not
      always the same. There is a difference of 1 pixel (in each
      direction) between :

      1/ the Graphics get in paint(Graphics) method of my Component
      inside the JIF when the JIF gets the focus.
      2/ the Graphics returned at any time by Component.getGraphics().

      To see the problem. Just add a dummy component to a JIF.
      This dummy component should draw a rectangle (10,10,50,50) in XOR
      mode in its paint method.

      Later, on a mouse pressed event, get the graphics of the component
      and draw the same rectangle always in XOR mode. The first one is
      not erased because of the different translation of both Graphics.
      (you see a second rectangle (1,1) pixels after the first one).

      When your are using ghost drawings in a JIF in a more complicated
      application it is very annoying.

      Here is the example :

      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;


      class View extends Container
      {
        public View()
        {
          super();
        }
        public void paint(Graphics g)
        {
          // System.err.println("paint "+g);
          new Throwable().printStackTrace();
          Rectangle clip = g.getClipBounds();
          g.setColor(getBackground());
          g.fillRect(clip.x, clip.y, clip.width, clip.height);
          g.setColor(Color.red);
          g.setXORMode(Color.blue);
          g.drawRect(10,10,50,50);
          g.setPaintMode();
        }
      }

      public class BadInternal extends JFrame
      {
        public static void main(String[] arg)
        {
          new BadInternal();
        }

        public BadInternal()
        {
          super("Bad Internal Sample");
          setSize(800,600);
          
          addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
      BadInternal.this.dispose();
      System.exit(0);
            }
          });
          
         
          // Creates the MDI manager
          JDesktopPane desktop = new JDesktopPane();
          getContentPane().add(desktop);

          // Creates the JInternalFrame in which we will put the drag source IlvManagerView
          JInternalFrame f1 =
            new JInternalFrame("Drag an IlvGraphic from this IlvManagerView", true);

          // Create s the JInternalFrame in which we will put the drop target IlvMAnagerView
          JInternalFrame f2 =
            new JInternalFrame("Drop an IlvGraphic on this IlvManagerView", true);

          f1.setBounds(20,20, 420, 260);
          f2.setBounds(320,280,420, 260);

          final View view = new View();
          addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
      Graphics g = view.getGraphics();
      g.setColor(Color.red);
      g.setXORMode(Color.blue);
      g.drawRect(10,10,50,50);
      g.setPaintMode();
            }
          });
          f1.getContentPane().add(view);

          desktop.add(f1);
          desktop.add(f2);
          
          setVisible(true);
        }
      }
      ======================================================================

      Name: mc57594 Date: 11/27/99


      java version "1.3beta"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.3beta-O)
      Java(TM) HotSpot Client VM (build 1.3beta-O, mixed mode)


      A drawString in "xor" mode does not properly clear an identical string drawn in
      "paint" mode.

      Using setXorMode in an attempt to clear a previously drawn string leaves
      artifacts of the string on the screen. This problem prevents implementation of
      string drag operations.

      The following code demonstrates the problem. The "toggle" button toggles the
      display between a normal display and an xor'ed display. If xor worked properly,
      both the text and the horizontal line should be cleared by the xor operation
      leaving a blank panel. Instead artifacts of the string remain, and the line
      appears to have doubled in thickness.

      ------------------------------------------------------
      import javax.swing.*;
      import java.awt.*;
      import java.awt.event.*;

      public class XorTest extends JPanel {

         boolean xor = false;

         public XorTest() {
            super();
            setLayout(null);
            JButton b = new JButton("Toggle");
            add(b);
            b.setSize(100, 50);
            b.setLocation(50, 100);
            b.addActionListener(
               new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                     xor = !xor;
                     repaint();
                  }
               }
            );
            setForeground(Color.black);
            setBackground(Color.white);
         }

         public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (xor) {
               g.setPaintMode();
               g.drawString("Hello World!", 60, 40);
               g.drawLine(60, 70, 140, 70);
               g.setXORMode(Color.white);
               
               //The following commands should clear the panel, but artifacts
               //of the String remain, and the line is doubled up.
               g.drawString("Hello World!", 60, 40);
               g.drawLine(60, 70, 140, 70);
            }
            else {
               g.setPaintMode();
               g.drawString("Hello World!", 60, 40);
               g.drawLine(60, 70, 140, 70);
            }
            g.setPaintMode();
         }

         public static void main(String args[]) {
            JFrame f = new JFrame("XorTest");
            f.addWindowListener(
               new WindowAdapter() {
                  public void windowClosing(WindowEvent e) {
                     System.exit(0);
                  }
               }
            );
            f.setSize(200, 200);
            f.setContentPane(new XorTest());
            f.setVisible(true);
         }
         
      }
      ------------------------------------------------------
      (Review ID: 98345)
      ======================================================================
      From: "Chris Eagle"
      To: "chamness"
      Subject: RE: (Review ID: 98345) Graphics setXorMode does not work for drawString
      Date: Sat, 27 Nov 1999 22:13:33 -0800

      Thanks for the quick reply. I had not seen the Bug to which you refer.
      After further play with my code, it appears that some of the drawing
      algorithms hit some pixels twice in which case the first hit properly xors
      the pixel off, but the second hit xors it back on, leaving an artifact. For
      example, I noticed that when xor'ing a rectangle over the normal version of
      itself using drawRect, I was getting a leftover pixel in each corner. This
      is what I expect if the rectangle algorithm works like the following:

      g.setXORMode(Color.white);
      g.drawLine(x1, y1, x2, y1); //top edge, first occurrence of x2, y1 turns it
      off
      g.drawLine(x2, y1, x2, y2); //right edge, second occurrence of x2, y1 turns
      it back on
                                  //leaving an artifact
      g.drawLine(x2, y2, x1, y2);
      g.drawLine(x1, y2, x1, y1);

      When I replace the call to drawRect with four calls to drawLine in which I
      ensure that I hit each corner only once, I get proper erasure of the
      original rectangle.

      I suspect a similar phenomena is occurring within drawString

      Thanks again for your time.

      Chris

      ======================================================================

            flar Jim Graham
            gstone Greg Stone
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: