让 JButtons 在 JFrame 中始终居中高度?
Making JButtons Always Centered Height-Wise in the JFrame?
到目前为止,我已经编写了以下程序来帮助我熟悉 Java Swing GUI 编程。有没有一种方法可以修改我的代码,使两个 JButton
控件(addButton
和 subtractButton
)始终在 JFrame
中居中高度,因为 window 调整大小了吗?
public class GUITesting extends JFrame implements ActionListener {
private static final int INITIAL_WIDTH = 400;
private static final int INITIAL_HEIGHT = 300;
JButton addButton, subtractButton;
public GUITesting() {
setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
setLocation(200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("0");
addButton = new JButton("Add");
addButton.addActionListener(this);
add(addButton); // Adding Button to the Window Frame Creation
subtractButton = new JButton("Subtract");
subtractButton.addActionListener(this);
setLayout(null);
addButton.setSize(INITIAL_WIDTH / 4, INITIAL_HEIGHT / 6);
subtractButton.setSize(INITIAL_WIDTH / 4, INITIAL_HEIGHT / 6);
addButton.setLocation(INITIAL_WIDTH / 6, INITIAL_HEIGHT / 6);
subtractButton.setLocation(7 * INITIAL_WIDTH / 12, INITIAL_HEIGHT / 6);
add(addButton);
add(subtractButton);
addComponentListener(new Resizer());
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
setTitle("Mouse clicked at (" + x + "," + y + ")");
}
});
}
public void actionPerformed(ActionEvent event) {
int value = Integer.parseInt(getTitle());
if (event.getActionCommand().equals("Add")) {
value = value + 1;
}
else {
value = value - 1;
}
}
private class Resizer extends ComponentAdapter {
// Override Some of the Abstract Methods from ComponentAdapter
public void componentResized(ComponentEvent event) {
int width = getWidth();
int height = getHeight();
addButton.setSize(width / 4, height / 6);
subtractButton.setSize(width / 4, height / 6);
addButton.setLocation(width / 6, height / 6);
subtractButton.setLocation(7 * width / 12, height / 6);
}
}
public static void main(String[] args) {
GUITesting window = new GUITesting();
window.setVisible(true);
}
}
无需做任何特殊操作,您只需使用 GridBagLayout
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
add(new JButton("Add"));
add(new JButton("Subtract"));
}
}
}
有关详细信息,请参阅 Laying Out Components Within a Container and How to Use GridBagLayout
如果您希望按钮大小相同,您可以使用复合布局,同时利用 GridBagLayout
和 GridLayout
,例如...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
JPanel contentPane = new JPanel(new GridLayout(1, 2));
contentPane.add(new JButton("Add"));
contentPane.add(new JButton("Subtract"));
add(contentPane);
}
}
}
但是,如果您想做一些非常时髦的事情,您可以构建自己的布局管理器,例如 ButtonLayout
,例如...
这基本上与第二个示例相同,但提供了一些额外的对齐选项,这些选项比通过 GridBagLayout
更容易实现
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new ButtonLayout(ButtonLayout.Alignment.HORIZONTAL, ButtonLayout.Anchor.CENTER));
add(new JButton("Add"));
add(new JButton("Subtract"));
}
}
public class ButtonLayout implements LayoutManager2 {
public enum Alignment {
VERTICAL, HORIZONTAL
}
public enum Anchor {
LEADING, CENTER, TRAILING
}
private Alignment alignment;
private Anchor anchor;
private int padding;
private Dimension virtualBounds;
public ButtonLayout() {
this(Alignment.HORIZONTAL, Anchor.TRAILING, 0);
}
public ButtonLayout(Alignment alignment, Anchor anchor) {
this(alignment, anchor, 0);
}
public ButtonLayout(Alignment alignment, Anchor anchor, int padding) {
this.alignment = alignment;
this.padding = padding;
this.anchor = anchor;
}
public Alignment getAlignment() {
return alignment;
}
public Anchor getAnchor() {
return anchor;
}
protected int getPadding() {
return padding;
}
protected int getTotalPadding(Container parent) {
int padding = getPadding();
return (padding * parent.getComponentCount()) - padding;
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public void invalidateLayout(Container target) {
virtualBounds = null;
}
protected Dimension virtualLayout(Container parent) {
if (virtualBounds != null) {
return virtualBounds;
}
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension preferredSize = component.getPreferredSize();
maxHeight = Math.max(maxHeight, preferredSize.height);
maxWidth = Math.max(maxWidth, preferredSize.width);
}
int padding = 0;
int width = 0;
int height = 0;
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL:
width = (maxWidth * componentCount) + getTotalPadding(parent);
height = maxHeight;
break;
case VERTICAL:
width = maxWidth;
height = (maxHeight * componentCount) + getTotalPadding(parent);
break;
}
virtualBounds = new Dimension(width, height);
return virtualBounds;
}
@Override
public Dimension maximumLayoutSize(Container parent) {
return virtualLayout(parent);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return virtualLayout(parent);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return virtualLayout(parent);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void layoutContainer(Container parent) {
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension preferredSize = component.getPreferredSize();
maxHeight = Math.max(maxHeight, preferredSize.height);
maxWidth = Math.max(maxWidth, preferredSize.width);
}
Dimension defaultSize = new Dimension(maxWidth, maxHeight);
Point point = offsetForAnchor(parent, defaultSize);
int xDelta = 0;
int yDelta = 0;
switch (alignment) {
case HORIZONTAL:
xDelta = getPadding() + defaultSize.width;
break;
case VERTICAL:
yDelta = getPadding() + defaultSize.height;
break;
}
for (Component component : parent.getComponents()) {
component.setSize(defaultSize);
component.setLocation(point);
point = new Point(point.x + xDelta, point.y + yDelta);
}
}
protected Point offsetForAnchor(Container parent, Dimension defaultSize) {
switch (anchor) {
case LEADING:
return leadingOffSet(parent, defaultSize);
case TRAILING:
return trailingOffSet(parent, defaultSize);
case CENTER:
return centerOffSet(parent, defaultSize);
}
return new Point(0, 0);
}
protected Point leadingOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
switch (alignment) {
case HORIZONTAL:
point.x = padding;
point.y = (parent.getHeight() - defaultSize.height) / 2;
break;
case VERTICAL:
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = padding;
break;
}
return point;
}
protected Point trailingOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL:
int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
point.x = parent.getWidth() - totalWidth;
point.y = (parent.getHeight() - defaultSize.height) / 2;
break;
case VERTICAL:
int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = parent.getHeight() - totalHeight;
break;
}
return point;
}
protected Point centerOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL: {
int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - totalWidth) / 2;
point.y = (parent.getHeight() - defaultSize.height) / 2;
}
break;
case VERTICAL: {
int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = (parent.getHeight() - totalHeight) / 2;
}
break;
}
return point;
}
}
}
到目前为止,我已经编写了以下程序来帮助我熟悉 Java Swing GUI 编程。有没有一种方法可以修改我的代码,使两个 JButton
控件(addButton
和 subtractButton
)始终在 JFrame
中居中高度,因为 window 调整大小了吗?
public class GUITesting extends JFrame implements ActionListener {
private static final int INITIAL_WIDTH = 400;
private static final int INITIAL_HEIGHT = 300;
JButton addButton, subtractButton;
public GUITesting() {
setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
setLocation(200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("0");
addButton = new JButton("Add");
addButton.addActionListener(this);
add(addButton); // Adding Button to the Window Frame Creation
subtractButton = new JButton("Subtract");
subtractButton.addActionListener(this);
setLayout(null);
addButton.setSize(INITIAL_WIDTH / 4, INITIAL_HEIGHT / 6);
subtractButton.setSize(INITIAL_WIDTH / 4, INITIAL_HEIGHT / 6);
addButton.setLocation(INITIAL_WIDTH / 6, INITIAL_HEIGHT / 6);
subtractButton.setLocation(7 * INITIAL_WIDTH / 12, INITIAL_HEIGHT / 6);
add(addButton);
add(subtractButton);
addComponentListener(new Resizer());
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
setTitle("Mouse clicked at (" + x + "," + y + ")");
}
});
}
public void actionPerformed(ActionEvent event) {
int value = Integer.parseInt(getTitle());
if (event.getActionCommand().equals("Add")) {
value = value + 1;
}
else {
value = value - 1;
}
}
private class Resizer extends ComponentAdapter {
// Override Some of the Abstract Methods from ComponentAdapter
public void componentResized(ComponentEvent event) {
int width = getWidth();
int height = getHeight();
addButton.setSize(width / 4, height / 6);
subtractButton.setSize(width / 4, height / 6);
addButton.setLocation(width / 6, height / 6);
subtractButton.setLocation(7 * width / 12, height / 6);
}
}
public static void main(String[] args) {
GUITesting window = new GUITesting();
window.setVisible(true);
}
}
无需做任何特殊操作,您只需使用 GridBagLayout
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
add(new JButton("Add"));
add(new JButton("Subtract"));
}
}
}
有关详细信息,请参阅 Laying Out Components Within a Container and How to Use GridBagLayout
如果您希望按钮大小相同,您可以使用复合布局,同时利用 GridBagLayout
和 GridLayout
,例如...
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
JPanel contentPane = new JPanel(new GridLayout(1, 2));
contentPane.add(new JButton("Add"));
contentPane.add(new JButton("Subtract"));
add(contentPane);
}
}
}
但是,如果您想做一些非常时髦的事情,您可以构建自己的布局管理器,例如 ButtonLayout
,例如...
这基本上与第二个示例相同,但提供了一些额外的对齐选项,这些选项比通过 GridBagLayout
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new ButtonLayout(ButtonLayout.Alignment.HORIZONTAL, ButtonLayout.Anchor.CENTER));
add(new JButton("Add"));
add(new JButton("Subtract"));
}
}
public class ButtonLayout implements LayoutManager2 {
public enum Alignment {
VERTICAL, HORIZONTAL
}
public enum Anchor {
LEADING, CENTER, TRAILING
}
private Alignment alignment;
private Anchor anchor;
private int padding;
private Dimension virtualBounds;
public ButtonLayout() {
this(Alignment.HORIZONTAL, Anchor.TRAILING, 0);
}
public ButtonLayout(Alignment alignment, Anchor anchor) {
this(alignment, anchor, 0);
}
public ButtonLayout(Alignment alignment, Anchor anchor, int padding) {
this.alignment = alignment;
this.padding = padding;
this.anchor = anchor;
}
public Alignment getAlignment() {
return alignment;
}
public Anchor getAnchor() {
return anchor;
}
protected int getPadding() {
return padding;
}
protected int getTotalPadding(Container parent) {
int padding = getPadding();
return (padding * parent.getComponentCount()) - padding;
}
@Override
public void addLayoutComponent(Component comp, Object constraints) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public void invalidateLayout(Container target) {
virtualBounds = null;
}
protected Dimension virtualLayout(Container parent) {
if (virtualBounds != null) {
return virtualBounds;
}
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension preferredSize = component.getPreferredSize();
maxHeight = Math.max(maxHeight, preferredSize.height);
maxWidth = Math.max(maxWidth, preferredSize.width);
}
int padding = 0;
int width = 0;
int height = 0;
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL:
width = (maxWidth * componentCount) + getTotalPadding(parent);
height = maxHeight;
break;
case VERTICAL:
width = maxWidth;
height = (maxHeight * componentCount) + getTotalPadding(parent);
break;
}
virtualBounds = new Dimension(width, height);
return virtualBounds;
}
@Override
public Dimension maximumLayoutSize(Container parent) {
return virtualLayout(parent);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return virtualLayout(parent);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return virtualLayout(parent);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void layoutContainer(Container parent) {
int maxWidth = 0;
int maxHeight = 0;
for (Component component : parent.getComponents()) {
Dimension preferredSize = component.getPreferredSize();
maxHeight = Math.max(maxHeight, preferredSize.height);
maxWidth = Math.max(maxWidth, preferredSize.width);
}
Dimension defaultSize = new Dimension(maxWidth, maxHeight);
Point point = offsetForAnchor(parent, defaultSize);
int xDelta = 0;
int yDelta = 0;
switch (alignment) {
case HORIZONTAL:
xDelta = getPadding() + defaultSize.width;
break;
case VERTICAL:
yDelta = getPadding() + defaultSize.height;
break;
}
for (Component component : parent.getComponents()) {
component.setSize(defaultSize);
component.setLocation(point);
point = new Point(point.x + xDelta, point.y + yDelta);
}
}
protected Point offsetForAnchor(Container parent, Dimension defaultSize) {
switch (anchor) {
case LEADING:
return leadingOffSet(parent, defaultSize);
case TRAILING:
return trailingOffSet(parent, defaultSize);
case CENTER:
return centerOffSet(parent, defaultSize);
}
return new Point(0, 0);
}
protected Point leadingOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
switch (alignment) {
case HORIZONTAL:
point.x = padding;
point.y = (parent.getHeight() - defaultSize.height) / 2;
break;
case VERTICAL:
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = padding;
break;
}
return point;
}
protected Point trailingOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL:
int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
point.x = parent.getWidth() - totalWidth;
point.y = (parent.getHeight() - defaultSize.height) / 2;
break;
case VERTICAL:
int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = parent.getHeight() - totalHeight;
break;
}
return point;
}
protected Point centerOffSet(Container parent, Dimension defaultSize) {
Point point = new Point(0, 0);
int componentCount = parent.getComponentCount();
switch (alignment) {
case HORIZONTAL: {
int totalWidth = (defaultSize.width * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - totalWidth) / 2;
point.y = (parent.getHeight() - defaultSize.height) / 2;
}
break;
case VERTICAL: {
int totalHeight = (defaultSize.height * componentCount) + getTotalPadding(parent);
point.x = (parent.getWidth() - defaultSize.width) / 2;
point.y = (parent.getHeight() - totalHeight) / 2;
}
break;
}
return point;
}
}
}