问题
I have added a button to a frame and controlling it's text and/or minimum size with timer.
I noticed, that button does grow sometimes, and sometimes does not.
If in null
layout, then it ignores both text and minimum width changing.
If in FlowLayout
layout, then it grows if text changing, but ignores minimum width changing.
How make it grow in latter case? If minimum width changes, then why doesn't layout manager reshapes button? How to force it to reshape?
Note: code below is SSCCE, i.e. it is for investigation purposes.
public class Try_ButtonAutoresize_01 {
private static final Logger log = LoggerFactory.getLogger(Try_ButtonAutoresize_01.class);
private static final String text = "Very Long Text For Appear On Button ";
private static int position = 7;
public static void main(String[] args) {
final JButton button = new JButton(text.substring(0, position));
button.setBounds(10, 10, 100, 50);
JFrame frame = new JFrame();
//frame.setLayout(null);
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100,100);
frame.setSize(640, 480);
frame.setVisible(true);
new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
/*
button.setText(button.getText() + text.charAt(position));
position++;
if( position >= text.length() ) {
position=0;
}
*/
button.setMinimumSize(new Dimension((int)button.getMinimumSize().getWidth()+10, (int)button.getMinimumSize().getHeight()));
log.info("Minimum width is now = {}", button.getMinimumSize().getWidth());
}
}).start();
}
}
UPDATE
It does not work with preferred size too. Invalidation also does not help.
public class Try_ButtonAutoresize_01 {
private static final Logger log = LoggerFactory.getLogger(Try_ButtonAutoresize_01.class);
private static final String text = "Very Long Text For Appear On Button ";
private static int position = 7;
public static void main(String[] args) {
final JButton button = new JButton(text.substring(0, position));
button.setBounds(10, 10, 100, 50);
final JFrame frame = new JFrame();
//frame.setLayout(null);
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100,100);
frame.setSize(640, 480);
frame.setVisible(true);
new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
/*
button.setText(button.getText() + text.charAt(position));
position++;
if( position >= text.length() ) {
position=0;
}
*/
//button.setMinimumSize(new Dimension((int)button.getMinimumSize().getWidth()+10, (int)button.getMinimumSize().getHeight()));
button.setPreferredSize(new Dimension((int)button.getPreferredSize().getWidth()+10, (int)button.getPreferredSize().getHeight()));
//frame.invalidate();
//button.invalidate();
log.info("Minimum width is now = {}", button.getMinimumSize().getWidth());
log.info("Preferred width is now = {}", button.getPreferredSize().getWidth());
}
}).start();
}
}
UPDATE 2
The answer reuires 2 conditions:
1) use setPreferredSize()
as @Sage suggested, and
2) call revalidate()
(what I saw in setText()
source code).
The final working code follows:
public class Try_ButtonAutoresize_02 {
private static final Logger log = LoggerFactory.getLogger(Try_ButtonAutoresize_02.class);
public static void main(String[] args) {
final JButton button = new JButton("short");
final JFrame frame = new JFrame();
frame.setLayout(new FlowLayout(FlowLayout.LEFT));
frame.add(button);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100,100);
frame.setSize(640, 480);
frame.setVisible(true);
new Timer(1000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//button.setMinimumSize(new Dimension((int)button.getMinimumSize().getWidth()+10, (int)button.getMinimumSize().getHeight()));
button.setPreferredSize(new Dimension((int)button.getPreferredSize().getWidth()+10, (int)button.getPreferredSize().getHeight()));
button.revalidate();
log.info("Preferred width is now = {}", button.getPreferredSize().getWidth());
}
}).start();
}
}
回答1:
- Don't go with first approach:
null layout(AbsoluteLayout)
even if someone threaten you to life death. Second approach with
FlowLayout
: It is a LayoutManager as you might already know. However, this layout manager respects preferred size of a component. So giving size hints by setting bounds:setBounds(x, y, width, height)
won't have effect. Usebutton.setPreferredSize(Dimension)
to have a quick result. But again you should actually extend the class and override thegetPreferredSize(Dimension)
and othergetXXXSize(Dimension)
method to adjust with the content size.JButton button = new JButton("Press Me"){ @Override public Dimension getPreferredSize() { Dimension size = new Dimension(); size.width = ???; // give some thinking about it size.height = ???; // give some thinking about it return size; } };
As @mKobel has pointed out below, which i have forgotten to address: do not set size to
JFrame
. It reduce the chance for layout managers to layout properly. CallJFrame.pack()
beforeJFrame.setVisible(true)
instead.
Have a look in this tutorial page for details:
- How to use FlowLayout
- Solving Common Layout Problems
来源:https://stackoverflow.com/questions/20336914/how-does-jbutton-control-its-size