我有一个在CardLayout中包含一组JPanels的JFrame。每个JPanel都有不同的大小,我希望JFrame适应当前显示的JPanel的大小(而不是JPanel适应JFrame的大小)。
我如何才能做到这一点?
发布于 2011-11-27 23:40:28
一般的情况是:如果你有一个布局问题,总是用合适的LayoutManager来解决它。从不调整组件的大小提示来达到您的目标。
在这种情况下,调整CardLayout特别容易。默认情况下,它根据所有卡的prefSizes的最大值来计算其prefSize。只需进行子类化和实现即可返回当前可见卡片的prefSize (加上insets):
public static class MyCardLayout extends CardLayout {
@Override
public Dimension preferredLayoutSize(Container parent) {
Component current = findCurrentComponent(parent);
if (current != null) {
Insets insets = parent.getInsets();
Dimension pref = current.getPreferredSize();
pref.width += insets.left + insets.right;
pref.height += insets.top + insets.bottom;
return pref;
}
return super.preferredLayoutSize(parent);
}
public Component findCurrentComponent(Container parent) {
for (Component comp : parent.getComponents()) {
if (comp.isVisible()) {
return comp;
}
}
return null;
}
}使用这个(借用@mKorbel的例子),main方法干净利落地缩小:
private static void createAndShowUI() {
final CardLayout cardLayout = new MyCardLayout();
final JPanel cardHolder = new JPanel(cardLayout);
final JFrame frame = new JFrame("MultiSizedPanels");
JLabel[] labels = {
new JLabel("Small Label", SwingConstants.CENTER),
new JLabel("Medium Label", SwingConstants.CENTER),
new JLabel("Large Label", SwingConstants.CENTER)};
for (int i = 0; i < labels.length; i++) {
int padding = 50 * (i + 1);
Border lineBorder = BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.blue),
BorderFactory.createEmptyBorder(padding, padding, padding, padding));
labels[i].setBorder(lineBorder);
JPanel containerPanel = new JPanel();
containerPanel.add(labels[i]);
cardHolder.add(containerPanel, String.valueOf(i));
}
JButton nextButton = new JButton("Next");
nextButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
cardLayout.next(cardHolder);
frame.pack();
}
});
JPanel btnHolder = new JPanel();
btnHolder.add(nextButton);
frame.add(cardHolder, BorderLayout.CENTER);
frame.add(btnHolder, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}发布于 2011-11-27 00:51:36
这是SSCCE。
1)对于不断增大或减小的大小,您应该寻找一些动画API。
或
2)如果没有任何后台任务输出到图形用户界面,您可以在调整JFrame大小时暂停。在这种情况下,您可以通过使用包装到Runnable线程中的Thread#sleep(int)来延迟增加/减少。
3)注意(对于OP)在EDT期间直接使用Thread#sleep(int)将冻结图形用户界面,直到延迟结束。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.Border;
//based on HFOE http://stackoverflow.com/questions/5414177/change-size-of-jpanel-using-cardlayout/5414770#5414770
public class MultiSizedPanels {
private static void createAndShowUI() {
final CardLayout cardLayout = new CardLayout();
final JPanel cardHolder = new JPanel(cardLayout);
final JFrame frame = new JFrame("MultiSizedPanels");
JLabel[] labels = {
new JLabel("Small Label", SwingConstants.CENTER),
new JLabel("Medium Label", SwingConstants.CENTER),
new JLabel("Large Label", SwingConstants.CENTER)};
for (int i = 0; i < labels.length; i++) {
int padding = 50;
Dimension size = labels[i].getPreferredSize();
size = new Dimension(size.width + 2 * (i + 1) * padding, size.height + 2 * (i + 1) * padding);
labels[i].setPreferredSize(size);
Border lineBorder = BorderFactory.createLineBorder(Color.blue);
labels[i].setBorder(lineBorder);
JPanel containerPanel = new JPanel();
if (i == 1) {
containerPanel.setPreferredSize(new Dimension(300, 200));
containerPanel.add(labels[i], BorderLayout.CENTER);
cardHolder.add(containerPanel, String.valueOf(i));
} else if (i == 2) {
containerPanel.setPreferredSize(new Dimension(600, 400));
containerPanel.add(labels[i], BorderLayout.CENTER);
cardHolder.add(containerPanel, String.valueOf(i));
} else {
containerPanel.setPreferredSize(new Dimension(800, 600));
containerPanel.add(labels[i], BorderLayout.CENTER);
cardHolder.add(containerPanel, String.valueOf(i));
}
}
JButton nextButton = new JButton("Next");
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardLayout.next(cardHolder);
Dimension dim = new Dimension();
for (Component comp : cardHolder.getComponents()) {
if (comp.isVisible() == true) {
dim = comp.getPreferredSize();
}
}
frame.setPreferredSize(dim);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
frame.pack();
}
});
}
});
JPanel btnHolder = new JPanel();
btnHolder.add(nextButton);
frame.add(cardHolder, BorderLayout.CENTER);
frame.add(btnHolder, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}发布于 2011-11-26 20:38:11
我认为你可能对你想要做的事情使用了错误的布局管理器(暂且不说,我不确定你是否想做你想做的事情)。
我还没有找到关于我怀疑的文档,即CardLayout根据其容器的大小调整其所有子对象的大小。我确实找到了下面关于它的"layoutContainer“方法的注释:
* Each component in the <code>parent</code> container is reshaped
* to be the size of the container, minus space for surrounding
* insets, horizontal gaps, and vertical gaps.我认为这是合理的行为,因为当遍历面板时,让面板大小跳来跳去对用户来说是非常恼人的。
如果这真的是你想要的行为,那么我认为你需要一个不同的布局管理器。由于这对于一般的UI来说是不寻常的行为,你很可能找不到一个标准的UI来做这个特殊的“特性”,所以你可能不得不自己编写。
https://stackoverflow.com/questions/8277834
复制相似问题