Currently I am trying to add an icon which should be as big as the button (added to GridBagLayout
). I want to scale the icon to the size of the button, but my button shows its size as 0.
I tried to print out the size of the button (after creating it and also after adding it). It always gives me 0 and therefore an ArgumentException
(width (0) and height (0) must be non-zero).
Also I want to dynamically size the font as big as the button is (no implementation yet but also doesn't work because the buttons doesn't give its size).
Does anybody has a solution for dynamic resizing using LayoutManager
? Maybe there is a way to get the cell size and then scale the image to the cell size?
Here is my test code:
import javax.swing.*;
import java.awt.*;
public class TestResize extends JFrame {
private Container cp;
private JPanel levelPane;
private GridBagConstraints gbc = new GridBagConstraints();
public TestResize() {
super();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 200;
int frameHeight = 200;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setTitle("temp");
setResizable(false);
cp = getContentPane();
cp.setLayout(new BorderLayout());
createLevelMenu();
setVisible(true);
} // end of public temp
public static void main(String[] args) {
new TestResize();
} // end of main
public void createLevelMenu(){
if (levelPane == null){
levelPane = new JPanel(new GridBagLayout());
gbc.fill = GridBagConstraints.NONE;
JButton back = new JButton();
back.setOpaque(false);
back.setBackground(null);
back.setBorder(null);
addObject(0,0,1,1,GridBagConstraints.FIRST_LINE_START,back);
Image img = (new ImageIcon("Content/Graphics/UI/returnIcon.png")).getImage().getScaledInstance(back.getWidth(),back.getHeight(),Image.SCALE_SMOOTH);
back.setIcon(new ImageIcon(img));
JPanel menu = new JPanel(new BorderLayout());
menu.setBackground(Color.RED);
JLabel l = new JLabel("Demo");
l.setFont(l.getFont().deriveFont(30)); //Font Size as big as Possible (adjust
l.setHorizontalAlignment(SwingConstants.CENTER);
l.setVerticalAlignment(SwingConstants.CENTER);
menu.add(l,BorderLayout.CENTER);
gbc.fill = GridBagConstraints.BOTH;
addObject(2,2,1,4,GridBagConstraints.CENTER,menu);
JButton info = new JButton("Info");
addObject(3,3,1.25f,1.25f,GridBagConstraints.LAST_LINE_END,info);
cp.add(levelPane, BorderLayout.CENTER);
}
}
public void addObject(int gridX,int gridY, double weightX,double weightY,int anchor, JComponent comp){
gbc.gridx =gridX;
gbc.gridy = gridY;
gbc.weightx = weightX;
gbc.weighty = weightY;
gbc.anchor = anchor;
levelPane.add(comp,gbc);
}
}
yes this would be for a lot of reasons
getTopLevelAncestor()
is not displayable ! (witch in this case yourTestResize
object)so the concept was wrong from the start and even if you didn't made the border null the size will be equal to the border insets (and for all of the api border's that is tight !!! even for a plain "hi" with font size of 5!!!).
so your best bet in situation like this (but not yours as i mentioned) is to call
for this to work(in your situation ) you have to make the starting size of the image your self then the when setting the icon to the button the ui will give it an extra size.
@AndrewThompson pointed to a great examples in that answer he wrote and @trashgod good examples too all of them are spectacular!! +1 for that.
Edit
you have to understand that when using layout managers every thing size is relative to it's parent !! for your example the icon button --> the level panel (witch it's the content pane) --> the root pane
JLayeredPane
object --> the root pane it self --> finally the frame !! every thing is resized based on the parent size but if in case the parent size 0,0 then don't expect the sub-component's to get more than that !! and just keep in mind thatGridBagLayout
is the most complex of all the layout and it can behave in a strange way .and the usage of
is to get the real size 'ON-THE-SCREEN' the return might not be even related to the
getSize()
or the others (maximum ,minimum) .so the best way to get the icon the same as the size you have to make a
ComponentListener
this is a bad idea because if the L & F have a default insets for button the you will give it more than what it would take!! and with the
ComponentListener
you will make it have an animation of resizing !!here is refactored version of your class ,
ComponentAdapter
is an implementation of the interfaceComponentListener
that implements every method in empty way , am using it so i don't have to implement all other methods too .the
widthPadding
and theheightPadding
is the total of the L & F insets for button's , i can't help you with that you have to do it by your self, this is a L & F dependent . but for a hack you can change thecomponentResized
method to this (i discourage this)sadly i don't think so , but @AndrewThompson answer seems easy to learn , i would study that if i want to start reading about
GlyphVector
it's neat and it's simple , and happy coding .