Java 不让图形脱离JFrame边界

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

虽然也有类似的问题,但我认为我的问题略有不同,因为我的代码是如何设置的。我的主方法中有一个JFrame。然而,我的构造函数中只有JPanel。我尝试将一些变量设置为静态,以便在main方法中访问它们,例如,如果此图形的x坐标加上宽度大于frame.getWidth()。。但出于某种原因,这是行不通的。我不想用代码轰炸任何人,所以我会尽量把主要信息放进去,如果你需要更多,我会更新它

   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())时执行