Java 不让图形脱离JFrame边界
虽然也有类似的问题,但我认为我的问题略有不同,因为我的代码是如何设置的。我的主方法中有一个JFrame。然而,我的构造函数中只有JPanel。我尝试将一些变量设置为静态,以便在main方法中访问它们,例如,如果此图形的x坐标加上宽度大于frame.getWidth()。。但出于某种原因,这是行不通的。我不想用代码轰炸任何人,所以我会尽量把主要信息放进去,如果你需要更多,我会更新它Java 不让图形脱离JFrame边界,java,swing,user-interface,jframe,jpanel,Java,Swing,User Interface,Jframe,Jpanel,虽然也有类似的问题,但我认为我的问题略有不同,因为我的代码是如何设置的。我的主方法中有一个JFrame。然而,我的构造函数中只有JPanel。我尝试将一些变量设置为静态,以便在main方法中访问它们,例如,如果此图形的x坐标加上宽度大于frame.getWidth()。。但出于某种原因,这是行不通的。我不想用代码轰炸任何人,所以我会尽量把主要信息放进去,如果你需要更多,我会更新它 package finalProj; import javax.swing.JFrame; im
package finalProj;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;
public class nonaMaingamePractice extends JPanel implements ActionListener, KeyListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static Ellipse2D ellipse;
static Toolkit tools = Toolkit.getDefaultToolkit();
static int screenWidth = (int)(Math.round(tools.getScreenSize().getWidth()));
static int screenHeight = (int)(Math.round(tools.getScreenSize().getHeight()));
private static Rectangle paddleRect;
JLabel text = new JLabel("cool");
Timer timeMove = new Timer(1, this);
Timer timeBall = new Timer(10, new timeBall());
private static double x = screenWidth/2, y = (screenHeight*0.8), xx = 0, yy = 0, score = 0, Ox = screenWidth/2, Oy = screenHeight/2, Oyy = 0, width = 100, height = 30;
public nonaMaingamePractice(){
setLayout(new BorderLayout());
timeBall.start();
timeMove.start();
addKeyListener(this);
setFocusable(true);
JPanel panelNorth = makePanel();
panelNorth.setBackground(Color.CYAN);
add(panelNorth, BorderLayout.NORTH);
JLabel scoreLabel = new JLabel("Score: " + score);
panelNorth.add(scoreLabel);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLUE);
paddleRect = new Rectangle((int)x, (int)y, (int)width, (int)height);
ellipse = new Ellipse2D.Double(Ox, Oy+Oyy, 50, 50);
Graphics2D graphics = (Graphics2D)g;
graphics.fill(paddleRect);
graphics.fill(ellipse);
}
@Override
public void actionPerformed(ActionEvent e) {
x = x + xx;
y = y + yy;
if(x<0){
x=0;
xx=0;
}
repaint();
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
int c = e.getKeyCode();
if(c==KeyEvent.VK_RIGHT){
xx=1;
}else if(c==KeyEvent.VK_LEFT){
xx=-1;
}
}
@Override
public void keyReleased(KeyEvent e) {
xx=0;
}
protected JPanel makePanel() {
@SuppressWarnings("serial")
JPanel pane = new JPanel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 30);
}
};
pane.setBackground(Color.CYAN);
return pane;
}
protected class timeBall implements ActionListener{
Timer timeWhateva = new Timer(100, this);
@Override
public void actionPerformed(ActionEvent e) {
try{
System.out.println(paddleRect.getX());
if(ellipse.intersects(paddleRect)){
timeWhateva.start();
Oy+=-1;
System.out.println(ellipse.getX() + " " + ellipse.getY());
}else if(!ellipse.intersects(paddleRect)){
Oyy+=1;
}
}catch(RuntimeException NullPointerException){
System.out.println(NullPointerException.getMessage());
}
repaint();
}
}
public static void main(String[] args){
nonaMaingamePractice main = new nonaMaingamePractice();
JFrame frame = new JFrame();
frame.add(main);
frame.setVisible(true);
frame.setTitle("Project 4 game");
frame.setSize(screenWidth, screenHeight);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
package finalProj;
导入javax.swing.JFrame;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
导入javax.swing.Timer;
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.Rectangle;
导入java.awt.Toolkit;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入java.awt.geom.Ellipse2D;
公共类NoMainGamePractice扩展了JPanel实现ActionListener、KeyListener{
/**
*
*/
私有静态最终长serialVersionUID=1L;
私有静态椭圆2维椭圆;
静态Toolkit tools=Toolkit.getDefaultToolkit();
静态int screenWidth=(int)(Math.round(tools.getScreenSize().getWidth());
静态int屏幕高度=(int)(Math.round(tools.getScreenSize().getHeight());
私有静态矩形;
JLabel text=新JLabel(“酷”);
定时器timeMove=新定时器(1,此);
Timer timeBall=新计时器(10,new timeBall());
私有静态双精度x=screenWidth/2,y=(screenHeight*0.8),xx=0,yy=0,分数=0,Ox=screenWidth/2,Oy=screenHeight/2,Oyy=0,宽度=100,高度=30;
公共非军事演习(){
setLayout(新的BorderLayout());
timeBall.start();
timeMove.start();
addKeyListener(此);
设置聚焦(真);
JPanel panelNorth=makePanel();
镶板北面。背景(颜色。青色);
添加(panelNorth,BorderLayout.NORTH);
JLabel scoreLabel=新的JLabel(“分数:+分数”);
panelNorth.add(分数标签);
}
公共组件(图形g){
超级组件(g);
g、 setColor(Color.BLUE);
新矩形((int)x,(int)y,(int)宽度,(int)高度);
椭圆=新椭圆2d.双(Ox,Oy+Oyy,50,50);
Graphics2D graphics=(Graphics2D)g;
图形填充(pablerrect);
图形填充(椭圆);
}
@凌驾
已执行的公共无效操作(操作事件e){
x=x+xx;
y=y+yy;
如果(x好,那么似乎有一些事情是错误的
首先,不要依赖static
进行跨对象通信,这是一个非常糟糕的主意,它会反过来严重影响您。相反,将信息传递给需要它的类
其次,我将重点放在拥有一个计时器(或“主循环”),负责更新游戏的当前状态并安排重新绘制。这是范例的基本概念
我要做的第一件事是把你的代码完全拆开,然后重建它
首先,我需要一种界面,它提供关于游戏当前状态的信息,我可以将其实例传递给游戏的其他部分,以便他们做出决策并更新游戏状态
public interface GameView {
public boolean isKeyRightPressed();
public boolean isKeyLeftPressed();
public Dimension getSize();
public void updateState();
}
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
public interface GameModel {
public Rectangle getPaddle();
public Ellipse2D getBall();
public void ballWasMissed();
}
这将提供有关左右键的状态、视图大小的信息,并提供一些基本功能来请求视图更新其当前状态
接下来,我们需要一些方法来模拟游戏的状态
public interface GameView {
public boolean isKeyRightPressed();
public boolean isKeyLeftPressed();
public Dimension getSize();
public void updateState();
}
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
public interface GameModel {
public Rectangle getPaddle();
public Ellipse2D getBall();
public void ballWasMissed();
}
因此,这基本上维护了关于桨和球的信息,并提供了一种方法,通过这种方法,“主游戏循环”可以向模型提供关于游戏状态的通知
接下来,我们需要实际的“主游戏循环”或控制器,这是负责更新模型状态和更新视图
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
public class MainLoop implements ActionListener {
private GameView gameView;
private GameModel gameModel;
private int ballYDelta = 1;
public MainLoop(GameView gameView, GameModel gameModel) {
this.gameView = gameView;
this.gameModel = gameModel;
}
@Override
public void actionPerformed(ActionEvent e) {
Rectangle paddle = gameModel.getPaddle();
Ellipse2D ball = gameModel.getBall();
// Update the paddle position...
if (gameView.isKeyLeftPressed()) {
paddle.x--;
} else if (gameView.isKeyRightPressed()) {
paddle.x++;
}
// Correct for overflow...
if (paddle.x < 0) {
paddle.x = 0;
} else if (paddle.x + paddle.width > gameView.getSize().width) {
paddle.x = gameView.getSize().width - paddle.width;
}
// Update the ball position...
Rectangle bounds = ball.getBounds();
bounds.y += ballYDelta;
if (bounds.y < 0) {
bounds.y = 0;
ballYDelta *= -1;
} else if (bounds.y > gameView.getSize().height) {
// Ball is out of bounds...
// Notify the gameView so it knows what to do when the ball goes
// out of the game view's viewable, ie update the score...
// Reset ball position to just out side the top of the view...
gameModel.ballWasMissed();
bounds.y = -bounds.height;
} else if (paddle.intersects(bounds)) {
// Put the ball to the top of the paddle
bounds.y = paddle.y - bounds.height;
// Bounce
ballYDelta *= -1;
}
ball.setFrame(bounds);
// Update the view
gameView.updateState();
}
}
你的问题是什么?你是在问如何使用不大于屏幕的自定义绘制来制作JPanel吗?抱歉@VGR,问题是:如何使图形不离开JFrame的外部?请记住,框架的装饰绘制在可见框架区域的边界内,因此,从技术上讲,尝试o将任何东西限制在框架内都需要考虑这些因素。话虽如此,我真的不知道你在问什么。什么图形?我能想到的最简单的事情是,简单地使用另一个JPanel
,添加到边框布局的中心位置,并使用它来显示任何自定义图形SY您似乎也在使用多线程,这有点可怕。当在绘制面板上调用getWidth()
和getHeight()
时,您的球和桨应该根据返回的值限制它们的位置。例如:当前,您正在检查if(x<0)
。要检查拨杆是否已到达右侧,请在(x+width>=getWidth())时执行
。