-2

I have a setup that usually works, but I'm finding it a bit of a pain at the moment.

I have a JDialog (formerly a JFrame, but I've changed the UI flow recently to remove redundant JFrames) set to BorderLayout that contains three main JPanels, header, content and footer.

The header JPanel has a background image that is loading fine. However, I'm calling all manner of setMinimumSize / setPreferredSize / etc (I even tried setSize and setBounds out of desperation) and the JPanel isn't being sized correctly. The layout for that component is BoxLayout, and the children sit comfortably within it, but that shouldn't affect what I'm trying to do with the header panel itself.

The only thing that works is setting a size on the parent JDialog. But I don't want to do that / from what I've read it seems like bad design. I'd also have to maths out the potential width / height of all the children, add the margins, etc.

Advice I am not looking for: "use a different LayoutManager."

I want to understand if there's a reason for the child components not being respected.

I can provide code, but isolating a small, runnable segment is difficult given the amount of interlocked systems I'm juggling. Here is the relevant snippet to set the size of the JPanel. The image dimensions are 480 * 96.

public JPanelThemed(BufferedImage image) {
    super();
    this.backgroundImage = image;
    setAllSimilarConstraints(new Dimension(image.getWidth(), image.getHeight()));
    setOpaque(false);
}

// for use with BoxLayout as it requires explicit bounds to be set
public void setAllSimilarConstraints(Dimension dim) {
    setPreferredSize(dim);
    setMinimumSize(dim);
    setMaximumSize(dim);
}
Gorbles
  • 1,169
  • 12
  • 27
  • 3
    `I can provide code, but isolating a small, runnable segment is difficult given the amount of interlocked systems I'm juggling` - well the problem is probably somewhere in that code and we have no idea what that code might be. `I'm calling all manner of setMinimumSize / setPreferredSize / etc` - Don't. You don't need to manually invoke those methods. It is the job of the layout manager to determine the proper size and location of components on the panel. – camickr Jul 01 '15 at 15:38
  • 2
    What we want is a [minimal runnable example program](http://stackoverflow.com/help/mcve). This statement, `"I can provide code, but isolating a small, runnable segment is difficult given the amount of interlocked systems I'm juggling."` -- suggests that you would do yourself and us a favor by refactoring your code to reduce the cyclomatic complexity (which is what you're describing to a "T"). Do this, and you'll likely find the problem causing your issue above, or if not, can then post a small runnable program for us to test. – Hovercraft Full Of Eels Jul 01 '15 at 15:38
  • So, the automatic response is a close vote and telling me to provide program code for the whole program? I'm very sorry, but I don't understand this mentality that pervades SO that I've seen far too often as a lurker, nevermind as asking questions myself. We are all programmers here, I am asking for *knowledge* about `JDialog` and if people know how it handles component size. Failing that, `BorderLayout`. – Gorbles Jul 01 '15 at 15:55
  • 2
    `"So, the automatic response is a close vote and telling me to provide program code for the whole program?"` -- please don't misinterpret our comments. Where in my comment or @camickr's did anyone ask for "the whole program"? You're asking "why is my code not working" and only posting vague descriptions and small code snippets. Who can guess what you're doing wrong based on this? Who has magical eyes that can see code not shown, code that we can test. Please read the link that I provided **before** posting your next rant. Understand what a "minimal example program is", and you'll understand us – Hovercraft Full Of Eels Jul 01 '15 at 15:59
  • The code I provided is the code that isn't working. I'm not ranting at all, and it doesn't do you credit to dismiss my arguments on that basis. The code I provided is the majority of the code from a top-level container sitting in the `.getContentPane` of the `JDialog`. No other code is affecting layout dimensions. I want to get a better understanding of layout issues. Why do you not want to talk about them? The whole program is the only option because it's a substantial project. Hence, the trouble isolating it. I have no *time* to do anything else. – Gorbles Jul 01 '15 at 16:02
  • 1
    *"I have no time to do anything else."* Your time management is not our problem. – Andrew Thompson Jul 01 '15 at 16:08
  • 2
    `"I have no time to do anything else."` -- and yet you ask others to volunteer their time to help you, yet bristle when asked to put in just a little effort to help us help you. Doesn't that strike you as a bit wrong? – Hovercraft Full Of Eels Jul 01 '15 at 16:10
  • If you guys don't have time, that is fine. This site is somewhere to ask for help, nomatter the reason. I have no inclination to debate with ego over how I need to somehow put more time in to be worthy of yours. – Gorbles Jul 01 '15 at 16:13
  • Also, Eels, having trouble tagging your name on mobile Web page. Have responded to you elsewhere. Sorry for the inconvenience. – Gorbles Jul 01 '15 at 16:17
  • 1
    `No other code is affecting layout dimensions.` - so you say. But until you post the demo code we can't tell what is happening. The problem is with your code, not the layout managers. I have given you an answer, based on the limited information provided in the question. Don't manually try to set the size of a component. If you need more help, we need more code, because we don't have the information on the context of how all your code is being used. You stated it was too hard to demonstrate so how do you expect us to guess how all the code is interacting??? – camickr Jul 01 '15 at 17:06
  • So now I have a little more time, I can explain things a bit better @camickr. If I don't define dimensions, how do I ensure the whole background I'm painting is displayed? I now have the time to dig through code, but as I'm stuck at hospital til the morning I literally can't get to it. This is what I was referring to earlier. – Gorbles Jul 01 '15 at 21:14

2 Answers2

5

I would implement it a bit another way - to ensure that preferred/min/max/Size can not be changed from elsewhere:

public JPanelThemed(BufferedImage image) {
    this.backgroundImage = image;
    setOpaque(false);
}

public Dimension getPreferredSize() {
    return new Dimension(this.backgroundImage.getWidth(), this.backgroundImage.getHeight());
}
andronix
  • 124
  • 9
  • Yes, for [example](http://stackoverflow.com/a/2658663/230513), also discussed [here](http://stackoverflow.com/q/7229226/230513); once the component can respond with its preferred size, just `pack()` the enclosing `JDialog`. – trashgod Jul 01 '15 at 16:09
  • Thanks for this comment, not sure which answer I will use yet. Do you know where / how extended JComponent classes can be changed elsewhere with regards to their size? – Gorbles Jul 02 '15 at 08:26
  • I mean that if you have some kind spaghetti code you may be not aware that *you* changing it elsewhere. – andronix Jul 02 '15 at 19:32
2

If I don't define dimensions, how do I ensure the whole background I'm painting is displayed?

You could use a JLabel to display the ImageIcon. The size of the label will be the size of the image. You then set the layout manager of the label so you can add components to it.

Edit:

do you know why it's commonly-recommended to subclass JPanel when painting backgrounds in Java

When you use a JPanel the size of the panel is based on the components added to the panel and the layout manager you are using. Your custom painting code then needs to paint the image the way your want. That is you can paint the image from (0, 0), or you can center the image on the panel, you can scale the image to make it fit the pane, but the image in no way controls the size of the panel, unless you override the getPreferredSize() method of the panel to use custom code to base the size of the larger of the components or the image. So you are in full control.

When you use the JLabel approach suggested here, the size of the label is always the size of the image. Then components will be positioned based on the layout manager but can be truncated if the image is smaller than the space required by the components.

So based on your requirement that you want to make sure the entire image is displayed, I suggested the JLabel approach, since you don't need to write any custom code. I find this a simple approach when using popup non-resizable dialogs to display a background image and a few components and buttons to close the dialog.

You can also check out Background Panel which provides these common painting features in a reusable class.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • Thanks for this approach; do you know why it's commonly-recommended to subclass `JPanel` when painting backgrounds in Java, then? That's the main reason I went with my previous approach. – Gorbles Jul 02 '15 at 08:27