简体   繁体   English

JPanel的位置和大小变化很奇怪

[英]JPanel Location and Size changing weird

I'm about to program a little version of "Pong". 我将要编写一个小版本的“ Pong”。 But I've already got a problem with my JPanels . 但是我的JPanels已经遇到了问题。 The size of the Shields is changing pretty weird to 10 from 100. And there is no method that changes the size of it! Shields的大小从100怪异地变为10。没有方法可以改变它的大小! Also the Shields jump to the upper middle of the JPanel . Shields也跳到JPanel They aren't expect to do that. 他们不希望那样做。 Seen on the two screenshots at the ent of the post. 在帖子的两个截屏上可以看到。 (Puu.sh) (Puu.sh)

Sorry if I'm just missing something obvious, but as I said, I'm training. 抱歉,我只是缺少一些明显的东西,但是正如我所说,我正在训练。

Main with psvm() 主要与psvm()

public class Main {

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

}

Field (Frame with the Game in it) 字段(其中包含游戏的框架)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JFrame;

public class Field extends JFrame {

private Room room = new Room();

public Field() {

    this.setSize((int) (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 1.5), (int) (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 1.5));
    this.setLayout(null);
    this.setLocation((int) ((Toolkit.getDefaultToolkit().getScreenSize().getWidth() - (Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 1.5)) / 2), (int) ((Toolkit.getDefaultToolkit().getScreenSize().getHeight() - (Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 1.5)) / 2));
    this.getContentPane().setBackground(Color.GRAY);
    this.setResizable(true);
    this.setEnabled(true);
    this.setMinimumSize(new Dimension(1000, 455));
    if (getHeight() < 455) {
        this.setSize(getWidth(), 455);
    } else if (getWidth() < 1000) {
        this.setSize(1000, getHeight());
    }

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    this.add(room);

    this.setVisible(true);
    addMouseListener(this);

    this.addComponentListener(new ComponentAdapter() {
        public void componentResized(ComponentEvent evt) {
            room.updateLocation(getSize());
        }
    });


}

}

Room 房间

import javax.swing.*;
import java.awt.*;
public class Room extends JPanel {


private Shield shieldL = new Shield(0); // LEFT side
private Shield shieldR = new Shield(1); // RIGHT side

public Room() {

    this.setBackground(new Color(122, 197, 205));

    this.add(shieldL);
    this.add(shieldR);
}

public void updateLocation(Dimension d) {
    this.setSize((int) d.getWidth(), (int) (d.getHeight() - (d.getHeight() / 5)));
    this.setLocation(0, (int) (d.getHeight() / 10));
    shieldL.updateLocation(getSize());
    shieldR.updateLocation(getSize());
    this.setVisible(true);

}
}

Shield 屏蔽

import javax.swing.*;
import java.awt.*;

public class Shield extends JPanel {

private int side = 0;

public Shield(int s) { //0 = Left  |  1 = Right

    side = s;
    this.setSize(10, 100);
    this.setBackground(Color.white);

}

public void updateLocation(Dimension d) {   //Bug found here
    System.out.println(getSize());          //Bug seems not to be created here?
    int xPos;
    if (side == 0) {
        xPos = (int) (d.getWidth() / 8);
    } else {
        xPos = (int) (d.getWidth() / 8 * 7 - this.getWidth() / 2);
    }
    this.setLocation(xPos, (int) (d.getHeight() / 2 - (getHeight() / 2)));
    this.setVisible(true);
}

}

They end up like this:, switching the location at randome framesize changings. 它们最终像这样:以随机的帧大小更改切换位置。

http://puu.sh/ceyE0/ef15ee1748.png http://puu.sh/ceyE0/ef15ee1748.png

http://puu.sh/ceyFN/122174db48.png http://puu.sh/ceyFN/122174db48.png

Thanks! 谢谢! Julian :) 朱利安:)

In Shield , change the line Shield ,更改线

setSize(10, 100);

to

setPreferredSize(new Dimension(10, 100));

Do not use setSize methods, they are called internally. 不要使用setSize方法,它们是在内部调用的。

Edit: 编辑:

Try only these 2 classes: 仅尝试以下两个类:

public class Field extends JFrame {

    private Room room = new Room();

    public Field() {

        //Mock panel
        JPanel filler = new JPanel();
        filler.setOpaque(false);

        getContentPane().setBackground(Color.GRAY);
        getContentPane().add(filler, BorderLayout.PAGE_START);
        getContentPane().add(room);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(1000, 455));
        setLocationRelativeTo(null);
        pack();
        room.init();
        setVisible(true);
    }
}

public class Room extends JPanel {

    private static int leftWidth = 100;
    private static int leftHeight = 100;
    private static int leftX;
    private static int leftY;

    private static int rightWidth = 100;
    private static int rightHeight = 100;
    private static int rightX;
    private static int rightY;

    public Room() {

        setBackground(new Color(122, 197, 205));
    }

    void init() {

        leftX = getWidth() / 8;
        leftY = getHeight() / 2 - leftHeight / 2;
        rightX = getWidth() * 7 / 8;
        rightY = getHeight() / 2 - rightHeight / 2;
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.WHITE);
        g2d.fillRect(leftX, leftY, leftWidth, leftHeight);
        g2d.fillRect(rightX, rightY, rightWidth, rightHeight);
    }
}

Your problem is that you do not understand Layout Managers and how they treat or use setSize, setPreferredSize, setMinimumSize, and setMaximumSize methods. 您的问题是您不了解布局管理器以及它们如何对待或使用setSize,setPreferredSize,setMinimumSize和setMaximumSize方法。

For your panel class, setSize does not work because when you create a JPanel, it uses FlowLayout as the default layout manager and layout managers ignore size specified by the setSize method. 对于面板类,setSize不起作用,因为在创建JPanel时,它将使用FlowLayout作为默认布局管理器,并且布局管理器将忽略setSize方法指定的大小。 You must use the others in some combination (at least one). 您必须组合使用其他(至少一个)。 The only way you can use setSize is for Components that do not assign a layout manager by default OR, by invoking setLayout(null). 可以使用setSize的唯一方法是,对于默认情况下不分配布局管理器的组件,或者通过调用setLayout(null)来分配布局管理器。 This is called Absolute Positioning. 这称为绝对定位。 This is where you MUST specify the location AND size of each component. 您必须在此处指定每个组件的位置和大小。

Search the Java Swing tutorial and search for "How to use Layout Managers." 搜索Java Swing教程,并搜索“如何使用布局管理器”。 If you are using Swing, it is IMPERATIVE that you understand this concept because different Layout Managers obey different size and positioning rules. 如果使用的是Swing,则必须理解此概念,因为不同的布局管理器遵循不同的大小和定位规则。 For example, Flow Layout and Grid Layout behave very differently. 例如,“流布局”和“网格布局”的行为有很大不同。

Of course, Absolute Positioning is a pain, but it is the method that offers you absolute control of size and positioning of Swing components. 当然,绝对定位是很痛苦的,但是它是为您提供绝对控制Swing组件的尺寸和位置的方法。 But understanding Layout Managers and using them properly can save you a lot of time creating your GUI's. 但是了解布局管理器并正确使用它们可以为您节省大量创建GUI的时间。

***** UPDATED INFO ***** The problem with resizing the frame is due to the fact your panel is using FlowLayout. *****更新信息*****调整框架大小的问题是由于您的面板正在使用FlowLayout。 This layout manager allows the rearrangement of components in the panel. 该布局管理器允许重新排列面板中的组件。 There are several ways to fix this problem. 有几种方法可以解决此问题。 One is to use a layout manager that preserves the aspect ratio of the component when it is resized. 一种是使用布局管理器,该布局管理器在调整组件大小时保留组件的纵横比。 For example, GridLayout "breaks down" a component into grids. 例如,GridLayout将组件“分解”为网格。 If you think of a checker board, it is an 8x8 grid. 如果您想到棋盘格,它是一个8x8的网格。 If you make the panel a perfect square, then all grids will be squares of equal size. 如果将面板制作成一个完美的正方形,则所有网格都将是大小相等的正方形。 When you resize a panel, the aspect ratio of the panel (not necessarily the inner components), is kept. 调整面板大小时,将保留面板的纵横比(不一定是内部组件)。 Another way, and maybe your best alternative while you learn how to use layout managers properly, is to prevent resizing of the frame. 另一种方式(可能是您在学习如何正确使用布局管理器时的最佳选择)是防止调整框架的大小。

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

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