在 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...因为我很懒,而且处理起来容易得多。

其次,你的MouseListeners 应该在内部注册Screen,它试图实现的功能由类内部维护。

根据可用的Rectangles 计算最小尺寸可能有点复杂,基本的想法是你想把它们组合成一个“超级”形状并计算它的边界,幸运的是,存在一个类这样做...

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 需要根据它拥有的可用信息(包括Screencontrols 和框架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 中限制窗口大小的主要内容,如果未能解决你的问题,请参考以下文章

JS如何设置并限制浏览器窗口的大小

调整窗口大小时带有约束的宽度限制

WPF:Scrollviewer 不将内容限制为窗口大小

MFC限制窗口大小

在 QLabel 上设置自动换行会破坏窗口的大小限制

java - 如何在java swing中检查当前窗口大小?