簡體   English   中英

JPanel 未在 JFrame 中顯示,但 JFrame 仍會更改大小

[英]JPanel not showing in JFrame, but JFrame still changes size

我不知道我做了什么,或者出了什么問題,但是我在最后一段時間所做的更改使我的 JPanel 完全不可見。 JFrame 它嵌套在它的大小仍然變化以容納它,我仍然可以切換 combobox 中的內容。

絕望中,我嘗試用一個按鈕替換 SnakeSettingsPanel class 的內容,但同樣的事情發生了——完全不可見,但我仍然可以與之交互。 我想這可能是一個計算機錯誤,所以我嘗試重新啟動,但仍然沒有。 當我嘗試在 JPanel 外部的框架中添加一個按鈕時,它工作得很好。 我究竟做錯了什么?

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class SnakeSettingsPanel extends JPanel {
    public boolean quit = false;
    public boolean play = false;
    public int width = 20;
    public int height = 15;
    public Speed speed = Speed.SLOW;

    public JTextField wField;
    public JTextField hField;
    public JComboBox<Speed> sField;

    public static void main(String[] args) {
        JFrame jf = new JFrame();
        jf.setTitle("Snake");
        SnakeSettingsPanel settings = new SnakeSettingsPanel();
        jf.add(settings);
        jf.pack();
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public SnakeSettingsPanel() {
        setLayout(new GridBagLayout());

        // @author Create our labels.
        JLabel wLabel = new JLabel("Width:");
        JLabel hLabel = new JLabel("Height:");
        JLabel sLabel = new JLabel("Speed:");
        
        GridBagConstraints p = new GridBagConstraints();
            p.gridx = 0;
            p.gridy = 0;
            p.insets = new Insets(10, 10, 10, 10);

        // @author Create the buttons, and add listeners
        JButton y = new JButton("Play");
        JButton n = new JButton("Quit");
        y.addActionListener(new PlayListener());
        n.addActionListener(new QuitListener());

        // @author Create text fields for height/width
        wField = new JTextField(15);
        wField.setText("20");
        hField = new JTextField(15);
        hField.setText("15");

        // @author Creates a combobox for selecting speed.
        Speed[] speeds = {Speed.SLOW, Speed.MEDIUM, Speed.FAST};
        sField = new JComboBox<Speed>(speeds);

        // @author Stitch everything into the panel.
        add(wLabel, p);
        p.gridx = 1;
        add(wField, p);
        p.gridx = 0;
        p.gridy = 1;
        add(hLabel, p);
        p.gridx = 1;
        add(hField, p);
        p.gridx = 0;
        p.gridy = 2;
        add(sLabel, p);
        p.gridx = 1;
        add(sField, p);
        p.gridx = 0;
        p.gridy = 3;
        add(y, p);
        p.gridx = 1;
        add(n, p);

        setVisible(true);
    }

    public boolean getPlay() {
        return play;
    }

    public boolean getQuit() {
        return quit;
    }

    // @author Returns all settings as a SnakeSettings object
    public SnakeSettings getSettings() {
        return new SnakeSettings(width, height, speed);
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public Speed getSpeed() {
        return speed;
    }

    // @author Sends out the word to start a new game.
    public class PlayListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            quit = false;
            play = true;
            width = Integer.parseInt(wField.getText());
            height = Integer.parseInt(hField.getText());
            speed = (Speed) sField.getSelectedItem();
        }
    }

    // @author Sends out the word to shut down the program.
    public class QuitListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            quit = true;
            play = false;
        }       
    }
}

讓這成為您應該避免將 Model(您的應用程序的數據)與 View(如何顯示)混合的教訓。 您的SnakeSettingsPanel目前是兩者。

  • 作為 Model,它包含 3 個重要字段: widthheightspeed
  • 作為 View,它是一個完整的 JPanel。 JPanel 有很多字段,您應該避免直接接觸這些字段。 包括widthheight ,通常通過getHeightgetWidth訪問——您將使用始終返回相同內置值 20 和 15 的版本覆蓋它們(直到用戶通過他們看不到的 UI 更改這些值)。

快速解決方法是重命名您當前的getWidth()getHeight()以避免與父 JPanel class 的內置getWidth()getHeight()方法發生沖突。 打電話給他們getMyWidth()getMyHeight() ,突然一切正常。

更好的解決方法是完全刪除這些字段和方法,並將您自己的 model 屬性存儲在SnakeSettings屬性中。 當用戶點擊播放時更新它,並在通過getSettings()請求時返回它。 為您減少代碼,減少與您的父JPanel class 發生意外名稱沖突的可能性。 這看起來像:

    // SnakeSettingsPanel, before
    public int width = 20;
    public int height = 15;
    public Speed speed = Speed.SLOW;

    public int getWidth() {    // <-- clashes with superclass
        return width;
    }
    public int getHeight() {   // <-- clashes with superclass
        return height;
    }
    public Speed getSpeed() {
        return speed;
    }
    public SnakeSettings getSettings() {
        return new SnakeSettings(width, height, speed);
    }

    // SnakeSettingsPanel, after
    SnakeSettings settings = new SnakeSettings();

    public SnakeSettings getSettings() {
        return settings;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM