0

Here's the application I'm building https://github.com/chrisbramm/LastFM-History-Graph.

Below is part of the controller class in src/lastfmhistoryclasses. When OutputGUIView is created it creates three components, a JPanel graphPanel, this is added to a JScrollPane graphScrollPanel and another JPanel autocompletePanel. These are then all added to the JFrame OutputGUIView. The listeners below then change the preferred size of graphPanel and the first time you press a button the UI updates to show that graphPanel has increased in size and the scrollbars of graphScrollPanel have change.

However now, if you press another button, the preferred size changes but the UI doesn't update, it will do it if you change the window dimensions by lets say maximising it.

class Zoom2000 implements ActionListener{
    public void actionPerformed(ActionEvent e){
        outputGUIView.graphPanel.setPreferredSize(new Dimension(screenWidth, 2000));
        outputGUIView.graphScrollPanel.updateUI();

    }
}
class ZoomDefault implements ActionListener{
    public void actionPerformed(ActionEvent e){
        outputGUIView.graphPanel.setPreferredSize(new Dimension(screenWidth, screenHeight));
        outputGUIView.graphScrollPanel.updateUI();


    }
}
class Zoom6000 implements ActionListener{
    public void actionPerformed(ActionEvent e){
        outputGUIView.graphPanel.setPreferredSize(new  Dimension(screenWidth, 6000));
        outputGUIView.graphScrollPanel.updateUI();

    }
}

I've tried different things as well such as invalidate/validate/revalidate (and repaint) on various components all the while graphPanel just sits there and only repaints when you change the window dimensions.

Any ideas what I'm doing wrong?

EDIT UPDATE: Here is the GraphPanel class:

package lastfmhistoryguis;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.*;

import de.umass.lastfm.*;
import lastfmhistoryclasses.*;

SuppressWarnings("serial")
public class GraphPanel extends JPanel {

private LastFMHistory graphData;
private int graphHeight;
private int graphWidth;
private int zoom;
private final int PAD = 20;

public GraphPanel(LastFMHistory model, int zoom){
    this.graphData = model;
    if (zoom != 1){
        this.zoom = zoom;
    }else{
        this.zoom = 1;
        System.out.println("getHeight() returning:" + getHeight());
    }
    System.out.println("Width" + getWidth() + "Height" + getHeight());

}

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
     System.out.println("Drawing");
    Graphics2D graph = (Graphics2D) g;

    if (graphData == null) {
        System.err.println("No data found");
    } else {
        System.out.println("paintComponent Width" + getWidth() + "Height" + getHeight());
        graphWidth = getWidth() - 5 * PAD;
        //graphHeight = getHeight() - 2 * PAD;
        graphHeight = 6000 - 2* PAD;
        System.out.println(graphWidth + ", " + graphHeight);

        int x0 = graphWidth + PAD;
        graph.draw(new Rectangle2D.Double(PAD, PAD, graphWidth, graphHeight));
        double xInc = (double) (graphWidth) / (graphData.dayMax);
        double secondHeight = (double) (graphHeight) / 86400;

        for (int i = 0; i <= 86400; i++) {
            if (i % 3600 == 0) {
                graph.draw(new Line2D.Double(x0, (i * secondHeight) + PAD,
                        x0 + 10, (i * secondHeight) + PAD));
                String hour = Integer.toString(i / 3600);
                graph.drawString(hour, x0 + 15,
                        (int) ((i * secondHeight) + PAD));
            }
        }

        for (Track t : graphData.history) {
            if (t.getPlayedWhen() != null) {

                Color color = t.getColour();

                int duration = t.getDuration();
                int day = Math.abs(t.getDay());
                double dayOrigin = x0 - ((day + 1) * xInc);
                double timeOrigin = t.getGraphHeight() * secondHeight + PAD;
                double trackHeight = duration * secondHeight;
                graph.setColor(color);
                // System.out.println("PLOTTING TRACK, " + day + ", " +
                // dayOrigin + ", " + t.getGraphHeight() + ", " + timeOrigin
                // + ", " + trackHeight);
                // graph.draw(new Rectangle2D.Double(dayOrigin, timeOrigin,
                // xInc, trackHeight));
                graph.fillRect((int) dayOrigin, (int) timeOrigin,
                        (int) xInc, (int) trackHeight);
            }

        }

        for (int i = 0; i < graphData.dayMax;){
            graph.draw(new Line2D.Double(x0 - i * xInc, PAD, x0 - i * xInc, graphHeight + PAD));
            i = i + 7;
        }

    }
}
public void zoom(int zoom){
    this.zoom = zoom;
    repaint();
}

}

It creates a Graphics2D object onto which a large outlining rectangle is drawn and each track rectangle is then drawn onto somewhere on this Graphics2D graph object. Now I've removed the use of setPreferredSize as recommended here but now I have the problem of when I manually set graphHeight in GraphPanel to a height say 6000, graphScrollPanel doesn't realise that graphPanel that it, containing is actually bigger as all graphHeight is doing is drawing a rectangle that is ~6000px high. So in this case should I be using setPreferredSize or is there another way to set the size of a Graphics2D object?

Community
  • 1
  • 1
Chris
  • 1,435
  • 2
  • 11
  • 9
  • I bit more information wouldn't go astray. Things like the component layout (what's layout in what) and the layout managers in use – MadProgrammer Jul 24 '12 at 23:40
  • sounds like you have a slightly incorrect expectation to the prefSize property: it's a sizing hint to be used by the LayoutManager - not a means to auto-magically trigger an application property like "zoom" :-) Or in other words: implement your custom panel to support a zoom property and notify the view hierarchy that it needs to be re-layouted – kleopatra Jul 25 '12 at 10:00

1 Answers1

5

Don't call updateUI this is related to the UI Look and Feel API and has little to do with repainting.

What layout managers have you tried/are using?

Calls to invalidate(), repaint() should effect the parent containers layout managers and cause them to re-layout the components accordingly, but you need to remember, layout managers only use the min/max/pref size information as guides.

My best guest from your example is that you should be trying to call either

outputGUIView.graphPanel.invalidate();
outputGUIView.graphPanel.repaint();

and/or

outputGUIView.invalidate();
outputGUIView.repaint();

Calling invalidate in the scroll pane is probably not going to achieve a lot as the viewport is responsible for layout out the contents, not the scroll pane.

If you're really desperate you could try

outputGUIView.graphScrollPanel.getViewport().invalidate();
outputGUIView.graphScrollPanel.getViewport().repaint();
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366