6

I have the following:

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

This is what it looks like: With bounds at 0,0
The ParametricEQView is the component with the white background filling most of the window. In this image its coordinates are (0,0) in the containing frame and everything is great. However, if I resize the window so that the ParametricEQView moves over a bit (it has a fixed size and is set to be centered in its available space), the rotated text stays relative to the (0,0) of the frame instead of the component:

Starting to move Fully off the component


Everything else draws relative to the panel, it's just the rotated text that doesn't. What am I doing wrong?

alex2410
  • 10,424
  • 3
  • 22
  • 40
MattPutnam
  • 2,619
  • 2
  • 17
  • 22

2 Answers2

1

1) For custom paintings you need to override protected void paintComponent(Graphics g) instead of public void paint(Graphics g). Read more about customPaintings.

2)Seems you have your problem, because you do something like next for creation of 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);

in that case ParametricEQView doesn't resize as you want, because JPanel use FlowLayout as default.

You need to use another LayoutManager for your panel, for example BorderLayout.

Try something like next:

JFrame frame = new JFrame();
ParametricEQView view = new ParametricEQView();
frame.add(view);

or

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

in that case your ParametricEQView panel will be painting in proper way.

alex2410
  • 10,424
  • 3
  • 22
  • 40
  • 1) You are right, he should override the `paintComponent()` methods. 2) See my answer on why the text is not correctly placed in the component. – Guillaume Dec 24 '13 at 15:46
1

When you call g2d.setTransform(atx); you override the transform currently set in the Graphics object, i.e. the translation between the panel and its parent frame. That's why the text is drawn in the frame referential, and not in the panel referential.

The correct code would be to get the current transform and modify it or directly call Graphics2D.rotate(double).

Guillaume
  • 5,359
  • 1
  • 21
  • 28