简体   繁体   中英

Java Swing Frame is a tad off?

I have a simple animation code that creates a meter type rectangle effect. I would like to create it so that it fills a panel completely. I am so close, but it extends past the frame on the bottom. What am I missing?

public class Main {

public static void main(String[] args) {

    JFrame frame = new JFrame("Pong");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new GridLayout(1,2));
    frame.setSize(500, 500);

    //MouseTest test = new MouseTest();
    Test test2 = new Test(frame.getWidth(), frame.getHeight(), frame.getHeight(), 50);
    //frame.add(test);
    frame.add(test2);

    frame.setVisible(true);

    }
}

public class Test extends JPanel implements ActionListener, MouseListener{

int y = 0, width, height, dy=0, maxHeight;
int BOTTOM;
Timer timer;

public Test(int width, int height, int BOTTOM, int SPEED){
    setBackground(Color.BLUE);
    this.width = width;
    maxHeight = height;
    this.BOTTOM = BOTTOM;

    addMouseListener(this);

    timer = new Timer(1000/SPEED, this);
    timer.start();

   }
 public void move(){

    if(y>=maxHeight){
        dy = -1;
    }
    if(y<=0)
    {
        dy = 1;
    }
    y+=dy;
    height+=dy;
    //System.out.println(y);
    repaint();

}

public void paintComponent(Graphics g){

    super.paintComponent(g);
    if(y<=maxHeight/2) {
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - y, width, height);
    }
    if(y>=maxHeight/2 && y<(maxHeight/10)*9){
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM-(maxHeight/2), width, maxHeight/2);
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - y, width, height-(maxHeight/2));
    }
    if(y>=(maxHeight/10)*9){
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM-(maxHeight/2), width, maxHeight/2);
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM-(9*(maxHeight/10)), width, (4*maxHeight)/10);
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - y, width, height-(9*(maxHeight)/10));
    }
        for(int i = 1; i<6; i++)
            g.fillRect(0, BOTTOM - (i*(maxHeight/5)), width, 10);

    System.out.println(y);



}

Your panel takes up less room than your JFrame , because your frame has a title bar and window borders. You can just query in your paint method for the correct width and height used by the 'JPanel' with your JPanel 's getWidth() and getHeight() (in other words, your JFrame's width and height is not the same as your JPanel's width and height, even though the JPanel takes up all the space within the frame visually between the borders).

Alternatively, if you did have logic where this was not possible, you could query the size of the insets of the frame , and subtract the left and right inset values from the width, and pass that as the width, and do the same for the height with the top and bottom inset values.

  • Override getPreferredSize of your JPanel , this will helps the layout manager determine the best way to layout your component
  • Use JFrame#pack to wrap the frame borders around the view
  • Use getWidth and getHeight to get the actual size the panel. You should do this whenever you need to know these values, don't store them for long periods, as the values can change
  • You should also have a read through Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?

This is basic example based on you code...

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test1 {

    public static void main(String[] args) {
        new Test1();
    }

    public Test1() {
        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.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private int yPos;
        private int dy = 1;
        private int bottom = 50;

        public TestPane() {
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    move();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }

        public void move() {

            if (yPos >= getHeight()) {
                dy = -1;
            }
            if (yPos <= 0) {
                dy = 1;
            }
            yPos += dy;
            repaint();

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int maxHeight = getHeight();
            int width = getWidth();
            int height = maxHeight;
            if (yPos <= maxHeight / 2) {
                g.setColor(Color.green);
                g.fillRect(0, bottom - yPos, width, height);
            }
            if (yPos >= maxHeight / 2 && yPos < (maxHeight / 10) * 9) {
                g.setColor(Color.green);
                g.fillRect(0, bottom - (maxHeight / 2), width, maxHeight / 2);
                g.setColor(Color.green);
                g.fillRect(0, bottom - yPos, width, height - (maxHeight / 2));
            }
            if (yPos >= (maxHeight / 10) * 9) {
                g.setColor(Color.green);
                g.fillRect(0, bottom - (maxHeight / 2), width, maxHeight / 2);
                g.setColor(Color.green);
                g.fillRect(0, bottom - (9 * (maxHeight / 10)), width, (4 * maxHeight) / 10);
                g.setColor(Color.green);
                g.fillRect(0, bottom - yPos, width, height - (9 * (maxHeight) / 10));
            }
            for (int i = 1; i < 6; i++) {
                g.fillRect(0, bottom - (i * (maxHeight / 5)), width, 10);
            }

        }
    }

}

Another way to go is to use pack(). It sets the size of the frame to be the size of the frame's contents. In your code it would look like this:

frame.add(test2);
frame.pack();

If you do it this way, you don't need the frame.setSize() call. You can add the panel either with .add() as you've done or with:

frame.setContentPane(test2);

So I combined both your comments and got it to work correctly. Here is the code that works.

public class Main {

public static void main(String[] args) {

    JFrame frame = new JFrame("Pong");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(new GridLayout(1,2));
    Insets inset = frame.getInsets();


    Test test2 = new Test(200-(inset.right + inset.left), 200 -(inset.top + inset.bottom), 200, 50);
    frame.setContentPane(test2);
    frame.pack();

    frame.setVisible(true);

}
}

public class Test extends JPanel implements ActionListener, MouseListener{

int y = 0, width, height, dy=0, maxHeight;
int BOTTOM;
Timer timer;
Dimension size;
Insets inset;

public Test(int width, int height, int BOTTOM, int SPEED){
    size = new Dimension(width, height);
    setBackground(Color.BLUE);
    setPreferredSize(size);
    inset = this.getInsets();
    this.width = width-(inset.right+inset.left);
    maxHeight = height;
    this.BOTTOM = BOTTOM - (inset.bottom+inset.top);

    addMouseListener(this);

    timer = new Timer(1000/SPEED, this);
    timer.start();

   }
public void move(){

    if(y>=maxHeight){
        dy = -1;
    }
    if(y<=0)
    {
        dy = 1;
    }
    y+=dy;
    height+=dy;
    //System.out.println(y);
    repaint();

}

public void paintComponent(Graphics g){

    super.paintComponent(g);
    if(y<=maxHeight/2) {
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - y, width, height);
    }
    if(y>=maxHeight/2 && y<(maxHeight/10)*9){
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - (maxHeight / 2), width, maxHeight / 2);
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - y, width, height-(maxHeight/2));
    }
    if(y>=(maxHeight/10)*9){
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM-(maxHeight/2), width, maxHeight/2);
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM-(9*(maxHeight/10)), width, (4*maxHeight)/10);
        g.setColor(Color.green);
        g.fillRect(0, BOTTOM - y, width, height-(9*(maxHeight)/10));
    }

    g.setColor(Color.white);
        for(int i = 1; i<6; i++)
            g.fillRect(0, BOTTOM - (i*(maxHeight/5)), width, 5);

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM