在 Java 中限制窗口大小
Posted
技术标签:
【中文标题】在 Java 中限制窗口大小【英文标题】:Limiting window size in Java 【发布时间】:2018-09-20 18:17:23 【问题描述】:我正在为我正在上的一门课程制定一个计划。我正在创建的程序是一个游戏。该程序有一个扩展框架的主类。在该类中,我创建了一个设置为边框布局的窗口。在边框布局的中心是一个面板,它也有一个边框布局。我的第二个扩展画布的类被分配到第二个边框布局的中心。在那个画布中,我有一个使用键盘在屏幕上移动的对象。比如说下面是我的窗口,而 O 是四处移动的对象:
------------------------------------------------------------
|File____________________________________________________X_|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| O |
| |
| |
| |
| |
| |
|__________________________________________________________|
有没有办法根据 O 的位置来限制窗口的大小?我不想将大小调整为小于渲染对象的位置。如果重要的话,O 被存储为一个 Rectangle 对象,第二个边框布局的 CENTER 的边框也是如此。通过使用 Rectangle.contains 方法,我让 O 停留在边界中。在 O 离开边界后,我希望进一步限制允许的大小。
代码如下:
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import static java.lang.Integer.min;
public class BouncingBall extends Frame
implements ActionListener, WindowListener, ComponentListener, AdjustmentListener, MouseListener, MouseMotionListener, Runnable
private boolean done = false;
Thread theThread;
int sbVis = 10;
int sbMin = 1;
int sbMax = 100 + sbVis;
int sbUnitInc = 3;
int sbBlockInc = 20;
private final int DELAY = 10;
long delay = (long)(DELAY*(double)((sbMax - sbMin)/100));
private Panel canvas = new Panel();
private Panel control = new Panel();
Scrollbar speedSB;
Scrollbar sizeSB;
Button runBtn;
Button pauseBtn;
Button quitBtn;
Label speedLabel;
Label sizeLabel;
Screen s = new Screen();
Rectangle ZERORECT = new Rectangle(0,0,0,0);
private boolean newRect = true;
int x1, x2, y1, y2;
BouncingBall ()
this.setLayout(new BorderLayout());
canvas.setLayout(new BorderLayout());
initComponents();
this.setVisible(true);
start();
//main function
public static void main(String[] args)
BouncingBall b = new BouncingBall();
//end main function
private void initComponents ()
//set up main frame layout and add the components to the correct location
this.setTitle("Bouncing Ball");
this.setSize(640,480);
//this.setMinimumSize(new Dimension(640,480));
this.add(canvas, BorderLayout.CENTER);
this.add(control, BorderLayout.SOUTH);
s.setBackground(Color.WHITE);
canvas.add(s, BorderLayout.CENTER);
//mouse listeners
s.addMouseMotionListener(this);
s.addMouseListener(this);
//listeners on this frame
this.addComponentListener(this);
this.addWindowListener(this);
//add buttons, scrollbars, and labels
speedSB = new Scrollbar(Scrollbar.HORIZONTAL);
speedSB.setMinimum(sbMin);
speedSB.setMaximum(sbMax);
speedSB.setVisibleAmount(sbVis);
speedSB.setUnitIncrement(sbUnitInc);
speedSB.setBlockIncrement(sbBlockInc);
speedSB.addAdjustmentListener(this);
sizeSB = new Scrollbar(Scrollbar.HORIZONTAL);
sizeSB.setMinimum(15);
sizeSB.setMaximum(sbMax);
sizeSB.setVisibleAmount(sbVis);
sizeSB.setUnitIncrement(sbUnitInc);
sizeSB.setBlockIncrement(sbBlockInc);
sizeSB.addAdjustmentListener(this);
sizeSB.setValue(s.ball.width);
runBtn = new Button("Run");
runBtn.addActionListener(this);
runBtn.setEnabled(false);
pauseBtn = new Button("Pause");
pauseBtn.addActionListener(this);
quitBtn = new Button("Quit");
quitBtn.addActionListener(this);
speedLabel = new Label("Speed");
sizeLabel = new Label("Size");
//setup the layout of the control panel
GridBagLayout lm = new GridBagLayout();
control.setLayout(lm);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10,30,5,30);
control.add(speedSB, c);
c.insets = new Insets(10,0,5,0);
c.gridx = 1;
c.gridy = 0;
control.add(runBtn, c);
c.gridx = 2;
c.gridy = 0;
control.add(pauseBtn, c);
c.gridx = 3;
c.gridy = 0;
control.add(quitBtn, c);
c.insets = new Insets(10,30,5,30);
c.gridx = 4;
c.gridy = 0;
control.add(sizeSB, c);
c.fill = GridBagConstraints.CENTER;
c.insets = new Insets(0,0,0,0);
c.gridx = 0;
c.gridy = 1;
control.add(speedLabel, c);
c.gridx = 4;
c.gridy = 1;
control.add(sizeLabel, c);
s.repaint();
public Rectangle makeRect ()
int width = this.x1 - this.x2;
int height = this.y1 - this.y2;
Rectangle rect = new Rectangle(min(this.x1, this.x2),min(this.y1,this.y2),Math.abs(width),Math.abs(height));
return rect;
public void run()
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
while (true)
try
theThread.sleep(0);
while (!done) //pause variable
s.step();
this.setMinimumSize(s.getMinimumSize());
try
theThread.sleep(delay); //move speed
catch (InterruptedException e)
catch (InterruptedException e)
public void start() //begin overloaded start()
if (theThread == null)
theThread = new Thread(this);
theThread.start();
public void stop()
this.removeWindowListener(this);
this.removeComponentListener(this);
sizeSB.removeAdjustmentListener(this);
speedSB.removeAdjustmentListener(this);
s.removeMouseListener(this);
s.removeMouseMotionListener(this);
dispose();
System.exit(0);
//end stop()
//canvas object
public class Screen extends Canvas
Image buffer;
Graphics og;
Rectangle ball;
Rectangle screen;
int x = 1;
int y = -1;
Vector<Rectangle> rects = new Vector<Rectangle>();
public Screen()
ball = new Rectangle(10,38,30,30);
screen = new Rectangle();
public int ballX()
return ball.x;
public int ballY()
return ball.y;
public void addOne(Rectangle r)
Rectangle nr = new Rectangle(r);
if (!nr.intersects(ball))
if (nr.x + nr.width > screen.width-1)
nr.setSize((screen.width-1) - nr.x, nr.height);
if (nr.y + nr.height > screen.height-1)
nr.setSize(nr.width, (screen.height-1) - nr.y);
rects.addElement(nr);
public void checkRemove (Point p)
Point np = new Point(p);
for (int i = 0; i < rects.size(); i++)
if (rects.get(i).contains(np))
rects.removeElementAt(i);
i--;
public void step ()
checkBorder();
checkTouching();
repaint();
public void checkBorder()
Rectangle temp = new Rectangle(ball);
temp.grow(2,2);
if (screen.contains(temp))
ball.setLocation((int) ball.getX() + x, (int) ball.getY() + y);
else
if (ball.x + ball.width > screen.width-3)
x = -1;
if (ball.y + ball.height > screen.height-3)
y = -1;
if (ball.x < screen.x+2)
x = 1;
if (ball.y < screen.y+2)
y = 1;
ball.setLocation(ball.x + x, ball.y + y);
public void checkTouching()
for (int i = 0; i < rects.size(); i++)
System.out.println("size: " + getMinimumSize().width);
Rectangle b = new Rectangle(ball);
b.grow(1,1);
if(rects.get(i).intersects(b))
int left = rects.get(i).x;
int top = rects.get(i).y;
int right = rects.get(i).x + rects.get(i).width;
int bottom = rects.get(i).y + rects.get(i).height;
if ((b.x + b.width) > left)
System.out.println("x = " + x);
x=x * -1;
System.out.println("left");
System.out.println("x = " + x);
else if ((b.x < right))
System.out.println("right");
x=x * -1;
else if ((b.y + b.height) > top)
System.out.println("top");
y=y * -1;
else if (b.y < bottom)
System.out.println("bottom");
y=y * -1;
public void setObjSize (int size)
ball.setSize(size,size);
public void resized()
screen.setBounds(this.getBounds());
if (ball.x + ball.width > screen.width-3)
ball.setLocation(screen.width-ball.width-3,ball.y);
if (ball.y + ball.height > screen.height-3)
ball.setLocation(ball.x,screen.height-ball.height-3);
repaint();
@Override
public void paint(Graphics g)
update(g);
@Override
public void update(Graphics g)
if (og != null)
og.dispose();
buffer = createImage(screen.width, screen.height);
og = buffer.getGraphics();
super.paint(g);
Rectangle rect = makeRect();
og.setColor(Color.BLACK);
if (!newRect)
og.fillRect(rect.x,rect.y,rect.width,rect.height);
for (Rectangle drawRect : this.rects)
og.fillRect(drawRect.x,drawRect.y,drawRect.width,drawRect.height);
//draw the screen border
og.setColor(Color.RED);
og.drawRect(screen.x,screen.y,screen.width-1,screen.height-1);
//draw the ball
og.setColor(Color.LIGHT_GRAY);
og.fillOval(ball.x,ball.y,ball.width,ball.height);
og.setColor(Color.BLACK);
og.drawOval(ball.x,ball.y,ball.width,ball.height);
g.drawImage(buffer,0,0,null);
@Override
public Dimension getMinimumSize()
for(Rectangle temp : this.rects)
//overloaded listeners
public void actionPerformed(ActionEvent e)
Object o = e.getSource();
if (o == quitBtn)
stop();
else if (o == runBtn)
done = false;
runBtn.setEnabled(false);
pauseBtn.setEnabled(true);
else if (o == pauseBtn)
done = true;
runBtn.setEnabled(true);
pauseBtn.setEnabled(false);
public void adjustmentValueChanged(AdjustmentEvent e)
Object obj = e.getSource();
if (obj == sizeSB)
int objSize;
int maxSize = min(s.getWidth()-s.ballX(), s.getHeight()-s.ballY());
if(maxSize > e.getValue())
objSize = e.getValue();
s.setObjSize(objSize);
else
objSize = maxSize;
s.setObjSize(objSize);
sizeSB.setValue(objSize);
if (obj == speedSB)
int speed = e.getValue();
delay = (long) (DELAY*(double)(sbMax - speed + 1)/100);
theThread.interrupt();
public void componentResized(ComponentEvent e)
s.resized();
System.out.println(s.getHeight());
public void componentMoved(ComponentEvent e)
public void componentShown(ComponentEvent e)
public void componentHidden(ComponentEvent e)
public void mouseClicked(MouseEvent e)
Point p = new Point(e.getX(),e.getY());
s.checkRemove(p);
public void mousePressed(MouseEvent e)
this.x1 = e.getX();
this.y1 = e.getY();
System.out.println("x1 = " + x1);
System.out.println("y1 = " + y1);
s.repaint();
public void mouseReleased(MouseEvent e)
this.x2 = e.getX();
this.y2 = e.getY();
Rectangle rect = makeRect();
if (rect.height != 0 || rect.width != 0)
s.addOne(rect);
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
this.newRect = true;
s.repaint();
public void mouseEntered(MouseEvent e)
public void mouseExited(MouseEvent e)
public void mouseDragged(MouseEvent e)
this.x2 = e.getX();
this.y2 = e.getY();
this.newRect = false;
s.repaint();
public void mouseMoved(MouseEvent e)
public void windowOpened(WindowEvent e)
public void windowClosing(WindowEvent e)
stop();
public void windowClosed(WindowEvent e)
public void windowIconified(WindowEvent e)
public void windowDeiconified(WindowEvent e)
public void windowActivated(WindowEvent e)
public void windowDeactivated(WindowEvent e)
//end overloaded listeners
【问题讨论】:
您是否考虑尝试使用getMinimumSize
,可能会从Canvas
类中覆盖它?
我已经考虑过了,但我不确定它会如何工作。我在画布上绘制了两个矩形。这将如何运作?
这一切都取决于你是如何编码的——因为我们没有这些信息,这一切都只是我们猜测的工作
我已更新问题以包含代码。一些代码还没有工作 :) 我开始添加一些我认为可能会使用 getMinimumSize 方法的代码。
好的,到目前为止,您从使用 java.awt.Panel
和一大堆开销中获得的收益为 0。你有什么理由不使用至少 Swing?
【参考方案1】:
我试图找到一些更优雅的东西,但无法让它按应有的方式工作,所以我最终采用了蛮力方法。
基本上,这会将ComponentListener
添加到Frame
并监视它的componentResized
事件。然后它将框架的大小与内容minimumSize
进行比较,并确保大小永远不会超过它(同时考虑到框架的边框)。
我知道这是在 Swing 中,但基本概念应该适用于 AWT
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
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.add(new TestPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.addComponentListener(new ComponentAdapter()
private boolean ignoreNext = false;
@Override
public void componentResized(ComponentEvent e)
if (ignoreNext)
ignoreNext = false;
return;
Insets insets = frame.getInsets();
ignoreNext = true;
int width = Math.max(frame.getWidth(), frame.getContentPane().getMinimumSize().width + (insets.left + insets.right));
int height = Math.max(frame.getHeight(), frame.getContentPane().getMinimumSize().height + (insets.top + insets.bottom));
frame.setSize(width, height);
);
frame.setVisible(true);
);
public class TestPane extends JPanel
private Rectangle rect;
public TestPane()
MouseAdapter ma = new MouseAdapter()
private Point anchor;
@Override
public void mouseDragged(MouseEvent e)
Point p = e.getPoint();
int minX = Math.min(anchor.x, p.x);
int minY = Math.min(anchor.y, p.y);
int maxX = Math.max(anchor.x, p.x);
int maxY = Math.max(anchor.y, p.y);
rect = new Rectangle(minX, minY, maxX - minX, maxY - minY);
repaint();
revalidate();
@Override
public void mousePressed(MouseEvent e)
anchor = e.getPoint();
@Override
public void mouseReleased(MouseEvent e)
anchor = null;
;
addMouseMotionListener(ma);
addMouseListener(ma);
@Override
public Dimension getPreferredSize()
return new Dimension(600, 600);
@Override
public Dimension getMinimumSize()
if (rect == null)
return super.getMinimumSize();
Dimension size = new Dimension(rect.x + rect.width, rect.y + rect.height);
return size;
@Override
protected void paintComponent(Graphics g)
super.paintComponent(g);
if (rect == null)
return;
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLUE);
g2d.fill(rect);
g2d.dispose();
已根据可用代码更新...
好的,这比它应该花费的时间更长。我不得不把你的代码拆开,然后重新组合起来。有许多基本错误和一些“难以找到”的作业,这些作业不断给出平均错误的结果。
首先,update
调用paint
,所以你的“绘画”程序是倒退的。 update
应该确保有一个可用的屏幕外缓冲区并在需要时创建一个缓冲区,然后应该在它的 Graphics
上下文中进行绘制。我玩了一下,改用BufferedImage
...因为我很懒,而且处理起来容易得多。
其次,你的MouseListener
s 应该在内部注册Screen
,它试图实现的功能由类内部维护。
根据可用的Rectangle
s 计算最小尺寸可能有点复杂,基本的想法是你想把它们组合成一个“超级”形状并计算它的边界,幸运的是,存在一个类这样做...
Area area = new Area();
for (Rectangle temp : this.rects)
System.out.println(temp);
area.add(new Area(temp));
Rectangle bounds = area.getBounds();
System.out.println("bounds = " + bounds);
Dimension size = new Dimension(bounds.x + bounds.width, bounds.y + bounds.height);
最后,经过我真正想要的更多的混乱之后,我最终得到了一个观察者模式,当“大小约束”可能发生变化时,它会触发通知。然后Frame
需要根据它拥有的可用信息(包括Screen
、controls
和框架Insets
来确定它的最小尺寸...
所以,你知道,真的很容易:P
弹跳球
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.Scrollbar;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import static java.lang.Math.min;
public class BouncingBall extends Frame
implements ActionListener, AdjustmentListener, Runnable
private boolean done = false;
Thread theThread;
int sbVis = 10;
int sbMin = 1;
int sbMax = 100 + sbVis;
int sbUnitInc = 3;
int sbBlockInc = 20;
private final int DELAY = 10;
long delay = (long) (DELAY * (double) ((sbMax - sbMin) / 100));
// private Panel canvas = new Panel();
private Panel control = new Panel();
Scrollbar speedSB;
Scrollbar sizeSB;
Button runBtn;
Button pauseBtn;
Button quitBtn;
Label speedLabel;
Label sizeLabel;
Screen s = new Screen();
Rectangle ZERORECT = new Rectangle(0, 0, 0, 0);
private boolean newRect = true;
int x1, x2, y1, y2;
BouncingBall()
this.setLayout(new BorderLayout());
// canvas.setLayout(new BorderLayout());
initComponents();
this.setVisible(true);
start();
//main function
public static void main(String[] args)
BouncingBall b = new BouncingBall();
//end main function
private void initComponents()
//set up main frame layout and add the components to the correct location
this.setTitle("Bouncing Ball");
this.setSize(640, 480);
this.add(s, BorderLayout.CENTER);
this.add(control, BorderLayout.SOUTH);
s.setBackground(Color.WHITE);
s.setConstraintListener(new Screen.ConstraintListener()
@Override
public void constraintsChanged(Dimension size)
System.out.println("Size = " + size);
Insets insets = getInsets();
int minWidth = size.width + (insets.left + insets.right);
int minHeight = size.height + control.getPreferredSize().height + (insets.top + insets.bottom);
System.out.println(minWidth + " - " + minHeight);
setMinimumSize(new Dimension(minWidth, minHeight));
);
// canvas.add(s, BorderLayout.CENTER);
//listeners on this frame
// this.addComponentListener(new ComponentAdapter()
// private boolean ignoreNext = false;
// @Override
// public void componentResized(ComponentEvent e)
// if (ignoreNext)
// ignoreNext = false;
// return;
//
// Insets insets = getInsets();
// ignoreNext = true;
// int minWidth = canvas.getMinimumSize().width;
// int minHeight = canvas.getMinimumSize().height + control.getPreferredSize().height;
// int width = Math.max(getWidth(), minWidth + (insets.left + insets.right));
// int height = Math.max(getHeight(), minHeight + (insets.top + insets.bottom));
// setSize(width, height);
//
// );
this.addWindowListener(new WindowAdapter()
@Override
public void windowClosing(WindowEvent e)
stop();
);
//add buttons, scrollbars, and labels
speedSB = new Scrollbar(Scrollbar.HORIZONTAL);
speedSB.setMinimum(sbMin);
speedSB.setMaximum(sbMax);
speedSB.setVisibleAmount(sbVis);
speedSB.setUnitIncrement(sbUnitInc);
speedSB.setBlockIncrement(sbBlockInc);
speedSB.addAdjustmentListener(this);
sizeSB = new Scrollbar(Scrollbar.HORIZONTAL);
sizeSB.setMinimum(15);
sizeSB.setMaximum(sbMax);
sizeSB.setVisibleAmount(sbVis);
sizeSB.setUnitIncrement(sbUnitInc);
sizeSB.setBlockIncrement(sbBlockInc);
sizeSB.addAdjustmentListener(this);
sizeSB.setValue(s.ball.width);
runBtn = new Button("Run");
runBtn.addActionListener(this);
runBtn.setEnabled(false);
pauseBtn = new Button("Pause");
pauseBtn.addActionListener(this);
quitBtn = new Button("Quit");
quitBtn.addActionListener(this);
speedLabel = new Label("Speed");
sizeLabel = new Label("Size");
//setup the layout of the control panel
GridBagLayout lm = new GridBagLayout();
control.setLayout(lm);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(10, 30, 5, 30);
control.add(speedSB, c);
c.insets = new Insets(10, 0, 5, 0);
c.gridx = 1;
c.gridy = 0;
control.add(runBtn, c);
c.gridx = 2;
c.gridy = 0;
control.add(pauseBtn, c);
c.gridx = 3;
c.gridy = 0;
control.add(quitBtn, c);
c.insets = new Insets(10, 30, 5, 30);
c.gridx = 4;
c.gridy = 0;
control.add(sizeSB, c);
c.fill = GridBagConstraints.CENTER;
c.insets = new Insets(0, 0, 0, 0);
c.gridx = 0;
c.gridy = 1;
control.add(speedLabel, c);
c.gridx = 4;
c.gridy = 1;
control.add(sizeLabel, c);
s.repaint();
public Rectangle makeRect()
int width = this.x1 - this.x2;
int height = this.y1 - this.y2;
Rectangle rect = new Rectangle(min(this.x1, this.x2), min(this.y1, this.y2), Math.abs(width), Math.abs(height));
return rect;
public void run()
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
while (true)
try
theThread.sleep(0);
while (!done) //pause variable
s.step();
try
theThread.sleep(delay); //move speed
catch (InterruptedException e)
catch (InterruptedException e)
public void start() //begin overloaded start()
if (theThread == null)
theThread = new Thread(this);
theThread.start();
public void stop()
sizeSB.removeAdjustmentListener(this);
speedSB.removeAdjustmentListener(this);
dispose();
System.exit(0);
//end stop()
//canvas object
//overloaded listeners
public void actionPerformed(ActionEvent e)
Object o = e.getSource();
if (o == quitBtn)
stop();
else if (o == runBtn)
done = false;
runBtn.setEnabled(false);
pauseBtn.setEnabled(true);
else if (o == pauseBtn)
done = true;
runBtn.setEnabled(true);
pauseBtn.setEnabled(false);
public void adjustmentValueChanged(AdjustmentEvent e)
Object obj = e.getSource();
if (obj == sizeSB)
int objSize;
int maxSize = min(s.getWidth() - s.ballX(), s.getHeight() - s.ballY());
if (maxSize > e.getValue())
objSize = e.getValue();
s.setObjSize(objSize);
else
objSize = maxSize;
s.setObjSize(objSize);
sizeSB.setValue(objSize);
if (obj == speedSB)
int speed = e.getValue();
delay = (long) (DELAY * (double) (sbMax - speed + 1) / 100);
theThread.interrupt();
//end overloaded listeners
屏幕
//canvas object
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
public class Screen extends Canvas
Rectangle ball;
Vector<Rectangle> rects = new Vector<Rectangle>();
int x = 1;
int y = -1;
private BufferedImage buffer;
private Rectangle temp;
public Screen()
ball = new Rectangle(10, 38, 30, 30);
MouseAdapter ma = new MouseAdapter()
private Point anchor;
public void mouseClicked(MouseEvent e)
Point p = new Point(e.getX(), e.getY());
checkRemove(p);
public void mousePressed(MouseEvent e)
anchor = new Point(e.getPoint());
public void mouseReleased(MouseEvent e)
anchor = null;
if (temp != null)
addOne(temp);
temp = null;
repaint();
public void mouseDragged(MouseEvent e)
Point p = e.getPoint();
int minX = Math.min(anchor.x, p.x);
int minY = Math.min(anchor.y, p.y);
int maxX = Math.max(anchor.x, p.x);
int maxY = Math.max(anchor.y, p.y);
temp = new Rectangle(minX, minY, maxX - minX, maxY - minY);
repaint();
;
addMouseListener(ma);
addMouseMotionListener(ma);
public int ballX()
return ball.x;
public int ballY()
return ball.y;
public void addOne(Rectangle r)
Rectangle nr = new Rectangle(r);
if (!nr.intersects(ball))
if (nr.x + nr.width > getWidth() - 1)
nr.setSize((getWidth() - 1) - nr.x, nr.height);
if (nr.y + nr.height > getHeight() - 1)
nr.setSize(nr.width, (getHeight() - 1) - nr.y);
rects.addElement(nr);
setMinimumSize(calculateMinimumSize());
constraintsChanged();
public void checkRemove(Point p)
Point np = new Point(p);
for (int i = 0; i < rects.size(); i++)
if (rects.get(i).contains(np))
rects.removeElementAt(i);
i--;
setMinimumSize(calculateMinimumSize());
constraintsChanged();
public void step()
checkBorder();
checkTouching();
repaint();
public void checkBorder()
Rectangle tempBall = new Rectangle(ball);
tempBall.grow(2, 2);
Rectangle screen = new Rectangle(new Point(0, 0), getSize());
if (screen.contains(tempBall))
ball.setLocation((int) ball.getX() + x, (int) ball.getY() + y);
else
if (ball.x + ball.width > screen.width - 3)
x = -1;
if (ball.y + ball.height > screen.height - 3)
y = -1;
if (ball.x < screen.x + 2)
x = 1;
if (ball.y < screen.y + 2)
y = 1;
ball.setLocation(ball.x + x, ball.y + y);
public void checkTouching()
if (temp != null)
rects.add(temp);
for (int i = 0; i < rects.size(); i++)
Rectangle b = new Rectangle(ball);
b.grow(1, 1);
if (rects.get(i).intersects(b))
int left = rects.get(i).x;
int top = rects.get(i).y;
int right = rects.get(i).x + rects.get(i).width;
int bottom = rects.get(i).y + rects.get(i).height;
if ((b.x + b.width) > left)
x = x * -1;
else if ((b.x < right))
x = x * -1;
else if ((b.y + b.height) > top)
y = y * -1;
else if (b.y < bottom)
y = y * -1;
if (temp != null)
rects.remove(temp);
public void setObjSize(int size)
ball.setSize(size, size);
@Override
public void invalidate()
super.invalidate();
buffer = null;
resized();
public void resized()
if (ball.x + ball.width > getWidth() - 3)
ball.setLocation(getWidth() - ball.width - 3, ball.y);
if (ball.y + ball.height > getHeight() - 3)
ball.setLocation(ball.x, getHeight() - ball.height - 3);
repaint();
@Override
public void paint(Graphics g)
Graphics2D g2d = (Graphics2D) g.create();
super.paint(g2d);
g2d.setColor(getBackground());
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
if (temp != null)
g2d.fill(temp);
for (Rectangle drawRect : this.rects)
g2d.fill(drawRect);
//draw the screen border
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
//draw the ball
g2d.setColor(Color.LIGHT_GRAY);
g2d.fillOval(ball.x, ball.y, ball.width, ball.height);
g2d.setColor(Color.BLACK);
g2d.drawOval(ball.x, ball.y, ball.width, ball.height);
g2d.dispose();
@Override
public void update(Graphics g)
if (buffer == null)
buffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = buffer.createGraphics();
super.update(g2d);
g2d.dispose();
g.drawImage(buffer, 0, 0, null);
protected Dimension calculateMinimumSize()
Area area = new Area();
for (Rectangle temp : this.rects)
System.out.println(temp);
area.add(new Area(temp));
Rectangle bounds = area.getBounds();
System.out.println("bounds = " + bounds);
Dimension size = new Dimension(bounds.x + bounds.width, bounds.y + bounds.height);
return size;
public interface ConstraintListener
public void constraintsChanged(Dimension size);
private ConstraintListener listener;
public void setConstraintListener(ConstraintListener listener)
this.listener = listener;
protected void constraintsChanged()
if (listener == null)
return;
listener.constraintsChanged(getMinimumSize());
【讨论】:
我以前做过类似的事情,但是它跳了很多,然后最终还是比矩形小。可以动态设置 minimumSize 吗? @Nick 我调查了那条路但没有成功 班上的教授似乎认为不用跳来跳去也能做到这一点。但是,当我和其他人问他时,它就像是一个秘密,如何做到这一点。非常感谢您帮助我找到解决方案。 首先,提供的示例对我来说并没有反弹。 SetMininumSize(在框架上)与平台无关,对我不起作用,在组件上设置它没有效果 感谢您的帮助。感谢你所做的一切。这比我预期的答案要多得多:)以上是关于在 Java 中限制窗口大小的主要内容,如果未能解决你的问题,请参考以下文章