JPanel 中的 TitledBorder 在使用 translate() 方法时移动

TitledBorder in JPanel moves when translate() method is used

我创建了一个 JPanel 并将其添加到 JFrameJPanelTitledBorder,但是当我使用 translate() 方法时,例如

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

整个组件,包括边框都已翻译。效果如图 1 所示。

期望的结果如下图所示。

代码粘贴在下面。

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);
    }
}

试试这个代码:

private void doDrawing(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.translate(0, 0);
    }

您已在 GPanel 的实例上调用了 setBorder(),然后在后者的 paintComponent() 实现中修改了图形上下文的变换。边界不知道这一点,所以显示的结果完全是意料之中的。相反,请遵循 setBorder(): "put the component in a JPanel and set the border on the JPanel." A related example is shown .

的父 JComponent 实施建议

在下面的变体中,

  • 封闭的 bPanel 现在有 Border,封闭的 gPanel 可以安全地操作图形上下文。

  • translate()之前,红点以原点为中心; translate()后,蓝点以原点为中心,但原点移动了。

  • 当你真的想覆盖getPreferredSize()时,不要使用setPreferredSize()

  • 不要不必要地扩展 JFrame

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);
        }
    }
}

您可能需要恢复通过执行 g2.translate(x, y);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);

另一种常见的方法是使用新的 Graphics 对象,它是 GPanel 的 Graphics 对象的副本:

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);
    });
  }
}