gpt4 book ai didi

java - JPanel 内的 JPanel 过多(使用 GridBagLayout)

转载 作者:行者123 更新时间:2023-12-02 14:52:34 26 4
gpt4 key购买 nike

所以基本上,如果我将 JPanel 放入使用 GridBagLayoutJPanel 中,并使用 setPreferredSize 限制大小>,最终它达到了无法容纳所有这些的地步,并且它表现出附图所示的行为:

enter image description here

我正在制作一个accordion 。这只是一个展示我遇到的问题的例子。 Accordion 的每个部分都可以单独打开,它们的大小是任意的,可以即时添加。获取所有单独面板的高度并将它们与总高度进行比较很容易,但是当添加太多面板时,它会表现出我所展示的处理行为。这也会缩小高度,因此更难以确定嘎吱声何时发生。我必须缓存高度并以某种方式预先计算添加的新部件的高度。最终目标是在添加新面板且没有足够的空间时删除旧面板。

是否有一种简单的方法可以确定某个物体在不受约束的情况下的高度,或者可能是一种受支持的方法来检测何时发生这种处理(这样我可以在再次绘制之前快速将其变薄)?使 GridBagLayout 表现得像其他一些布局并溢出到 hammerspace 的选项而不是压缩也可以。

代码示例:

import java.awt.*;
import java.awt.event.*;
import javaisms.out;
import javax.swing.*;

public class FoldDrag extends JLayeredPane {
public TexturedPanel backingPanel = new TexturedPanel(new GridBagLayout(),"data/gui/grayerbricks.png");
static JPanel windowbase=new JPanel();
static JPanel restrictedpanel=new JPanel(new GridBagLayout());

GridBagConstraints gbc = new GridBagConstraints();

public FoldDrag() {
JButton addpan = new JButton("Add things");
windowbase.add(addpan);
windowbase.add(restrictedpanel);
restrictedpanel.setBackground(Color.red);
restrictedpanel.setPreferredSize(new Dimension(200,200));
gbc.weighty=1;
gbc.weightx=1;
gbc.gridx=0;
gbc.gridy=0;
gbc.gridheight=1;
gbc.gridwidth=1;
gbc.fill=GridBagConstraints.HORIZONTAL;
addpan.addActionListener(new ActionListener() {
int number=0;
@Override
public void actionPerformed(ActionEvent e)
{
number++;
gbc.gridy=number;
JPanel tmppanel = new JPanel();
tmppanel.setPreferredSize(new Dimension(100,30));
if(number%3==0)
tmppanel.setBackground(Color.blue);
if(number%3==1)
tmppanel.setBackground(Color.yellow);
if(number%3==2)
tmppanel.setBackground(Color.green);
restrictedpanel.add(tmppanel,gbc);
restrictedpanel.validate();
}
});
windowbase.setVisible(true);
}
private static void createAndShowUI() {
JFrame frame = new JFrame("DragLabelOnLayeredPane");
frame.getContentPane().add(windowbase);
FoldDrag thedrag=new FoldDrag();
windowbase.add(thedrag);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(300,300));
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
out.active=true;
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}

编辑:看来我没有很好地描述我的 Accordion 版本。这是 link .

最佳答案

您有特殊的要求,通过使用它的布局管理器可以更好地满足您的要求。这使您能够控制布局的各个方面,而无需诉诸黑客或“变通方法”,这些方法永远不会完全起作用或产生奇怪的副作用

Accordion Layout

public class AccordionLayout implements LayoutManager {

// This "could" be controlled by constraints, but that would assume
// that more then one component could be expanded at a time
private Component expanded;

public void setExpanded(Component expanded) {
this.expanded = expanded;
}

public Component getExpanded() {
return expanded;
}

@Override
public void addLayoutComponent(String name, Component comp) {
}

@Override
public void removeLayoutComponent(Component comp) {
}

@Override
public Dimension preferredLayoutSize(Container parent) {
Dimension size = minimumLayoutSize(parent);
if (expanded != null) {
size.height -= expanded.getMinimumSize().height;
size.height += expanded.getPreferredSize().height;
}

return size;
}

@Override
public Dimension minimumLayoutSize(Container parent) {
int height = 0;
int width = 0;
for (Component comp : parent.getComponents()) {
width = Math.max(width, comp.getPreferredSize().width);
height += comp.getMinimumSize().height;
}
return new Dimension(width, height);
}

@Override
public void layoutContainer(Container parent) {

Insets insets = parent.getInsets();
int availableHeight = parent.getHeight() - (insets.top + insets.bottom);
int x = insets.left;
int y = insets.top;

int maxSize = 0;
Dimension minSize = minimumLayoutSize(parent);
if (expanded != null) {
minSize.height -= expanded.getMinimumSize().height;
// Try an honour the preferred size the expanded component...
maxSize = Math.max(expanded.getPreferredSize().height, availableHeight - minSize.height);
}

int width = parent.getWidth() - (insets.left + insets.right);
for (Component comp : parent.getComponents()) {
if (expanded != comp) {
comp.setSize(width, comp.getMinimumSize().height);
} else {
comp.setSize(width, maxSize);
}
comp.setLocation(x, y);
y += comp.getHeight();
}

}

}

以及可运行的示例...

这已经到了极致,创建一个专门的组件来充当每个“折叠”,但这只是从外部降低了 API 的复杂性,这意味着,您只需要考虑标题和内容,然后让API 的其余部分自行处理

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class Test {

public static void main(String[] args) {
new Test();
}

public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

private AccordionLayout layout;

public TestPane() {
layout = new AccordionLayout();
setLayout(layout);

AccordionListener listener = new AccordionListener() {
@Override
public void accordionSelected(Component comp) {
layout.setExpanded(comp);
revalidate();
repaint();
}
};

Color colors[] = {Color.RED, Color.BLUE, Color.CYAN, Color.GREEN, Color.MAGENTA, Color.ORANGE, Color.PINK, Color.YELLOW};
String titles[] = {"Red", "Blue", "Cyan", "Green", "Magenta", "Orange", "Pink", "Yellow"};
for (int index = 0; index < colors.length; index++) {
AccordionPanel panel = new AccordionPanel(titles[index], new ContentPane(colors[index]));
panel.setAccordionListener(listener);
add(panel);
}
}

}

public class ContentPane extends JPanel {

public ContentPane(Color background) {
setBackground(background);
}

@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}

}

public interface AccordionListener {

public void accordionSelected(Component comp);

}

public class AccordionPanel extends JPanel {

private JLabel title;
private JPanel header;
private Component content;

private AccordionListener accordionListener;

public AccordionPanel() {
setLayout(new BorderLayout());

title = new JLabel("Title");

header = new JPanel(new FlowLayout(FlowLayout.LEADING));
header.setBackground(Color.GRAY);
header.setBorder(new LineBorder(Color.BLACK));
header.add(title);
add(header, BorderLayout.NORTH);

header.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
AccordionListener listener = getAccordionListener();
if (listener != null) {
listener.accordionSelected(AccordionPanel.this);
}
}
});
}

public AccordionPanel(String title) {
this();
setTitle(title);
}

public AccordionPanel(String title, Component content) {
this(title);
setContentPane(content);
}

public void setAccordionListener(AccordionListener accordionListener) {
this.accordionListener = accordionListener;
}

public AccordionListener getAccordionListener() {
return accordionListener;
}

public void setTitle(String text) {
title.setText(text);
revalidate();
}

public String getText() {
return title.getText();
}

public void setContentPane(Component content) {
if (this.content != null) {
remove(this.content);
}

this.content = content;
if (this.content != null) {
add(this.content);
}
revalidate();
}

public Component getContent() {
return content;
}

@Override
public Dimension getMinimumSize() {
return header.getPreferredSize();
}

@Override
public Dimension getPreferredSize() {
Dimension size = content != null ? content.getPreferredSize() : super.getPreferredSize();
Dimension min = getMinimumSize();
size.width = Math.max(min.width, size.width);
size.height += min.height;
return size;
}

}

public class AccordionLayout implements LayoutManager {

// This "could" be controled by constraints, but that would assume
// that more then one component could be expanded at a time
private Component expanded;

public void setExpanded(Component expanded) {
this.expanded = expanded;
}

public Component getExpanded() {
return expanded;
}

@Override
public void addLayoutComponent(String name, Component comp) {
}

@Override
public void removeLayoutComponent(Component comp) {
}

@Override
public Dimension preferredLayoutSize(Container parent) {
Dimension size = minimumLayoutSize(parent);
if (expanded != null) {
size.height -= expanded.getMinimumSize().height;
size.height += expanded.getPreferredSize().height;
}

return size;
}

@Override
public Dimension minimumLayoutSize(Container parent) {
int height = 0;
int width = 0;
for (Component comp : parent.getComponents()) {
width = Math.max(width, comp.getPreferredSize().width);
height += comp.getMinimumSize().height;
}
return new Dimension(width, height);
}

@Override
public void layoutContainer(Container parent) {

Insets insets = parent.getInsets();
int availableHeight = parent.getHeight() - (insets.top + insets.bottom);
int x = insets.left;
int y = insets.top;

int maxSize = 0;
Dimension minSize = minimumLayoutSize(parent);
if (expanded != null) {
minSize.height -= expanded.getMinimumSize().height;
// Try an honour the preferred size the expanded component...
maxSize = Math.max(expanded.getPreferredSize().height, availableHeight - minSize.height);
}

int width = parent.getWidth() - (insets.left + insets.right);
for (Component comp : parent.getComponents()) {
if (expanded != comp) {
comp.setSize(width, comp.getMinimumSize().height);
} else {
comp.setSize(width, maxSize);
}
comp.setLocation(x, y);
y += comp.getHeight();
}

}

}

}

现在,如果您真的准备好迎接挑战,您可以使用 a animated layout proxy并做类似的事情...

Animated Layout

关于java - JPanel 内的 JPanel 过多(使用 GridBagLayout),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32368190/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com