仿射变换似乎忽略了组件边界。

6

我有以下内容:

public class ParametricEQView extends JPanel implements PluginView {
    private static final int BAND_WIDTH = 3;
    private static final int THROW_HEIGHT = 64;

    private static final int WIDTH = 128*BAND_WIDTH + 2*MARGIN;
    private static final int HEIGHT = 2*THROW_HEIGHT + 2*MARGIN;
    private static final int MID_HEIGHT = THROW_HEIGHT + MARGIN;

    private final ParametricEQ _peq;

    public ParametricEQView(ParametricEQ peq) {
        super();
        _peq = peq;

        SwingUtils.freezeSize(this, WIDTH, HEIGHT);
        setToolTipText("Parametric Equalizer");
    }

    @Override
    public void paint(Graphics g) {
        final Graphics2D g2d = (Graphics2D) g;
        final int max = findMax();

        g.setColor(BACKGROUND);
        g.fillRect(0, 0, WIDTH, HEIGHT);

        g.setColor(DATA);
        final double scalingFactor = -((double) THROW_HEIGHT) / max;
        final double[] fineLevels = _peq.getFineLevels();
        int x = MARGIN;
        int h;
        final int[] xPoints = new int[128];
        final int[] yPoints = new int[128];
        for (int i = 0; i < 128; ++i) {
            h = (int) (fineLevels[i] * scalingFactor);
            xPoints[i] = x;
            yPoints[i] = MID_HEIGHT + h;
            x += BAND_WIDTH;
        }
        g.drawPolyline(xPoints, yPoints, 128);

        g.setColor(AXES);
        g.drawLine(MARGIN, MARGIN, MARGIN, HEIGHT-MARGIN);
        g.drawLine(MARGIN, MID_HEIGHT, WIDTH-MARGIN, MID_HEIGHT);

        g.setFont(AXIS_FONT);
        final FontMetrics metrics = g.getFontMetrics();
        int width = (int) metrics.getStringBounds(AXIS_LABEL_INPUT_MIDINUM, g).getWidth();
        g.drawString(AXIS_LABEL_INPUT_MIDINUM, WIDTH-MARGIN-width, HEIGHT-3);

        final AffineTransform atx = new AffineTransform();
        atx.setToRotation(-Math.PI/2, 0, HEIGHT);
        g2d.setTransform(atx);
        final String topLabel = "+" + max;
        width = (int) metrics.getStringBounds(topLabel, g).getWidth();
        g2d.drawString(topLabel, HEIGHT-MARGIN-width, HEIGHT+10);

        width = (int) metrics.getStringBounds(AXIS_LABEL_OUTPUT_VELOCITY, g).getWidth();
        g2d.drawString(AXIS_LABEL_OUTPUT_VELOCITY, MID_HEIGHT-(width/2), HEIGHT+10);

        g2d.drawString("-" + max, MARGIN, HEIGHT+10);
    }

    private int findMax() {
        int max = 3;
        for (int i = 0; i < 128; ++i)
            max = Math.max(max, (int) Math.ceil(Math.abs(_peq.getFineLevels()[i])));
        return max;
    }
}

这是它的外观: 边界在0,0
ParametricEQView 是白色背景填充大部分窗口的组件。在这张图片中,它在包含框架中的坐标为 (0,0),一切都很好。但是,如果我调整窗口大小,使 ParametricEQView 移动一点(它有一个固定的大小并设置居中于其可用空间中),则旋转的文本仍相对于框架的 (0,0) 而不是该组件:

开始移动 完全超出组件


其它所有内容都相对于面板绘制,只有旋转的文本不是。我做错了什么?

2个回答

1

1) 对于自定义绘画,您需要重写 protected void paintComponent(Graphics g) 而不是 public void paint(Graphics g)。了解更多关于 customPaintings 的信息。

2) 看起来您有问题,因为您在创建GUI时做了类似下面的事情:

JFrame frame = new JFrame();
JPanel p = new JPanel();
ParametricEQView view = new ParametricEQView();
view.setPreferredSize(new Dimension(200,200));
p.add(view);
frame.add(p);

在这种情况下,ParametricEQView 不会按照您的要求进行调整大小,因为默认情况下 JPanel 使用 FlowLayout
您需要为面板使用另一个 LayoutManager,例如 BorderLayout
尝试类似于下面的内容:
JFrame frame = new JFrame();
ParametricEQView view = new ParametricEQView();
frame.add(view);

或者

JPanel panel = new JPanel(new BorderLayout());
panel.add(view,BorderLayout.CENTER);
frame.add(panel);

在这种情况下,你的ParametricEQView面板将以适当的方式绘制。

  1. 你是对的,他应该重写 paintComponent() 方法。
  2. 查看我的答案,了解为什么文本没有正确放置在组件中。
- Guillaume

1
当您调用g2d.setTransform(atx);时,您将覆盖当前在Graphics对象中设置的变换,即面板与其父框架之间的平移。这就是为什么文本是以框架参考系而不是面板参考系绘制的原因。
正确的代码应该是获取当前的变换并修改它,或直接调用Graphics2D.rotate(double)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接