How can I add buttons on a picture? - java

I am currently creating a GUI for a game. I am currently loading an image using JLabel onto my JPanel, I was wondering whether it would be possible to add buttons on various parts of the image e.g. (5,7) and (12,12).

If you wish to have JButtons appear over your image, a better approach would be to override the paintComponent of the JPanel and use drawImage to draw the image similar to this example . This will allow you to add components to the container.
Absolute positioning(null layout) is generally frowned upon for setting component locations, however. This DragLayout should be a better substitute taking care of component sizing.
DragLayout was designed to replace a null layout. It will respect the location of a component. By default it will use the preferred size of the component to determines its size. Finally, it will automatically calculate the preferred size of the Container.

Related

Java Swings Auto-Resize Pictures

I'm doing this project using Swing.
To add a more welcoming feel to the UI, I'm also adding a few Photoshopped images as the background.Here's where the problem begins...
I want the images to automatically resize themselves once the size of the window is increased or decreased, how can I make this happen ?
One way is to override the paintComponent(...) method of a JPanel to paint the image using the drawImage(....) method.
Another option is use a JLabel with an Icon as the background for the frame. Then you can use the Stretch Icon which will automatically scale based on the space available to the label. This is the most flexible solution since the StretchIcon can be used on any component that supports icons.
You can also check out the Background Panel which allows you to display an image. You can display the image at its actual size, scaled or tiled.

Adding JPanel to Canvas

Since JPanel and Canvas are both same-level components, the solution would probably be some sort of a 'hack'. This question says that you won't be able to add the lightweight component to the heavyweight canvas (I want JPanel transparent).
If this isn't posible, then would putting a transparent Component work? Also, is it feasible to add Swing components to the Component (it just has to work, even if it's bad). And how would I go about actually putting it over the canvas (since they are both same-level components)?
Note: I would never do something like this in a real app, I just need it in this case
One possiblity is to add the JPanel to whatever container the Canvas is on, then setting the color of the JPanel to have an alpha of 0. This should add it over the old one, without blocking out the Canvas. Is this what you want?
EDIT: Thinking about it, the JPanel's default color is transparent... You should just be able to add the JPanel the Canvas's parent, and lay it over it

Resizing a JPanel with resampling to preserve content

Give that I have written a JPanel with many different components on it, is there a way to apply an overall "dilate" ability on the panel so that everything in it stretches proportionally when I resize my window?
That is, if I manually resize my window to be 1/4 the size, everything in the panel should also shrink by 1/4 so the new panel is just a dilation of the first. Given that I have not designed the individual components inside to do this (there are many) is there any easy way to make the panel behave this way?
UPDATE: In order to be more clear on the solution I need, I will describe the panel contents:
The panel is a "game" of sorts, with a single null-layout and dozens of ImageIcons flying around the screen at any time. The ImageIcons are preloaded PNG files, which already have a permanent size. Of course, I could manually resize each ImageIcon and reposition them relative to window size, but that would involve recoding many components.
There are no buttons or text to worry about, so what I'm really looking for is some kind of "postprocessed" resize where the panel simply shrinks whatever's rendered by some porportion (think of resizing an image in Photoshop).
One option is of course to give up swing all together and use some 3rd party widget component library which draws itself using any Graphics. Then you can either draw the widgets on the image and resize the image, or, better yet, apply a transform to the graphics object you pass to the library.
If you do want to stick with swing there is the SwingUtilities.paintComponent method, which you could use to paint the Panel onto a BufferedImage which you could then resize. (I've used this myself to do some nice transitions between "views" in a game.)
The problem is of course that you somehow need to translate the user input accordingly. I have no solution for this right now, but the above perhaps helps you in some way.
You can try to override paintChildren() method of the panel and scale graphics to achieve desired visible size.
You could try J(X)Layer, see http://www.pbjar.org/blogs/jxlayer/jxlayer40/
Using layout managers instead of absolute positioning of the widgets will give you this behaviour. See the oracle tutorials: Using Layout Managers.
Do you really want fonts to resize on resize events? I don't know a layout manager which will do that for you.

Custom layout Java Swing

I want to make board(map) like this in Java.
Each small hexagon is image.
Suppose I have two Java classes. Canvas(big hexagon) and Hexagon. First is entire board from which I generate randomly all small hexagons. Both classes derived from JPanel. Now I have GridLayout. How can I arrange layout like this?
Why do you need the small hexagon panels?
I would rather just define List (list of Hexagons) each with desired position and just override paintComponent() method of main JPanel. You can use this http://java-sl.com/shapes.html to create hexagon shapes.
To track mouse click you can use contains() method of Shape.
you can
1) common way
by painting to the JPanel/JComponent by override paintComponent() (I asumed that there are Image/BufferedImage/Icon/ImageIcon)
2) by place Icon/ImageIcon to the JLabel
you have look at JLayer (since Java7) or use (former) JXLayer
OverlayLayout or customizations for OverlayLayout by #camickr
The point of layout manages is to make it possible for the layout to auto-adjust when components change their size or the window does.
It looks like your hexagons will always be the same size, so you really don't need a layout manager, and positioning the hexagons absolutely should be fine.

JPanel size by inner components

Is it possible to tell JPanel to set its size to fit all components that it contains? Something like pack() for JFrame.
edit: The trick with preferredSize didn't help. I've got JSplitPane, where in one part there is GridBagLayout with many labels (see screenshot) and labels overlap each other.
screenshot http://foto.darth.cz/pictures/screen.png
After looking at the source code for pack(), I came up with:
panel.setPreferredSize(panel.getPreferredSize());
This forces the panel to recalculate its preferred size based on the preferred sizes of its subcomponenents.
You may or may not have to call validate() afterward; in my tiny example, it seemed to make no difference, but the Javadoc says:
The validate method is used to cause a container to lay out its subcomponents again. It should be invoked when this container's subcomponents are modified (added to or removed from the container, or layout-related information changed) after the container has been displayed.
So I guess it depends on why you're having to repack your JPanel.
By default Containers have a preferred size that matches the preferred layout size given by the container. So literally all you have to do is:
panel.setSize(panel.getPreferredSize());
Presumably you are doing something odd with the parent to stop the parent's layout manager doing the equivalent of this.
maybe you can do something like that by removing from your panel
setResizable(false);
I would try:
panel.revalidate();
panel.repaint();
This will not necessarily set the panel to its preferred size, that is more dependent on what the layout manager decides to use.
This is useful in cases where you have added/removed components from a panel that is currently displayed and visible.
Update:
Based on your screenshot I can say the following:
1) Consider programatically changing the divider location.
2) Consider programatically resizing the window itself horizontally since it seems to be a little tight to show both sides of the split pane.
Or both.
You can set the divider location by doing
splitPane.setDividerLocation(newSize);
Keep in mind that there are two overloaded methods for this, one taking a float one taking an int. The float does a percentage of the size while the int is the size in pixels. The size is for the left hand panel (or top panel for that orientation).
I would consider possibly changing the divider location based on the preferred width of the panels.
The javax.swing mysteries reveal themselves only gradually, and only to those who are prepared to offer many libations (particularly torn out clumps of hair, hours burning the midnight oil, etc.) to the gods of Swing.
However, for this case in point I would suggest the following as a sort of Swiss army knife which usually does what you think the framework should do anyway:
myJPanel.getTopLevelAncestor().validate()
As the sacred text says, "Validates this container and all of its subcomponents." (Container.validate). NB getTopLevelAncestor() is a JComponent method.
Can't remember how JSplitPane fits into this: try it and you'll probably find that it validates both components (right and left, top and bottom), but I would be surprised if changing the divider doesn't do this for you anyway.
I had a similar issue using Netbeans GUI Builder. My inner panels were getting weird sizes; I was trying to adjust the minimum and preferred sizes manually, which was a frustrating exercise.
The problem was solved when I reset all the minimum and preferred sizes back to default (In Netbeans GUI Builder: right click JPanel component -> Properties -> preferredSize -> Reset to Default). When there is no imposed size, the jpanel takes the size of the inner component.
Note: GridBaLayout was used in my case
JSplitPanes are a bit fussy when it comes to its children's sizes, have a look at the Java tutorial. Are you using the GridBagLayout correctly? Looks like it's not setting the right JPanel's minimum size properly.
Here's an example of a panel which:
Resizes with it's parent.
Sets the width to the width of the parent.
Sets the height according to sum of the height of all of it's children.
JPanel panel = JPanel(new GridBagLayout())
panel.setMaximumSize(new Dimension(panel.getMaximumSize().width, panel.getPreferredSize().height))
panel.validate()
panel.repaint()

Categories