我有一個JFrame
在CardLayout
包含一組JPanels
。每個JPanel
具有不同的尺寸,我希望JFrame
適應當前顯示的尺寸JPanel
(而不是JPanel
以適應JFrame
的尺寸)。如何設置JFrame大小以適應CardLayout顯示的JPanel?
我該如何做到這一點?
我有一個JFrame
在CardLayout
包含一組JPanels
。每個JPanel
具有不同的尺寸,我希望JFrame
適應當前顯示的尺寸JPanel
(而不是JPanel
以適應JFrame
的尺寸)。如何設置JFrame大小以適應CardLayout顯示的JPanel?
我該如何做到這一點?
一般是:如果你有一個佈局問題,總是用適當的佈局管理解決它。 從不調整組件的大小提示以達到您的目標。
在這種情況下,調整CardLayout特別容易。默認情況下,它會將其prefSize計算爲所有卡片的prefSizes的最大值。簡單地繼承並實現返回當前的可見卡片的prefSize(加插圖):
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的例子),其主要方法乾淨逐漸縮小:
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);
}
我覺得你可能有錯誤的佈局管理器來做你想做的事(暫時擱置一會兒,我不確定你是否想做你說的你想做的事)。
我還沒有找到有關我懷疑的文檔,即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.
我認爲這是合理的行爲,因爲那將是非常惱人的用戶具有面板尺寸跳圍繞面板運行。
如果這真的是你想要的行爲,那麼我認爲你想要一個不同的佈局管理器。而且,由於這是一般用戶界面的不尋常行爲,因此您可能找不到標準的用戶來執行此特定「功能」,因此您可能需要編寫自己的「功能」。
這是SSCCE。
1)對於大小的連續增減,你應該尋找一些動畫API。
或
2)如果沒有與輸出到GUI任何後臺任務,可以在施膠JFrame
暫停。在這種情況下,您可以使用包含Runnable
線程的Thread#sleep(int)
延遲增加/減少。
3)在EDT期間直接使用Thread#sleep(int)
的通知(不適用於OP)將凍結GUI,直到延遲結束。
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();
}
});
}
}
-1是否過度使用setPrefSize:一般規則(正如您所知道的:-)通過使用適當的LayoutManager來解決大小問題。如果你沒有找到你想要的東西,那麼編寫/調整一個LayoutManager ... – kleopatra
Try this code this may help you.
protected void paintComponent(Graphics g) {
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0, 0, getSize().width-1, getSize().height-1);
System.out.println("width is "+getSize().width+"height is "+getSize().height);
super.paintComponent(g);
}
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawOval(0, 0, getSize().width-1, getSize().height-1);
}
Shape shape;
public boolean contains(int x, int y) {
if (shape == null || !shape.getBounds().equals(getBounds())) {
shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
}
return shape.contains(x, y);
}}
*「我希望JFrame適應當前顯示的JPanel的大小」*僅僅因爲顯示的內容發生變化而讓用戶改變幀大小會感到很奇怪。 –
當內部面板不匹配時,修復大小JFrame非常難看。我嘗試過這個。 – JVerstry
我不確定這會工作,但你可以試試這個:'frame.setSize(panel。getPreferredSize());' –