3

I have created a JPanel and add it on a JFrame. JPanel has TitledBorder, but when I use the method translate(), e.g.,

g2.translate(getWidth() / 2, getHeight() / 2);

the whole component, including the border is translated. The effect is presented on Figure 1. Figure 1

The desired result is depicted on the figure below. Figure 2

Code is pasted below.

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

class GPanel extends JPanel {
    private void doDrawing(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(getWidth() / 2, getHeight() / 2);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        doDrawing(g);
    }
}

class Main extends JFrame {
    public Main() {
    }

    public static void main(String[] args) {
        Main ex = new Main();
        ex.setSize(new Dimension(400, 400));
        GPanel panel = new GPanel();
        panel.setBorder(BorderFactory.createTitledBorder("Title"));
        ex.add(panel);
        ex.setLocationRelativeTo(null);
        ex.setVisible(true);
    }
}
Andrej
  • 3,719
  • 11
  • 44
  • 73
  • Could this be caused from the layout manager being used on the JFrame? If you create a JPanel with the titled border to hold GPanel, does the error persist? – DCON May 26 '17 at 08:30

3 Answers3

3

You have invoked setBorder() on an instance of GPanel and then modified the graphics context's transform in the latter's implementation of paintComponent(). The border doesn't know about this, so the result shown is entirely expected. Instead, follow the parent JComponent implementation advice for setBorder(): "put the component in a JPanel and set the border on the JPanel." A related example is shown here.

In the variation below,

  • The enclosing bPanel now has the Border, and the enclosed gPanel can safely manipulate the graphics context.

  • Before translate(), the red dot is centered on the origin; after translate(), the blue dot is centered on the origin, but the origin has moved.

  • Don't use setPreferredSize() when you really mean to override getPreferredSize().

  • Don't extend JFrame needlessly.

image

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;

class GTest {

    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GPanel gPanel = new GPanel();
        JPanel bPanel = new JPanel();
        bPanel.setBorder(BorderFactory.createTitledBorder("Title"));
        bPanel.add(gPanel);
        f.add(bPanel);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class GPanel extends JPanel {

        private static final int N = 16;

        private void doDrawing(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setPaint(Color.red);
            g.fillOval(-N, -N, 2 * N, 2 * N);
            g2.translate(getWidth() / 2, getHeight() / 2);
            g2.setPaint(Color.blue);
            g.fillOval(-N, -N, 2 * N, 2 * N);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            doDrawing(g);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(256, 256);
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
3

You might need to restore the move made by executing g2.translate(x, y); with g2.translate(-x, -y);:

Graphics2D g2 = (Graphics2D) g;
double x = getWidth() / 2d;
double y = getHeight() / 2d;
g2.translate(x, y);
g2.setPaint(Color.BLUE);
g2.fill(s);
g2.translate(-x, -y);

Another common way is to use a new Graphics object which is a copy of GPanel's Graphics object:

Graphics2D g2 = (Graphics2D) g.create();
g2.translate(getWidth() / 2, getHeight() / 2);
g2.setPaint(Color.BLUE);
g2.fill(s);
g2.dispose();

Main2.java

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

class GPanel extends JPanel {
  private final Rectangle s = new Rectangle(0, 0, 16, 16);
  private void doDrawing(Graphics g) {
    g.setColor(Color.RED);
    g.fillRect(s.x, s.y, s.width, s.height);

//     Graphics2D g2 = (Graphics2D) g;
//     double x = getWidth() / 2d;
//     double y = getHeight() / 2d;
//     g2.translate(x, y);
//     g2.setPaint(Color.BLUE);
//     g2.fill(s);
//     g2.translate(-x, -y);

    Graphics2D g2 = (Graphics2D) g.create();
    g2.translate(getWidth() / 2, getHeight() / 2);
    g2.setPaint(Color.BLUE);
    g2.fill(s);
    g2.dispose();
  }

  @Override
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    doDrawing(g);
  }
}

public class Main2 extends JFrame {
  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      GPanel panel = new GPanel();
      panel.setBorder(BorderFactory.createTitledBorder("Title"));
      JFrame ex = new JFrame();
      ex.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      ex.getContentPane().add(panel);
      ex.setSize(400, 400);
      ex.setLocationRelativeTo(null);
      ex.setVisible(true);
    });
  }
}
aterai
  • 9,658
  • 4
  • 35
  • 44
0

try this code:

private void doDrawing(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(0, 0);
    }
Piotr Rogowski
  • 3,642
  • 19
  • 24
  • Thanks, but this code doesn't solve the problem. I need to translate origin into the `(width / 2, height /2)' – Andrej May 26 '17 at 09:27