我正在使用GridBagLayout
(3x1)来显示我正在制作的程序的登录屏幕。布局及其中的所有内容看起来都很好,以及在JFrame
装饰时的假设。无论JFrame是否全屏,一切都会完美调整。
应该是什么样的:
问题出在我frame.setUndecorated(true)
时。这似乎无缘无故地调整了一些组件的大小。
我检查了所有组件的大小,没有任何变化,只是组件的布局。
我只是想让它看起来它在全屏时的方式相同,因为此应用程序大多数时间都处于全屏状态。为什么要调整大小,我该如何预防呢?提前谢谢。
这是(简明)代码:
package main;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.Transparency;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Main {
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
frame.getContentPane().add(new MainView());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(900, 900);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
frame.setUndecorated(true); // Problem is here
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
frame.setVisible(true);
}
}
@SuppressWarnings("serial")
class MainView extends JPanel implements MouseListener {
private ScalableImage backgroundImage;
private final JPanel loginPanel;
private final GridBagConstraints spgbc = new GridBagConstraints();
private final JLabel loginLabel;
private final JTextField loginField;
private final JButton loginButton;
private final JButton adminButton;
private final GridBagConstraints gbc;
private static final double[] colweights = { 1, .5, .05 };
private static final double[] rowweights = { 1, .5, 0 };
public MainView() {
super();
gbc = new GridBagConstraints();
setOpaque(false);
loginPanel = new JPanel();
loginLabel = new JLabel("<html>   Login to Volunteer Account</html>");
loginField = new JTextField("Enter ID Here...");
loginField.setToolTipText("Enter volunteer ID");
loginField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
loginButton.doClick();
}
});
loginButton = new JButton("Enter");
adminButton = new JButton("Admin");
adminButton.setPreferredSize(new Dimension(200, 200));
adminButton.setToolTipText("Click here if you're an admin");
layoutView();
addMouseListener(this);
revalidate();
}
public void layoutView() {
setLayout(new GridBagLayout());
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weighty = rowweights[0];
gbc.weightx = colweights[0];
gbc.fill = GridBagConstraints.BOTH;
gbc.anchor = GridBagConstraints.CENTER;
this.add(new JComponent() {
}, gbc);
layoutLoginPanel();
gbc.gridx = 1;
gbc.weighty = rowweights[1];
gbc.weightx = colweights[1];
gbc.gridwidth = 1;
gbc.gridheight = 3;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.CENTER;
this.add(loginPanel, gbc);
gbc.gridx = 2;
gbc.weighty = rowweights[2];
gbc.weightx = colweights[2];
gbc.gridwidth = 1;
gbc.gridheight = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.anchor = GridBagConstraints.SOUTHEAST;
gbc.insets = new Insets(5, 5, 5, 5);
gbc.ipadx = 100;
gbc.ipady = 100;
this.add(adminButton, gbc);
gbc.insets = new Insets(0, 0, 0, 0);
gbc.fill = GridBagConstraints.BOTH;
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 3;
gbc.gridheight = 1;
gbc.ipadx = 0;
gbc.ipady = 0;
Image img = new ImageIcon(
"C:/Users/akars/Documents/Eclipse Projects/FreeGeek Volunteering/resources/images/freegeek_frontdesk.jpg")
.getImage();
backgroundImage = new ScalableImage(img, false);
backgroundImage.setOpaque(true);
this.add(backgroundImage, gbc);
}
private void layoutLoginPanel() {
loginPanel.setLayout(new GridBagLayout());
spgbc.weightx = 1;
spgbc.weighty = 0;
spgbc.gridx = 0;
spgbc.fill = GridBagConstraints.HORIZONTAL;
spgbc.insets = new Insets(8, 8, 8, 8);
spgbc.gridy = 0;
loginPanel.add(loginLabel, spgbc);
spgbc.gridy = 1;
loginPanel.add(loginField, spgbc);
spgbc.gridy = 2;
spgbc.fill = GridBagConstraints.NONE;
spgbc.anchor = GridBagConstraints.EAST;
spgbc.ipady = 20;
spgbc.ipadx = 20;
loginPanel.add(loginButton, spgbc);
loginPanel.setBorder(BorderFactory.createLineBorder(getDarkerColor(loginPanel.getBackground(), 100), 3, true));
loginPanel.setOpaque(true);
}
public Color getDarkerColor(Color col, int num) {
return new Color(col.getRed() - num, col.getGreen() - num, col.getBlue() - num);
}
@Override
public void mouseClicked(MouseEvent e) {
MainView.this.grabFocus();
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
class ScalableImage extends JPanel {
private Image master;
private boolean toFit;
private Image scaled;
public ScalableImage(Image master) {
this(master, true);
}
public ScalableImage(Image master, boolean toFit) {
this.master = master;
setToFit(toFit);
}
@Override
public Dimension getPreferredSize() {
return master == null ? super.getPreferredSize() : new Dimension(master.getWidth(this), master.getHeight(this));
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Image toDraw = null;
if (scaled != null) {
toDraw = scaled;
} else if (master != null) {
toDraw = master;
}
if (toDraw != null) {
int x = (getWidth() - toDraw.getWidth(this)) / 2;
int y = (getHeight() - toDraw.getHeight(this)) / 2;
g.drawImage(toDraw, x, y, this);
}
}
@Override
public void invalidate() {
generateScaledInstance();
super.invalidate();
}
private boolean isToFit() {
return toFit;
}
private void setToFit(boolean value) {
if (value != toFit) {
toFit = value;
invalidate();
}
}
private void generateScaledInstance() {
scaled = null;
if (isToFit()) {
scaled = getScaledInstanceToFit(master, getSize());
} else {
scaled = getScaledInstanceToFill(master, getSize());
}
}
private BufferedImage toBufferedImage(Image master) {
Dimension masterSize = new Dimension(master.getWidth(this), master.getHeight(this));
BufferedImage image = createCompatibleImage(masterSize);
Graphics2D g2d = image.createGraphics();
g2d.drawImage(master, 0, 0, this);
g2d.dispose();
return image;
}
private Image getScaledInstanceToFit(Image master, Dimension size) {
Dimension masterSize = new Dimension(master.getWidth(this), master.getHeight(this));
return getScaledInstance(toBufferedImage(master), getScaleFactorToFit(masterSize, size),
RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
}
private Image getScaledInstanceToFill(Image master, Dimension size) {
Dimension masterSize = new Dimension(master.getWidth(this), master.getHeight(this));
return getScaledInstance(toBufferedImage(master), getScaleFactorToFill(masterSize, size),
RenderingHints.VALUE_INTERPOLATION_BILINEAR, true);
}
public Dimension getSizeToFit(Dimension original, Dimension toFit) {
double factor = getScaleFactorToFit(original, toFit);
Dimension size = new Dimension(original);
size.width *= factor;
size.height *= factor;
return size;
}
public Dimension getSizeToFill(Dimension original, Dimension toFit) {
double factor = getScaleFactorToFill(original, toFit);
Dimension size = new Dimension(original);
size.width *= factor;
size.height *= factor;
return size;
}
private double getScaleFactor(int iMasterSize, int iTargetSize) {
return (double) iTargetSize / (double) iMasterSize;
}
private double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
private double getScaleFactorToFill(Dimension masterSize, Dimension targetSize) {
double dScaleWidth = getScaleFactor(masterSize.width, targetSize.width);
double dScaleHeight = getScaleFactor(masterSize.height, targetSize.height);
return Math.max(dScaleHeight, dScaleWidth);
}
private BufferedImage createCompatibleImage(Dimension size) {
return createCompatibleImage(size.width, size.height);
}
private BufferedImage createCompatibleImage(int width, int height) {
GraphicsConfiguration gc = getGraphicsConfiguration();
if (gc == null) {
gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
BufferedImage image = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
image.coerceData(true);
return image;
}
private BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) {
BufferedImage imgScale = img;
int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor);
int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor);
if (dScaleFactor <= 1.0d) {
imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);
} else {
imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality);
}
return imgScale;
}
private BufferedImage getScaledDownInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint,
boolean higherQuality) {
int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB
: BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = img;
if (targetHeight > 0 || targetWidth > 0) {
int w, h;
if (higherQuality) {
// Use multi-step technique: start with original size, then
// scale down in multiple passes with drawImage()
// until the target size is reached
w = img.getWidth();
h = img.getHeight();
} else {
// Use one-step technique: scale directly from original
// size to target size with a single drawImage() call
w = targetWidth;
h = targetHeight;
}
do {
if (higherQuality && w > targetWidth) {
w /= 2;
if (w < targetWidth) {
w = targetWidth;
}
}
if (higherQuality && h > targetHeight) {
h /= 2;
if (h < targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
} while (w != targetWidth || h != targetHeight);
} else {
ret = new BufferedImage(1, 1, type);
}
return ret;
}
private BufferedImage getScaledUpInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint,
boolean higherQuality) {
int type = BufferedImage.TYPE_INT_ARGB;
BufferedImage ret = img;
int w, h;
if (higherQuality) {
w = img.getWidth();
h = img.getHeight();
} else {
w = targetWidth;
h = targetHeight;
}
do {
if (higherQuality && w < targetWidth) {
w *= 2;
if (w > targetWidth) {
w = targetWidth;
}
}
if (higherQuality && h < targetHeight) {
h *= 2;
if (h > targetHeight) {
h = targetHeight;
}
}
BufferedImage tmp = new BufferedImage(w, h, type);
Graphics2D g2 = tmp.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
g2.drawImage(ret, 0, 0, w, h, null);
g2.dispose();
ret = tmp;
tmp = null;
} while (w != targetWidth || h != targetHeight);
return ret;
}
}