2

I have a swing component where the ideal size of the component will vary based on the content that is is currently being displayed (which happens in this case to be an image).

I'd like this preferred size to change when the content is changed, and also allow the layout to be changed (for example, if the component is being used inside a JScrollPane then the scroll extents would change to fit the size of the component).

What is the canonical way to do this in Swing ?

mKorbel
  • 109,525
  • 20
  • 134
  • 319
mikera
  • 105,238
  • 25
  • 256
  • 415

2 Answers2

5

Suggestions:

  • Use a class extends JPanel (or JComponent),
  • give it a getPreferredSize() method override where you return a Dimension with the parameters that you desire.
  • For instance if the diameter will be based on a BufferedImage, you could have something like:

getPreferredSize example:

public Dimension getPreferredSize() {
  if (myBuffImg != null) {
    return new Dimension(myBuffImg.getWidth(), myBuffImg.getHeight());
  } 
  // default return value
  return super.getPreferredSize();      
}

Edit
Regarding your comment:

how would you handle the case of the component's content image changing though? is it just a a case of triggering a re-layout in the surrounding container?

You'd give this class a setImage(Image image) method of course, and you could repaint() this panel from within this method. The method I suppose could call revalidate() on this JPanel's ancestor causing this component to be re-layed out, but I'm not too crazy about methods in this class having side effects on its ancestor and think that likely it will be better for the code calling the setImage(...) method to suggest that the container revalidate itself.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • thanks this makes sense - how would you handle the case of the component's content image changing though? is it just a a case of triggering a re-layout in the surrounding container? – mikera Sep 23 '12 at 04:27
3

A lot will come down to your individual needs. When dealing with "image panes", I typically will call setPreferredSize and invalidate, repaint when the image changes.

Changing the layout should automatically trigger a invalidate, reprint request anyway.

But I agree with Hovercraft, you'll want to do this from your own customs panel.

Another approach would be to use something like CardLayout to handle changing between different content layout outs, rather the cleaning up a single panel and re-adding comports to it

I'd also have a look at the Scrollable

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • actually, ... no: you will never want to use setXXSize - but as you agree with @Eels at the end ... :-) – kleopatra Sep 23 '12 at 12:24
  • @mKorbel: In a comment to Rempelos [here](http://stackoverflow.com/a/7229662/230513), I contrast `setPreferredSize()` with `Scrollable`; both have [well-known caveats](http://stackoverflow.com/q/7229226/230513). – trashgod Sep 23 '12 at 12:31
  • @kleopatra for reasons of education, why not? I would surmise that it could be overridden by the user (calling setPrefSize), but I have a (personal) thing about overriding setters a getters in this manner, it's a complete pain in the arse to debug (call set & having get return something different). I agree in this context, it's probably the right thing to do (and I do just this myself). I also hate people that insist on using setXxxx because they can't figure out layouts. But I'm obviously missing something – MadProgrammer Sep 23 '12 at 12:34
  • hmm ... don't understand what you are asking, assuming you read the qa referenced by @trashgod Plus, can't see any debug (which is more the exception than the norm == writing unit tests :) related issues with getters/setters – kleopatra Sep 23 '12 at 16:04