【发布时间】: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?