简体   繁体   English

如何使JPanel使它的组件更贴合自己?

[英]How to Get JPanel to Fit Snug With Its Components?

I have 2 issues. 我有2个问题。

First issue: I have to set the JFrame as non resizable, however, an error is thrown up when I enter in frame.setResizable(false); 第一个问题:我必须将JFrame设置为不可调整大小,但是,当我在frame.setResizable(false)中输入时,会引发错误。

Second issue: I have ran into the problem of the JFrame not fitting the component within it perfectly. 第二个问题:我遇到了JFrame无法完全适合其中的组件的问题。 I have set the dimensions for the JFrame to 600x720 and the board component as being 600x600. 我已将JFrame的尺寸设置为600x720,并将板组件设置为600x600。 However, when I extend the JFrame I can see that there is more of the component to be revealed. 但是,当我扩展JFrame时,我可以看到还有更多的组件需要显示。 How would I change this to accommodate the component to fit snugly but also leave space for another component of size 100x120? 如何更改此尺寸以适应紧密贴合的组件,同时又为另一个尺寸为100x120的组件留出空间? My understanding of this is that JFrame sets the size with the borders included, however, I want the space within the JFrame to be exactly 600x720 pixels without including the border. 我对此的理解是JFrame设置了包含边框的大小,但是,我希望JFrame中的空间恰好是600x720像素,而不包括边框。

The code is set out below. 代码如下。

Game Class 游戏类

package snake;

//This class is used to run the game.
public class Game {

    /**
     * @author HyperBlue
     */

    //Declaring a static variable of type Board. This can be accessed from anywhere in the program. The fact that it is static means that it cannot be edited.
    public static Board board;

    public static void main(String[] args) {
        // TODO Auto-generated method stub

    //Creates an object board from the Board() construct
    board = new Board();

    }


}

Board Class 董事会班

package snake;

//Importing allows us to use pre-defined classes in Java, this contains its methods. We can also import entire packages which contain a number of classes in that package.
//This class allows us to assign/capture the width and height of an object.

import java.awt.Dimension;
//The Toolkit is an abstract class containing abstract and (possibly) non-abstract methods. Abstract classes cannot be instantiated (i.e. we cannot make an object from them). Abstract methods have no body (no code), for example we declare it as "public abstract boolean isChanged() ;", the semi colon shows it has no body (i.e. no {}).
import java.awt.Toolkit;

//ActionEvent gets information about an event (input) and its source. You can create an object from this.
import java.awt.event.ActionEvent;
//The ActionListener defines what should be done when a certain action is performed by the user.
import java.awt.event.ActionListener;



//This imports the JFrame class from the swing package.
import javax.swing.JFrame;
import javax.swing.Timer;

//This class is used to create the game board.
//The ActionListener is implemented because it is implementing an interface. What ActionListener does is it handles events; the ActionListener defines what should be done when a certain action is performed by the user.
public class Board implements ActionListener {

    //The JFrame is the window in which everything will be placed into, this will provide the framed window (what is visible to us) in which the game will run in. We are creating a variable frame of type JFrame.
    public JFrame frame;
    //Creating a variable drawBoard of type DrawBoard. This allows us to add the component of drawBoard to the Board.
    public DrawBoard drawBoard;
    //Defining a new Timer called ticker. This is using the form  new Timer(int delay in milliseconds, ActionListener listener).  What the timer does is it allows threads to schedule the execution of instructions. In this case to constantly refresh the drawBoard component at regular intervals. This will give the appearance of motion. What "this" does is it is in reference to the current instance, 
    public Timer ticker = new Timer(20, this);


    //This is a constructor for the class Board. This will allow us to create an object.
    public Board() {
        //Making an instance of dimension dim and assigning it to the size of the screen.
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        //Declaring instance of the JFrame 'frame'. This JFrame is called to declare a title for this frame - "Snake".
        frame = new JFrame("Snake");
        //JFrame is initially set to invisible, so we use the setVisible method (setting it to true) to make the JFrame 'frame' visible.
        frame.setVisible(true);
        frame.setPreferredSize(new Dimension(600, 720));
        frame.getContentPane().add(drawBoard = new DrawBoard());
        frame.pack(); 
        //What this does is it places the JFrame 'frame' into the middle of the user's screen, this diminishes the issue of not all screens being the same resolution and size. This is done by setting the (x, y) position of the JPanel. For example, the x position is gained by dividing the size of the monitor by 2 and negating the size of the JPanel by 2 from that value, this places it in the middle of the screen's x axis. This is true for the y-axis too. 
        frame.setLocation((dim.width / 2) - (frame.getWidth() / 2), (dim.height / 2) - (frame.getHeight() / 2));
        //Sets the operation which will happen when the user closes the JFrame 'frame', the EXIT_ON_CLOSE exits the application using the System exit method. This means that when the JFrame is closed, the application will be exited (closed).
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Starts the timer, this starts is sending action events to its listeners.
        ticker.start();
    }


    //Overriding the actionPerformed method from the ActionListener class.
    @Override
    //This is the actionPerformed method. We parse it the ActionEvent e, what this is is an object which gives information about the event and its source. This allows us to perform an action based upon a specific event (e.g. a keyboard key pressed).
    public void actionPerformed(ActionEvent e) {
        //This repaints this component for every tick
        //drawBoard.repaint();
    }
}

DrawBoard Class 抽屉板类

package snake;

//Allows use of default sRGB colours.
import java.awt.Color;
//Graphics is an abstract class that allows us to draw onto components.
import java.awt.Graphics;

import javax.swing.JPanel;

//Warnings will not be thrown (are suppressed).
@SuppressWarnings("serial")

//This class is used to create the board component in which the snake can move on.
//What extending does is it allows us to inherit the methods and attributes (properties) of another class. In this case, the DrawBoard class (subclass - inherits state and behaviour from all of its ancestors) inherits properties from the JPanel class (superclass - gives properties to its subclasses).
public class DrawBoard extends JPanel{

    //Declaring the colour 'yellow' as the hex colour code (turned to decimal using a hex calculator so Java can use it) which was chosen in the design stage.
    public static Color yellow = new Color(13816442);

    //We are overriding the protected method in order to define our own body (and properties) for the paintComponent method. Overriding this allows us to define how we will paint the component DrawBoard. Protected means that it can only be accessed by things within the same package.
    @Override
    //A component is an object which has a graphical representation that can interact with the user (e.g. buttons).
    //What this does is it paints the component using the graphics class, defined as instance g.
    protected void paintComponent(Graphics g) {
        //'Super.' refers to the method calling its super class, which in this case is JPanel. Doing this allows me to use in built 'drawings' such as rectangle and oval, which can be drawn by calling their methods.
        super.paintComponent(g);
        //Setting the colour in which graphics objects are made to the colour defined in the colour 'yellow'
        g.setColor(yellow);
        //Filling in a rectangle which starts at the point (0, 120) - [this is from the top left of the screen, with (0, 120) referring to 120 pixels down] and has a width and height of (600, 600), in other words provides a background of colour 'yellow' defined.
        g.fillRect(0, 120, 600, 600);
    }

}

Regarding: 关于:

How to Get JPanel to Fit Snugly With It's Components? 如何使JPanel与其组件紧密配合?

Let the layout managers do this work for you. 让布局经理为您完成这项工作。

Suggestions: 意见建议:

  • Don't set sizes or preferred sizes. 不要设置尺寸或首选尺寸。
  • Instead let the component's preferred size and your layout managers do the sizing for you. 而是让组件的首选大小和布局管理器为您确定大小。
  • If you do need to actively have a hand in setting some sizes, override getPreferredSize() and return an appropriate dimension, but do so taking care not to upset the preferred size of the constituent components. 如果确实需要积极地设置一些尺寸,请重写getPreferredSize()并返回适当的尺寸,但要注意不要破坏组成组件的首选尺寸。 This must be done with care. 这必须谨慎进行。
  • Re " I have set the dimensions for the JFrame to 600x720 and the board component as being 600x600. However, when I extend the JFrame I can see that there is more of the component to be revealed." 关于" I have set the dimensions for the JFrame to 600x720 and the board component as being 600x600. However, when I extend the JFrame I can see that there is more of the component to be revealed." -- You're forgetting the size of the top bar of the JFrame, something that may change size depending on the look and feel. -您忘记了JFrame顶部栏的大小,这可能会根据外观而改变大小。 Again, don't set the JFrame's size, and this will be a moot point. 同样,不要设置JFrame的大小,这将是一个有争议的问题。
  • To center a JFrame, simply call frame.setLocationRelativeTo(null); 要居中JFrame,只需调用frame.setLocationRelativeTo(null); after it has been packed. 包装好之后。
  • Avoid over-use of comments as these make your code nearly unreadable. 避免过多使用注释,因为这些注释会使您的代码几乎不可读。
  • If you have problems and need help with an error such as you mention here: "I have to set the JFrame as non resizable, however, an error is thrown up when I enter in frame.setResizable(false);" 如果遇到问题并需要帮助,例如您在这里提到的错误: "I have to set the JFrame as non resizable, however, an error is thrown up when I enter in frame.setResizable(false);" , then show the offending code and the error message. ,然后显示有问题的代码和错误消息。
  • Don't call frame.setVisible(true); 不要调用frame.setVisible(true); until all components have been added and the JFrame has been packed. 直到添加了所有组件并且打包了JFrame。

For example 例如

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.*;
import javax.swing.*;

public class Game {
   public static Board board;

   public static void main(String[] args) {
      board = new Board();
   }
}

class Board implements ActionListener {
   public JFrame frame;
   public DrawBoard drawBoard;
   public Timer ticker = new Timer(20, this);

   public Board() {
      frame = new JFrame("Snake");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      // frame.setPreferredSize(new Dimension(600, 720));
      frame.getContentPane().add(drawBoard = new DrawBoard(), BorderLayout.CENTER);
      frame.getContentPane().add(new BottomComponent(), BorderLayout.PAGE_END);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
      ticker.start();
   }

   @Override
   public void actionPerformed(ActionEvent e) {
   }
}

class DrawBoard extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = PREF_W;
   public static Color yellow = new Color(13816442);

   public DrawBoard() {
      setBorder(BorderFactory.createTitledBorder("Draw Board"));
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(yellow);
      g.fillRect(0, 120, 600, 600);
   }
}

class BottomComponent extends JPanel {
   private static final int PREF_W = 600;
   private static final int PREF_H = 120;

   public BottomComponent() {
      setBorder(BorderFactory.createTitledBorder("Bottom Component"));
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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