- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我最近一直在开发一个 Swing 应用程序。我遇到了布局管理器的问题。我似乎无法弄清楚如何使布局中的组件一直增长到其父容器的边缘。让我解释一下。
假设我在一行中有 8 个按钮。根据窗口大小将确定它们是否占用所有空间。 GBL 我找到了中心,所以左右都有空间。 BoxLayout 通常将空格放在右侧。这可能是由于它们的 anchor 或对齐方式。
我认为问题在于,当所有组件都具有相同设置时,布局会尝试为每个组件提供相同的空间。因此,那一点额外的空间不能平均分配给他们遗漏的每个组件。
我想知道是否有解决此问题的方法。就像空间太小一样,我希望有一种方法可以让最后一个组件吃掉它,或者在组件之间尽可能地划分它。
这是显示问题的示例代码。请注意,当您调整面板大小时,您会获得额外的空间。
public class LeftoverExample {
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
LeftoverExample.createGUI();
}
});
}
public static void createGUI(){
JFrame jF = new JFrame();
jF.setSize(new Dimension(1333,500));
jF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create ContentPane
JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
GridBagLayout gBL = new GridBagLayout();
gBL.columnWidths = new int[]{0};
gBL.rowHeights = new int[]{50, 50, 50 , 50};
contentPane.setLayout(gBL);
//Initial Constraints
GridBagConstraints gBC = new GridBagConstraints();
gBC.fill = GridBagConstraints.BOTH;
gBC.gridx = 0;
gBC.gridy = 0;
gBC.weightx = 1;
gBC.weighty = 0;
gBC.insets = new Insets(10, 0, 10, 0);
//Add Examples to ContentPane
contentPane.add(LeftoverExample.createGBL(false), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createGBL(true), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createBoxLayout(false), gBC);
gBC.gridy++;
contentPane.add(LeftoverExample.createBoxLayout(true), gBC);
//Final
jF.setContentPane(contentPane);
jF.setVisible(true);
}
private static JComponent createGBL(boolean addButtons){
//GBL Example
JLabel gBLJLabel = new JLabel("GridBagLayout");
gBLJLabel.setVerticalAlignment(SwingConstants.CENTER);
gBLJLabel.setLayout(new BoxLayout(gBLJLabel, BoxLayout.X_AXIS));
gBLJLabel.setBackground(Color.CYAN);
gBLJLabel.setOpaque(true);
gBLJLabel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
GridBagLayout gBL = new GridBagLayout();
gBL.columnWidths = new int[]{0};
gBL.rowHeights = new int[]{50};
gBLJLabel.setLayout(gBL);
//Initial Constraints
GridBagConstraints gBC = new GridBagConstraints();
gBC.fill = GridBagConstraints.BOTH;
gBC.gridx = 0;
gBC.gridy = 0;
gBC.weightx = 1;
gBC.weighty = 0;
gBC.insets = new Insets(0, 0, 0, 0);
//Add to GBL Panel
if(addButtons){
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
LeftoverExample.addButtons(gBLJLabel, gBC);
}
return gBLJLabel;
}
private static JComponent createBoxLayout(boolean addButtons){
//BoxLayout Example
JLabel boxLayoutJL = new JLabel("BOX_LAYOUT");
boxLayoutJL.setVerticalAlignment(SwingConstants.CENTER);
boxLayoutJL.setLayout(new BoxLayout(boxLayoutJL, BoxLayout.X_AXIS));
boxLayoutJL.setBackground(Color.GREEN);
boxLayoutJL.setOpaque(true);
boxLayoutJL.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
//Add to BoxLayout Panel
if(addButtons){
LeftoverExample.addButtons(boxLayoutJL);
LeftoverExample.addButtons(boxLayoutJL);
LeftoverExample.addButtons(boxLayoutJL);
}
return boxLayoutJL;
}
private static JButton createButton(Color c){
JButton jB = new JButton();
jB.setBackground(c);
jB.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
return jB;
}
private static void addButtons(JComponent jC, GridBagConstraints gBC){
//Create Buttons
Color[] colorA = {Color.RED, Color.BLUE, Color.BLACK, Color.GREEN};
for(Color c : colorA){
jC.add(LeftoverExample.createButton(c), gBC);
gBC.gridx++;
}
}
private static void addButtons(JComponent jC){
//Create Buttons
Color[] colorA = {Color.BLUE, Color.BLACK, Color.GREEN, Color.RED};
for(Color c : colorA){
jC.add(LeftoverExample.createButton(c));
}
}
}
查看每个西侧和东侧如何留有一些空间被父级(在本例中为 JLabel)占据但按钮没有。我希望按钮也能占据那个空间。
图片展示示例:
最佳答案
问题是由 Swing 使用整数值而不是 double 值引起的。
考虑到这个事实,容器宽度除以 Component
的数量的余数 r(在您的例子中是 JButton
objects) 它包含的对象可用于将第一个 r Component
对象的大小增加 1 以进行补偿。显然,这意味着第一个 r Component
对象将比其他 Components
大 +1,但这应该不会引起注意。
为了更新 Component
对象的宽度,我们需要访问那里的容器(例如 JPanel
)和所有 Component
我们希望更新的对象。在我的示例中,我将为此目的使用一个 List
。
这里有一个方法可以相应地调整 Component
对象的大小。
private static void fixComponentWidths(Component container,
List<? extends Component> componentList, int componentHeight) {
if (!componentList.isEmpty()) { // Avoid possible division by zero
// get the desired component width for the container using integer division
int baseComponentWidth = container.getWidth() / componentList.size();
// find the remainder
int remainder = container.getWidth() % componentList.size();
// update all the components
for (int i = 0; i < componentList.size(); i++) {
// the component width will be the base width plus 1 iff i < remainder
int componentWidth = baseComponentWidth;
if (i < remainder) {
componentWidth++;
}
// update the maximum size
componentList.get(i).setMaximumSize(new Dimension(componentWidth, componentHeight));
}
// be sure to revalidate otherwise it may not work
container.revalidate();
}
}
为了使其在调整大小时起作用,必须为我们的容器实现一个ComponentListener
。这可以是 JFrame
或只是一个 JPanel
(按照我的示例)。请注意,只有 componentResized(ComponentEvent)
方法需要为此任务实现。
buttonContainer.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) { // just implementing this
fixComponentWidths(buttonContainer, buttons, BUTTON_HEIGHT);
// where buttonContainer is a JPanel,
// buttons is a List of JButtons
// BUTTON_HEIGHT, well the height of the button!
}
@Override
public void componentMoved(ComponentEvent ce) { // not needed
}
@Override
public void componentShown(ComponentEvent ce) { // not needed
}
@Override
public void componentHidden(ComponentEvent ce) { // not needed
}
});
这就是所有需要的。但为了完整起见,这里有一个基于作者问题的小示例,后面是 JPanel
的子类,它使用 BoxLayout
可用于为 解决此行为>BoxLayout.X_AXIS
和 BoxLayout.Y_AXIS
。
完整示例
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class FillExample extends JFrame {
private static final int FRAMEL_DEFAULT_WIDTH = 700;
private static final int FRAME_DEFAULT_HEIGHT = 400;
private static final int BUTTON_HEIGHT = Integer.MAX_VALUE;
private final List<JButton> buttons;
public FillExample() {
buttons = new ArrayList<>();
}
public void createAndShow() {
setTitle("Fill Example");
setSize(FRAMEL_DEFAULT_WIDTH, FRAME_DEFAULT_HEIGHT);
final JPanel buttonContainer = new JPanel();
buttonContainer.setLayout(new BoxLayout(buttonContainer, BoxLayout.X_AXIS));
for (int i = 0; i < 3; i++) {
addButtons(buttonContainer);
}
getContentPane().add(buttonContainer);
buttonContainer.addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
fixComponentWidths(buttonContainer, buttons, BUTTON_HEIGHT);
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
});
setVisible(true);
}
private static void fixComponentWidths(Component container, List<? extends Component> componentList, int componentHeight) {
if (!componentList.isEmpty()) {
int baseComponentWidth = container.getWidth() / componentList.size();
int remainder = container.getWidth() % componentList.size();
for (int i = 0; i < componentList.size(); i++) {
int componentWidth = baseComponentWidth;
if (i < remainder) {
componentWidth++;
}
componentList.get(i).setMaximumSize(new Dimension(componentWidth, componentHeight));
}
container.revalidate();
}
}
private void addButtons(JComponent component) {
Color[] colorA = {Color.RED, Color.BLUE, Color.BLACK, Color.GREEN};
for (Color c : colorA) {
JButton button = createButton(c);
buttons.add(button);
component.add(button);
}
}
private static JButton createButton(Color color) {
JButton button = new JButton();
button.setBackground(color);
button.setMaximumSize(new Dimension(Integer.MAX_VALUE, BUTTON_HEIGHT));
return button;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new FillExample().createAndShow();
}
});
}
}
填充框布局面板
这个小类可用于快速解决 BoxLayout.X_AXIS
和 BoxLayout.Y_AXIS
的间距问题。请注意,创建 BoxLayout
和 LayoutManager
的类不能更改。
add(Component comp)
和
add(Component comp, int index)
将
Component
对象添加到面板。请注意,并不是所有的 add
方法都会被覆盖,应谨慎使用该类。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
public class FillBoxLayoutPanel extends JPanel {
public static final int X_AXIS = BoxLayout.X_AXIS;
public static final int Y_AXIS = BoxLayout.Y_AXIS;
private final List<Component> components;
private final int direction;
private boolean layoutSet;
public FillBoxLayoutPanel(int direction) {
components = new ArrayList<>();
this.direction = direction;
setLayout(new BoxLayout(this, direction));
layoutSet = true;
addComponentListener(new ComponentListener() {
@Override
public void componentResized(ComponentEvent ce) {
adjustComponents();
}
@Override
public void componentMoved(ComponentEvent ce) {
}
@Override
public void componentShown(ComponentEvent ce) {
}
@Override
public void componentHidden(ComponentEvent ce) {
}
});
}
@Override
public void setLayout(LayoutManager mgr) {
if (layoutSet) {
throw new UnsupportedOperationException("FillPanel's layout manager cannot be changed.");
} else {
super.setLayout(mgr);
}
}
@Override
public Component add(Component comp) {
comp = super.add(comp);
components.add(comp);
return comp;
}
@Override
public Component add(Component comp, int i) {
comp = super.add(comp, i);
components.add(i, comp);
return comp;
}
private void adjustComponents() {
if (!components.isEmpty()) {
int size = direction == X_AXIS ? getWidth() : getHeight();
int baseComponentSize = size / components.size();
int remainder = size % components.size();
for (int i = 0; i < components.size(); i++) {
int componentSize = baseComponentSize;
if (i < remainder) {
componentSize++;
}
Dimension dimension;
if (direction == X_AXIS) {
dimension = new Dimension(componentSize, components.get(i).getHeight());
} else {
dimension = new Dimension(components.get(i).getWidth(), componentSize);
}
components.get(i).setMaximumSize(dimension);
}
revalidate();
}
}
}
关于java - 如何填充有关布局管理器的剩余空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46863055/
运行 Tomcat 失败并出现 java.lang.OutOfMemoryError - 与缺少 PermGen 空间相关的错误。 我最近将 Tomcat 更改为以自己的用户(而非 root)运行。
我们有一个表,其中包含数百万行,其中包含 PostGIS 几何图形。我们要执行的查询是:落在边界几何内的最新条目是什么?这个查询的问题是我们经常会有大量的项目匹配边界框(半径大约为 5 公里),然后
我有一个Elasticsearch设置,它将允许用户搜索通配符作为索引。 array:3 [ "index" => "users" "type" => "user" "body" => arra
我创建了一个表,其中每行包含两个按钮,并且两个按钮连接在一起,我想将两个按钮分开。我用过 不起作用,css 也是,这是他们的另一种方式。 我有另一个问题,因为我不想在表格边框内显示操作按钮,而是在靠近
我试图在 jQuery Mobile 中的两个按钮之间留出空白。现实中的布局是这样的: Button 1 Button 2 (Hidden w/ display: none)
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
您好,我对图表应用程序还很陌生。现在我为我的应用程序创建了条形图。当我运行 create bar chart as separate project 时,输出如下所示。 然后当我将条形图与我的应用程序
我在使用 H2 和 GeoDB(内存中,junit)时遇到问题。 另外,使用 Hibernate 5(每个包的最新版本,包括 hibernate-spatial)和 Spring 4。 通过 id 实
我想画一张澳大利亚的 map ,并将每个城市表示为一个点。 然后突出显示人口众多(> 1M)的城市 library(sp) library(maps) data(canada.cities) head
关闭。这个问题是opinion-based .它目前不接受答案。 想改进这个问题?更新问题,以便 editing this post 提供事实和引用来回答它. 6年前关闭。 Improve this
如何保持.txt文件中存在的空格?在.txt文件中,它表示: text :text text1 :text1 text23 :text2 text345 :text3 如果我写这段
以下哪个键最大? 选项 1:16 个数字 [0,9] 选项 2:30 个元音 选项 3:字母表中的 16 个字母 选项 4:32 位 有人可以帮助我,告诉我哪一个是正确的答案以及我们如何计算它吗?我知
在 Unity 3d 中使用 Azure 空间 anchor 来实现在 iOS 和 Android 上部署的室内和室外增强现实体验是否有益? 最佳答案 是的,对于 Azure Spatial Anch
我有一个绝对定位的圆形图像。图像只需占据屏幕宽度的 17%,并且距离顶部 5 个像素。 问题是,当我调整图像大小以占据屏幕宽度的 17% 时,它会这样做,但同时容器会变长。图像本身不会拉伸(stret
我在 Ubuntu 14.04 上使用 Cassandra。从文档中,我可以看到运行命令: nodetool snapshot 创建我的 key 空间的快照。 命令的输出是: nodetool sn
Heroku引入了“私有(private)空间”,是否可以将现有应用迁移到私有(private)空间? https://blog.heroku.com/archives/2015/9/10/herok
是否允许在语义记录中使用非绑定(bind)空格 或其他 HTML 编码字符?我遇到的问题是 ; 字符被软件视为记录的结尾。 例如:假设我有一份婚姻记录,其中包含 2 个结婚者的姓氏、结婚年份以及结
我正在研究“智能 parking ”项目,偶然发现了包含我们真正需要的YouTube视频。我们已经实现了第一部分,即从视频源进行实时透视变换,下一步是将其定义为一组矩形 我基本上需要知道他是如何做到的
我有两个类:Engine 和 Trainset(多个单元),这两个类共享其 ID 空间,其中包含名称和系列 id=- . 这是我的Engine类(它是抽象的,因为有引擎的子类型(DieselEngin
如果有人能帮助我,那就太好了。 我正在尝试使用Java的Split命令,使用空格分割字符串,但问题是,字符串可能没有空格,这意味着它将只是一个简单的顺序(而不是“输入2”将是“退出”) Scanner
我是一名优秀的程序员,十分优秀!