JPanel定位不正确 [英] JPanel positioned incorrectly

查看:129
本文介绍了JPanel定位不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用Java制作了一个游戏,你应该在1-100之间猜测一个随机生成的int。如果你猜得太低,一个文本字段将填充一个文字,上面写着太低但是用瑞典语。如果你猜得太高也一样。



当答案是正确的时候会出现问题,然后我调用一个方法制作一个不可见的JPanel,可见。这样做很好,但Jpanel本身不会移动到它应该是的顶部。它需要完美贴合,因为它只是背景的照片拼图。 背景的属性为:1920 x 1080. photoshopped GG WP 的属性为1920 x 297.Jpane称为grattis



我希望我没有错过任何重要的东西,我感谢所有的帮助,因为我现在卡住了。



PS。对不起英文和格式错误。

  package slumpatal; 

import java.util.Random;

//这个类运行程序,主要方法在这里。
公共类SlumpaTal扩展了callback1 {
private int randomTal;
随机随机= new Random();

@Override
public int SetValue(int value){
if(value< randomTal)
return -1;
else if(value == randomTal)
返回0;
else
返回1;

}

//私人JFrame1帧;
SlumpaTal(){
GenerateRandomNumber();
JFrame1.createWindow(this);
}

public void GenerateRandomNumber(){
randomTal = random.nextInt(100)+ 1;
}

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

  package slumpatal; 


import java.awt。*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing。*;


公共类JFrame1 {
// public static int dittSvar;
public static void createWindow(callback1 callbackArg){

// Font font = new Font(Verdana,Font.BOLD,28);

JFrame frame = new JFrame(Gissa ett Tal mellan 1-100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JPanel contentPane = new JPanel();
contentPane.setOpaque(true);
contentPane.setBorder(BorderFactory.createMatteBorder(5,5,5,5,Color.WHITE));
contentPane.setBackground(Color.WHITE);
contentPane.setLayout(new BorderLayout(10,10));

ImagePanel imagePanel = new ImagePanel(callbackArg);


//框架属性


contentPane.add(imagePanel,BorderLayout.CENTER);
frame.setContentPane(contentPane);
frame.setSize(1000,600);
frame.setVisible(true);
}
}


类ImagePanel扩展JPanel

{
callback1回调;
public int dittSvar;
private BufferedImage图片;
JButton restartApp;
JTextField dittSvarText1;
JTextField dittRes1;
BufferedImage myPicture;
public JPanel grattis;

public ImagePanel(callback1 callbackArg){
try {
myPicture = ImageIO.read(new URL(https://imagizer.imageshack.us/v2/1375x213q90/843) /r7f8.jpg));
} catch(Exception ex){
System.err.print(No reward image);
}
callback = callbackArg;
setOpaque(true);
setBorder(BorderFactory.createLineBorder(Color.BLACK,5));
try {
image = ImageIO.read(new URL(http://imageshack.com/a/img835/193/v8k3.jpg));
}
//如果它不起作用,请写一条错误消息printStackTrace。
catch(IOException e){
System.err.printf(%s,e.toString());
e.printStackTrace();
}
createGUI();
createGUI2();

dittSvarText1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
dittSvar = Integer.parseInt(dittSvarText1.getText());
int res = callback.SetValue(dittSvar);
if(res< 0)
dittRes1.setText(Förlågt);
else if(res == 0){
dittRes1.setText(RättSvar!!!!);
makeItVisible();
} else
dittRes1.setText(FörHögt);
dittSvarText1。 setText();
}
});
restartApp.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
callback.GenerateRandomNumber();
dittSvarText1.setText(null);
dittRes1.setText(null);
grattis.setVisible(false);

}
});
}

public void makeItVisible(){
System.out.print(显示奖励图片);
grattis = new JPanel();
grattis.setOpaque(false);
grattis.setLayout(new FlowLayout(FlowLayout.LEFT));


if(myPicture!= null){
JLabel picLabel = new JLabel(new ImageIcon(myPicture));

//picLabel.setLocation(new Point(0,0));
picLabel.setLocation(new Point(0,0));
// picLabel.setSize(1000,297);
// grattis.setLocation(0,0);
picLabel.setVerticalAlignment(WIDTH);
grattis.setVisible(true);
grattis.setSize(1000,600);

grattis.add(picLabel);
add(grattis);
updateUI();
} else {
System.err.print(没有创建图片!);
}


}

public void createGUI(){
setLayout(new GridBagLayout());
JPanel panel1 = new JPanel();

panel1.setOpaque(false);
panel1.setLayout(new GridLayout(2,2,2,2));
JLabel skrivdingissning = new JLabel(Skriv dingissninghär:);
skrivdingissning.setForeground(Color.WHITE);
dittSvarText1 = new JTextField(10);
JLabel VadBlevDet =新JLabel(Vad blev det:);
VadBlevDet.setForeground(Color.WHITE);
dittRes1 = new JTextField(10);


panel1.add(skrivdingissning);
panel1.add(dittSvarText1);
panel1.add(VadBlevDet);
panel1.add(dittRes1);

add(panel1);

}

public void createGUI2(){

JPanel panel2 = new JPanel();

panel2.setLocation(100,500);
panel2.setOpaque(false);
restartApp = new JButton(Starta om);
restartApp.setLocation(100,500);
restartApp.setBackground(Color.WHITE);

panel2.add(restartApp);

// add(panel2);
}


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

@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//g.drawImage(image,0,0,this);
}
}

抽象类callback1 {
abstract int SetValue(int value);

abstract void GenerateRandomNumber();

}


解决方案

我改写了你的整个项目。您可以将英语翻译成瑞典语。



以下是游戏的几个屏幕截图。



< img src =https://i.stack.imgur.com/lzugs.jpgalt =猜猜游戏1>





我使用了(EDT)通过调用SwingUtilities invokeLater方法。

  • 实例化GUI模型。

  • 实例化GUI JFrame。

  • 接下来,让我们看一下模型类

      package com.ggl.guessing.game.model; 

    import java.util.Random;

    公共类GuessingGameModel {

    private int lowerLimit;
    private int upperLimit;
    private int randomNumber;
    private int numberOfGuesses;


    private随机随机;

    public GuessingGameModel(int lowerLimit,int upperLimit){
    this.random = new Random();
    init(lowerLimit,upperLimit);
    }

    public void init(int lowerLimit,int upperLimit){
    this.lowerLimit = lowerLimit;
    this.upperLimit = upperLimit;
    this.numberOfGuesses = 0;
    this.randomNumber = random.nextInt(upperLimit - lowerLimit + 1)
    + lowerLimit;
    }

    public int guess(int guess){
    this.numberOfGuesses ++;
    if(guess< randomNumber){
    return -1;
    }否则if(guess> randomNumber){
    返回1;
    } else {
    返回0;
    }
    }

    public int getNumberOfGuesses(){
    return numberOfGuesses;
    }

    public String getFrameTitle(){
    returnGissa ett Tal mellan+ lowerLimit + -
    + upperLimit;
    }
    }

    此课程保存游戏信息,并提供便利标题的方法。您可以在随机数上设置下限和上限,以便将来添加不同的范围。



    现在,让我们进入GUI本身。这是GuessingGameFrame类。

      package com.ggl.guessing.game.view; 

    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    import javax.swing.JFrame;
    import javax.swing.JPanel;

    import com.ggl.guessing.game.model.GuessingGameModel;

    公共类GuessingGameFrame {

    私人GameImages gameImages;

    私有GuessingGameModel模型;

    私人GuessingGamePanel ggPanel;

    私有JFrame框架;

    public GuessingGameFrame(GuessingGameModel model){
    this.model = model;
    this.gameImages = new GameImages();
    createPartControl();
    }

    private void createPartControl(){
    frame = new JFrame();
    frame.setTitle(model.getFrameTitle());
    frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    frame.addWindowListener(new WindowAdapter(){
    @Override
    public void windowClosing(WindowEvent event){
    exitProcedure();
    }
    }) ;

    尺寸d = sizeGuessesPanel();

    ggPanel = new GuessingGamePanel(this,model,gameImages,d);
    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new FlowLayout());
    mainPanel.add(ggPanel);

    frame.setLayout(new FlowLayout());
    frame.add(mainPanel);
    // frame.setSize(640,480);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
    }

    private Dimension sizeGuessesPanel(){
    GuessesPanel guessesPanel = new GuessesPanel(this,model);
    frame.setLayout(new FlowLayout());
    frame.add(guessesPanel.getPanel());
    frame.pack();
    Dimension d = guessesPanel.getPanel()。getSize();
    guessesPanel.setPreferredSize(d);
    frame.remove(guessesPanel.getPanel());
    返回d;
    }

    public void exitProcedure(){
    frame.dispose();
    System.exit(0);
    }

    public void setGuessed(boolean guessed){
    ggPanel.setGuessed(guessed);
    }

    }

    相当标准的Swing,除了sizeGuessesPanel方法。为了将面板放在背景图像的中心,我需要知道它有多大。 sizeGuessesPanel使用JFrame打包来告诉我大小。



    setGuessed方法是一种方便的方法,它允许我在JPanel上设置布尔标志来绘制胜利图像。控制器不需要知道JPanel。



    接下来,我们将看看GameImages类。

      package com.ggl.guessing.game.view; 

    import java.awt.Dimension;
    import java.awt.Image;
    import java.io.IOException;
    import java.net.URL;

    import javax.imageio.ImageIO;

    公共类GameImages {

    private Image backgroundImage;
    private Image victoryImage;

    public GameImages(){
    readBackgroundImage();
    readVictoryImage();
    }

    private void readBackgroundImage(){
    Image image = null;
    try {
    URL url = getClass()。getResource(/ v8k3reduced.jpg);
    image = ImageIO.read(url);
    } catch(IOException e){
    e.printStackTrace();
    }
    this.backgroundImage = image;
    }

    private void readVictoryImage(){
    Image image = null;
    try {
    URL url = getClass()。getResource(/ r7f8reduced.jpg);
    image = ImageIO.read(url);
    } catch(IOException e){
    e.printStackTrace();
    }
    this.victoryImage = image;
    }

    public Image getBackgroundImage(){
    return backgroundImage;
    }

    public Dimension getPreferredSize(){
    返回新维度(backgroundImage.getWidth(null),
    backgroundImage.getHeight(null));
    }

    public Image getVictoryImage(){
    return victoryImage;
    }

    }

    此类从中读取图像放置在Java构建路径中的images文件夹。这确保了可以从Eclipse读取图像,以及在Java归档文件(JAR)中打包图像
    时。



    接下来,我们我会看看GuessingGamePanel。

      package com.ggl.guessing.game.view; 

    import java.awt.Dimension;
    import java.awt.Graphics;

    import javax.swing.JPanel;

    import com.ggl.guessing.game.model.GuessingGameModel;

    公共类GuessingGamePanel扩展JPanel {

    private static final long serialVersionUID =
    -2429103448910749064L;

    私有布尔猜测;

    private Dimension guessesPanelDimension;

    私人GameImages gameImages;

    private GuessesPanel guessesPanel;

    私人GuessingGameFrame框架;

    私有GuessingGameModel模型;

    public GuessingGamePanel(GuessingGameFrame frame,
    GuessingGameModel model,GameImages gameImages,
    Dimension guessesPanelDimension){
    this.frame = frame;
    this.model = model;
    this.gameImages = gameImages;
    this.guessesPanelDimension = guessesPanelDimension;
    this.guessed = false;

    createPartControl();
    }

    private void createPartControl(){
    this.setLayout(null);
    this.setPreferredSize(gameImages.getPreferredSize());

    guessesPanel = new GuessesPanel(frame,model);
    Dimension gp = guessesPanelDimension;
    Dimension tp = gameImages.getPreferredSize();
    int x =(tp.width - gp.width)/ 2;
    int y =(tp.height - gp.height)/ 2;
    guessesPanel.getPanel()。setBounds(x,y,gp.width,gp.height);
    this.add(guessesPanel.getPanel());
    }

    public void setGuessed(boolean guessed){
    this.guessed = guessed;
    repaint();
    }

    @Override
    protected void paintComponent(Graphics g){
    super.paintComponent(g);

    g.drawImage(gameImages.getBackgroundImage(),0,0,null);
    if(guessed){
    g.drawImage(gameImages.getVictoryImage(),0,0,null);
    }
    }
    }

    我们扩展JPanel因为我们覆盖JPanel paintComponent方法。



    在createPartControl方法中,您会注意到我使用了null布局。 空布局只能在Swing专家的监督和批准下使用。在这种情况下,这是我可以控制GuessesPanel大小和位置的唯一方法。



    最后,我们将看看GuessesPanel类。

      package com.ggl.guessing .game.view; 

    import java.awt.Color;
    import java.awt.Component;
    import
    java.awt.Container;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTextField;

    import com.ggl.guessing.game.model.GuessingGameModel;

    public class GuessesPanel {

    private static final Insets finalInsets =
    new Insets(6,6,6,6);

    private Dimension preferredSize;

    私人GuessingGameFrame框架;

    私有GuessingGameModel模型;

    私人JPanel面板;

    private JTextField dittSvarText1;
    private JTextField dittRes1;
    private JTextField guessesField;

    public GuessesPanel(GuessingGameFrame frame,
    GuessingGameModel model){
    this.frame = frame;
    this.model = model;
    createPartControl();
    }

    private void createPartControl(){
    panel = new JPanel();
    panel.setBackground(Color.YELLOW);
    panel.setLayout(new FlowLayout());

    JPanel insidePanel = new JPanel();
    insidePanel.setLayout(new GridBagLayout());

    int gridy = 0;

    JLabel guessLabel = new JLabel(Skriv dingissninghär:);
    addComponent(insidePanel,guessLabel,0,gridy,1,1,
    finalInsets,GridBagConstraints.LINE_START,
    GridBagConstraints.NONE);

    dittSvarText1 = new JTextField(10);
    dittSvarText1.addActionListener(new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent event){
    int guess = Integer.valueOf(dittSvarText1.getText());
    int lowHigh = model.guess(guess);
    if(lowHigh< 0){
    dittRes1.setText(Förlågt);
    }否则if(lowHigh> 0){
    dittRes1.setText(FörHögt);
    } else {
    dittRes1.setText(RättSvar!!!!);
    frame.setGuessed( true);
    }
    guessesField.setText(Integer.toString(
    model.getNumberOfGuesses()));
    dittSvarText1.setSelectionStart(0);
    dittSvarText1.setSelectionEnd (
    dittSvarText1.getText()。length());
    }
    });
    addComponent(insidePanel,dittSvarText1,1,gridy ++,1,1,
    finalInsets,GridBagConstraints.LINE_START,
    GridBagConstraints.NONE);

    JLabel responseLabel = new JLabel(Vad blev det:);
    addComponent(insidePanel,responseLabel,0,gridy,1,1,
    finalInsets,GridBagConstraints.LINE_START,
    GridBagConstraints.NONE);

    dittRes1 = new JTextField(10);
    dittRes1.setEditable(false);
    addComponent(insidePanel,dittRes1,1,gridy ++,1,1,
    finalInsets,GridBagConstraints.LINE_START,
    GridBagConstraints.NONE);

    JLabel guessesLabel = new JLabel(猜测次数:);
    addComponent(insidePanel,guessesLabel,0,gridy,1,1,
    finalInsets,GridBagConstraints.LINE_START,
    GridBagConstraints.NONE);

    guessesField = new JTextField(10);
    guessesField.setEditable(false);
    addComponent(insidePanel,guessesField,1,gridy ++,1,1,
    finalInsets,GridBagConstraints.LINE_START,
    GridBagConstraints.NONE);

    panel.add(insidePanel);
    }

    private void addComponent(容器容器,组件组件,
    int gridx,int gridy,int gridwidth,int gridheight,
    Insets insets,int anchor,int填充){
    GridBagConstraints gbc = new GridBagConstraints(gridx,gridy,
    gridwidth,gridheight,1.0D,1.0D,anchor,fill,
    insets,0,0);
    container.add(component,gbc);
    }

    public void setPreferredSize(Dimension preferredSize){
    panel.setPreferredSize(preferredSize);
    panel.setMaximumSize(preferredSize);
    panel.setMinimumSize(preferredSize);
    this.preferredSize = preferredSize;
    }

    public Dimension getPreferredSize(){
    return preferredSize;
    }

    公共JPanel getPanel(){
    返回面板;
    }

    }

    这是一个非常标准的JPanel使用GridBagLayout。 addComponent方法为每个Swing组件创建一个GridBagConstraints。 GridBagLayout是您想要对标签和字段进行排列时使用的布局。



    主要且唯一的控制器是此类中的匿名动作侦听器类。



    我创建了比你更多的类,并以不同的方式排列代码。研究代码,看看它是否有助于您更好地理解MVC,以及如何编写Swing应用程序。


    I've made a game in Java, where you're supposed to guess a random-generated int, between 1-100. If you guess too low, a textfield will be filled with a text that says, "too low" but in Swedish. Same if you guess too high.

    The problem occurs when the answer is right, I then call a method to make an Invisible JPanel, visible. That works just fine, but the Jpanel itself won't move to the top where its supposed to be. And it needs to fit perfectly since it's just an photoshopped picture of the background. The properties of the background is: 1920 x 1080. The properties of the photoshopped GG WP is 1920 x 297. The Jpane is called "grattis"

    I hope I've hasn't missed something important and I appreciate all the help I can get, because Im stuck now.

    Ps. Sorry for the bad english and formatting.

    package slumpatal;
    
    import java.util.Random;
    
    //This class runs the program, the main method is here.
    public class SlumpaTal extends callback1 {
        private int randomTal;
        Random random = new Random();
    
        @Override
        public int SetValue(int value) {
            if (value < randomTal)
                return -1;
            else if (value == randomTal)
                return 0;
            else
                return 1;
    
        }
    
        //private JFrame1 frame;
        SlumpaTal() {
            GenerateRandomNumber();
            JFrame1.createWindow(this);
        }
    
        public void GenerateRandomNumber() {
            randomTal = random.nextInt(100) + 1;
        }
    
        public static void main(String[] args) {
            new SlumpaTal();
        }
    }
    

    .

    package slumpatal;
    
    
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    
    public class JFrame1 {
        //public  static int dittSvar;
        public static void createWindow(callback1 callbackArg) {
    
            //Font font = new Font("Verdana", Font.BOLD,28);
    
            JFrame frame = new JFrame("Gissa ett Tal mellan 1-100");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JPanel contentPane = new JPanel();
            contentPane.setOpaque(true);
            contentPane.setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5, Color.WHITE));
            contentPane.setBackground(Color.WHITE);
            contentPane.setLayout(new BorderLayout(10, 10));
    
            ImagePanel imagePanel = new ImagePanel(callbackArg);
    
    
            //frame properties
    
    
            contentPane.add(imagePanel, BorderLayout.CENTER);
            frame.setContentPane(contentPane);
            frame.setSize(1000, 600);
            frame.setVisible(true);
        }
    }
    
    
    class ImagePanel extends JPanel
    
    {
        callback1 callback;
        public int dittSvar;
        private BufferedImage image;
        JButton restartApp;
        JTextField dittSvarText1;
        JTextField dittRes1;
        BufferedImage myPicture;
        public JPanel grattis;
    
        public ImagePanel(callback1 callbackArg) {
            try {
                myPicture = ImageIO.read(new URL("https://imagizer.imageshack.us/v2/1375x213q90/843/r7f8.jpg"));
            } catch (Exception ex) {
                System.err.print("No reward image");
            }
            callback = callbackArg;
            setOpaque(true);
            setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
            try {
                image = ImageIO.read(new URL("http://imageshack.com/a/img835/193/v8k3.jpg"));
            }
            //If it doesn't work, write an error message, printStackTrace.
            catch (IOException e) {
                System.err.printf("%s", e.toString());
                e.printStackTrace();
            }
            createGUI();
            createGUI2();
    
            dittSvarText1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    dittSvar = Integer.parseInt(dittSvarText1.getText());
                    int res = callback.SetValue(dittSvar);
                    if (res < 0)
                        dittRes1.setText("För lågt");
                    else if (res == 0) {
                        dittRes1.setText("Rätt Svar!!!!");
                        makeItVisible();
                    } else
                        dittRes1.setText("För Högt");
                    dittSvarText1.setText("");
                }
            });
            restartApp.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    callback.GenerateRandomNumber();
                    dittSvarText1.setText(null);
                    dittRes1.setText(null);
                    grattis.setVisible(false);
    
                }
            });
        }
    
        public void makeItVisible() {
            System.out.print("Showing reward image");
            grattis = new JPanel();
            grattis.setOpaque(false);
            grattis.setLayout(new FlowLayout(FlowLayout.LEFT));
    
    
            if (myPicture != null) {
                JLabel picLabel = new JLabel(new ImageIcon(myPicture));
    
                //picLabel.setLocation(new Point(0,0));
                picLabel.setLocation(new Point(0, 0));
                // picLabel.setSize(1000,297);
                // grattis.setLocation(0, 0);
                picLabel.setVerticalAlignment(WIDTH);
                grattis.setVisible(true);
                grattis.setSize(1000, 600);
    
                grattis.add(picLabel);
                add(grattis);
                updateUI();
            } else {
                System.err.print("No picture created!");
            }
    
    
        }
    
        public void createGUI() {
            setLayout(new GridBagLayout());
            JPanel panel1 = new JPanel();
    
            panel1.setOpaque(false);
            panel1.setLayout(new GridLayout(2, 2, 2, 2));
            JLabel skrivdingissning = new JLabel("Skriv din gissning här : ");
            skrivdingissning.setForeground(Color.WHITE);
            dittSvarText1 = new JTextField(10);
            JLabel VadBlevDet = new JLabel("Vad blev det : ");
            VadBlevDet.setForeground(Color.WHITE);
            dittRes1 = new JTextField(10);
    
    
            panel1.add(skrivdingissning);
            panel1.add(dittSvarText1);
            panel1.add(VadBlevDet);
            panel1.add(dittRes1);
    
            add(panel1);
    
        }
    
        public void createGUI2() {
    
            JPanel panel2 = new JPanel();
    
            panel2.setLocation(100, 500);
            panel2.setOpaque(false);
            restartApp = new JButton("Starta om");
            restartApp.setLocation(100, 500);
            restartApp.setBackground(Color.WHITE);
    
            panel2.add(restartApp);
    
            // add(panel2);
        }
    
    
        @Override
        public Dimension getPreferredSize() {
            return (new Dimension(300, 300));
        }
    
        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            //g.drawImage(image, 0,0,this);
        }
    }
    
    abstract class callback1 {
        abstract int SetValue(int value);
    
        abstract void GenerateRandomNumber();
    
    }
    

    解决方案

    I rewrote your entire project. You can translate the English into Swedish.

    Here are a couple of screen shots of the game.

    I used a model / view / controller pattern to code the project. This separates concerns and makes it easier to focus on one part of the project at a time.

    Here are the images I used.

    Here's the Package Explorer from Eclipse showing the organization of the Java Swing project.

    And here's the code. I wrote one model class and 4 view classes. The controller is an anonymous class inside one of the view classes.

    This is the main GuessingGame class.

    package com.ggl.guessing.game;
    
    import javax.swing.SwingUtilities;
    
    import com.ggl.guessing.game.model.GuessingGameModel;
    import com.ggl.guessing.game.view.GuessingGameFrame;
    
    public class GuessingGame implements Runnable {
    
        @Override
        public void run() {
            new GuessingGameFrame(new GuessingGameModel(1, 100));
    
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new GuessingGame());
        }
    
    }
    

    Short and sweet. This class does 3 things.

    1. Puts the Swing GUI on the Event Dispatch thread (EDT) by calling the SwingUtilities invokeLater method.
    2. Instantiates the GUI model.
    3. Instantiates the GUI JFrame.

    Next, lets look at the model class

    package com.ggl.guessing.game.model;
    
    import java.util.Random;
    
    public class GuessingGameModel {
    
        private int lowerLimit;
        private int upperLimit;
        private int randomNumber;
        private int numberOfGuesses;
    
    
        private Random random;
    
        public GuessingGameModel(int lowerLimit, int upperLimit) {
            this.random = new Random();
            init(lowerLimit, upperLimit);
        }
    
        public void init(int lowerLimit, int upperLimit) {
            this.lowerLimit = lowerLimit;
            this.upperLimit = upperLimit;
            this.numberOfGuesses = 0;
            this.randomNumber = random.nextInt(upperLimit - lowerLimit + 1) 
                    + lowerLimit;
        }
    
        public int guess(int guess) {
            this.numberOfGuesses++;
            if (guess < randomNumber) {
                return -1;
            } else if (guess > randomNumber) {
                return 1;
            } else {
                return 0;
            }
        }
    
        public int getNumberOfGuesses() {
            return numberOfGuesses;
        }
    
        public String getFrameTitle() {
            return "Gissa ett Tal mellan " + lowerLimit + " - "
                    + upperLimit;
        }
    }
    

    This class keeps the game information, and provides a convenience method for the title. You can set the lower and upper limit on the random number, so you could add different ranges in the future.

    Now, let's get to the GUI itself. This is the GuessingGameFrame class.

    package com.ggl.guessing.game.view;
    
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    
    import com.ggl.guessing.game.model.GuessingGameModel;
    
    public class GuessingGameFrame {
    
        private GameImages gameImages;
    
        private GuessingGameModel model;
    
        private GuessingGamePanel ggPanel;
    
        private JFrame frame;
    
        public GuessingGameFrame(GuessingGameModel model) {
            this.model = model;
            this.gameImages = new GameImages();
            createPartControl();
        }
    
        private void createPartControl() {
            frame = new JFrame();
            frame.setTitle(model.getFrameTitle());
            frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent event) {
                    exitProcedure();
                }
            });
    
            Dimension d = sizeGuessesPanel();
    
            ggPanel = new GuessingGamePanel(this, model, gameImages, d);
            JPanel mainPanel = new JPanel();
            mainPanel.setLayout(new FlowLayout());
            mainPanel.add(ggPanel);
    
            frame.setLayout(new FlowLayout());
            frame.add(mainPanel);
    //      frame.setSize(640, 480);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
        private Dimension sizeGuessesPanel() {
            GuessesPanel guessesPanel = new GuessesPanel(this, model);
            frame.setLayout(new FlowLayout());
            frame.add(guessesPanel.getPanel());
            frame.pack();
            Dimension d = guessesPanel.getPanel().getSize();
            guessesPanel.setPreferredSize(d);
            frame.remove(guessesPanel.getPanel());
            return d;
        }
    
        public void exitProcedure() {
            frame.dispose();
            System.exit(0);
        }
    
        public void setGuessed(boolean guessed) {
            ggPanel.setGuessed(guessed);
        }
    
    }
    

    Pretty standard Swing, except for the sizeGuessesPanel method. In order to place the panel in the center of the background image, I need to know how big it is. The sizeGuessesPanel uses JFrame packing to tell me the size.

    The setGuessed method is a convenience method that allows me to set the boolean flag on the JPanel to draw the victory image. The controller doesn't need to know about the JPanel.

    Next, we'll look at the GameImages class.

    package com.ggl.guessing.game.view;
    
    import java.awt.Dimension;
    import java.awt.Image;
    import java.io.IOException;
    import java.net.URL;
    
    import javax.imageio.ImageIO;
    
    public class GameImages {
    
        private Image backgroundImage;
        private Image victoryImage;
    
        public GameImages() {
            readBackgroundImage();
            readVictoryImage();
        }
    
        private void readBackgroundImage() {
            Image image = null;
            try {
                URL url = getClass().getResource("/v8k3reduced.jpg");
                image = ImageIO.read(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.backgroundImage = image;
        }
    
        private void readVictoryImage() {
            Image image = null;
            try {
                URL url = getClass().getResource("/r7f8reduced.jpg");
                image = ImageIO.read(url);
            } catch (IOException e) {
                e.printStackTrace();
            }
            this.victoryImage = image;
        }
    
        public Image getBackgroundImage() {
            return backgroundImage;
        }
    
        public Dimension getPreferredSize() {
            return new Dimension(backgroundImage.getWidth(null),
                    backgroundImage.getHeight(null));
        }
    
        public Image getVictoryImage() {
            return victoryImage;
        }
    
    }
    

    This class reads the images from an images folder that's placed in the Java build path. This ensures that the images can be read from Eclipse as well as when the images are packaged inside of a Java archive file (JAR).

    Next, we'll look at the GuessingGamePanel.

    package com.ggl.guessing.game.view;
    
    import java.awt.Dimension;
    import java.awt.Graphics;
    
    import javax.swing.JPanel;
    
    import com.ggl.guessing.game.model.GuessingGameModel;
    
    public class GuessingGamePanel extends JPanel {
    
        private static final long   serialVersionUID    = 
                -2429103448910749064L;
    
        private boolean guessed;
    
        private Dimension guessesPanelDimension;
    
        private GameImages gameImages;
    
        private GuessesPanel guessesPanel;
    
        private GuessingGameFrame frame;
    
        private GuessingGameModel model;
    
        public GuessingGamePanel(GuessingGameFrame frame,
                GuessingGameModel model, GameImages gameImages, 
                Dimension guessesPanelDimension) {
            this.frame = frame;
            this.model = model;
            this.gameImages = gameImages;
            this.guessesPanelDimension = guessesPanelDimension;
            this.guessed = false;
    
            createPartControl();
        }
    
        private void createPartControl() {
            this.setLayout(null);
            this.setPreferredSize(gameImages.getPreferredSize());
    
            guessesPanel = new GuessesPanel(frame, model);
            Dimension gp = guessesPanelDimension;
            Dimension tp = gameImages.getPreferredSize();
            int x = (tp.width - gp.width) / 2;
            int y = (tp.height - gp.height) / 2;
            guessesPanel.getPanel().setBounds(x, y, gp.width, gp.height);
            this.add(guessesPanel.getPanel());
        }
    
        public void setGuessed(boolean guessed) {
            this.guessed = guessed;
            repaint();
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
    
            g.drawImage(gameImages.getBackgroundImage(), 0, 0, null);
            if (guessed) {
                g.drawImage(gameImages.getVictoryImage(), 0, 0, null);
            }
        }
    }
    

    We extend a JPanel because we override the JPanel paintComponent method.

    In the createPartControl method, you'll notice that I use a null layout. A null layout should only be used with the supervision and approval of a Swing expert. In this case, it was the only way I could control the size and position of the GuessesPanel.

    Finally, we'll look at the GuessesPanel class.

    package com.ggl.guessing.game.view;
    
    import java.awt.Color;
    import java.awt.Component;
    import
     java.awt.Container;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    
    import com.ggl.guessing.game.model.GuessingGameModel;
    
    public class GuessesPanel {
    
        private static final Insets finalInsets = 
                new Insets(6, 6, 6, 6);
    
        private Dimension preferredSize;
    
        private GuessingGameFrame frame;
    
        private GuessingGameModel model;
    
        private JPanel panel;
    
        private JTextField dittSvarText1;
        private JTextField dittRes1;
        private JTextField guessesField;
    
        public GuessesPanel(GuessingGameFrame frame,
                GuessingGameModel model) {
            this.frame = frame;
            this.model = model;
            createPartControl();
        }
    
        private void createPartControl() {
            panel = new JPanel();
            panel.setBackground(Color.YELLOW);
            panel.setLayout(new FlowLayout());
    
            JPanel insidePanel = new JPanel();
            insidePanel.setLayout(new GridBagLayout());
    
            int gridy = 0;
    
            JLabel guessLabel = new JLabel("Skriv din gissning här:");
            addComponent(insidePanel, guessLabel, 0, gridy, 1, 1,
                    finalInsets, GridBagConstraints.LINE_START,
                    GridBagConstraints.NONE);
    
            dittSvarText1 = new JTextField(10);
            dittSvarText1.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent event) {
                    int guess = Integer.valueOf(dittSvarText1.getText());
                    int lowHigh = model.guess(guess);
                    if (lowHigh < 0) {
                        dittRes1.setText("För lågt");
                    } else if (lowHigh > 0) {
                        dittRes1.setText("För Högt");
                    } else {
                        dittRes1.setText("Rätt Svar!!!!");
                        frame.setGuessed(true);
                    }
                    guessesField.setText(Integer.toString(
                            model.getNumberOfGuesses()));
                    dittSvarText1.setSelectionStart(0);
                    dittSvarText1.setSelectionEnd(
                            dittSvarText1.getText().length());
                }   
            });
            addComponent(insidePanel, dittSvarText1, 1, gridy++, 1, 1,
                    finalInsets, GridBagConstraints.LINE_START,
                    GridBagConstraints.NONE);
    
            JLabel responseLabel = new JLabel("Vad blev det:");
            addComponent(insidePanel, responseLabel, 0, gridy, 1, 1,
                    finalInsets, GridBagConstraints.LINE_START,
                    GridBagConstraints.NONE);
    
            dittRes1 = new JTextField(10);
            dittRes1.setEditable(false);
            addComponent(insidePanel, dittRes1, 1, gridy++, 1, 1,
                    finalInsets, GridBagConstraints.LINE_START,
                    GridBagConstraints.NONE);
    
            JLabel guessesLabel = new JLabel("Number of guesses:");
            addComponent(insidePanel, guessesLabel, 0, gridy, 1, 1,
                    finalInsets, GridBagConstraints.LINE_START,
                    GridBagConstraints.NONE);
    
            guessesField = new JTextField(10);
            guessesField.setEditable(false);
            addComponent(insidePanel, guessesField, 1, gridy++, 1, 1,
                    finalInsets, GridBagConstraints.LINE_START,
                    GridBagConstraints.NONE);
    
            panel.add(insidePanel);
        }
    
        private void addComponent(Container container, Component component,
                int gridx, int gridy, int gridwidth, int gridheight, 
                Insets insets, int anchor, int fill) {
            GridBagConstraints gbc = new GridBagConstraints(gridx, gridy,
                    gridwidth, gridheight, 1.0D, 1.0D, anchor, fill, 
                    insets, 0, 0);
            container.add(component, gbc);
        }
    
        public void setPreferredSize(Dimension preferredSize) {
            panel.setPreferredSize(preferredSize);
            panel.setMaximumSize(preferredSize);
            panel.setMinimumSize(preferredSize);
            this.preferredSize = preferredSize;
        }
    
        public Dimension getPreferredSize() {
            return preferredSize;
        }
    
        public JPanel getPanel() {
            return panel;
        }
    
    }
    

    This is a pretty standard JPanel that uses a GridBagLayout. The addComponent method creates a GridBagConstraints for each Swing component. A GridBagLayout is the layout to use when you want to line up labels and fields.

    The main and only controller is an anonymous action listener class inside of this class.

    I created more classes than you did and arranged the code differently than you did. Study the code and see if it helps you to understand MVC better, as well as how to code a Swing application.

    这篇关于JPanel定位不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆