我正在为我正在上课的课程。我正在创建的程序是一款游戏。该程序有一个扩展框架的主类。在该类中,我创建了一个设置为边框布局的窗口。在边框布局的中心是一个也有边框布局的面板。我的第二个类,它扩展了canvas,被分配给第二个边框布局的CENTER。在那个画布中,我有一个使用键盘在屏幕上移动的对象。比如说以下是我的窗口,O是移动的对象:
------------------------------------------------------------
|File____________________________________________________X_|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| O |
| |
| |
| |
| |
| |
|__________________________________________________________|
有没有办法根据O的位置来限制窗口的大小?我不想调整小于渲染对象的位置。如果重要,则O存储为矩形对象,第二个边框布局的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
}
答案 0 :(得分: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
应该在Screen
内部注册,它试图实现的功能由类内部维护。
根据可用的Rectangle
计算最小尺寸可能有点复杂,基本的想法是你想将它们组合成一个“超级”形状并计算它的界限,幸运的是你,a这样做是存在的......
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());
}
}