JPanel定位不正确

时间:2014-05-04 11:24:29

标签: java image swing jpanel jlabel

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

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

我希望我没有错过任何重要的事情,并且感谢我能得到的所有帮助,因为我现在陷入困境。

聚苯乙烯。对不起英文和格式错误。

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();

}

1 个答案:

答案 0 :(得分:0)

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

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

Guessing Game 1

Guessing Game 2

我使用model / view / controller pattern来编写项目代码。这分散了顾虑,使得一次只关注项目的一个部分变得更容易。

以下是我使用过的图片。

Background Image

Victory Image

这是Eclipse的Package Explorer,显示了Java Swing项目的组织。

Eclipse Package Explorer

这是代码。我写了一个模型类和4个视图类。控制器是其中一个视图类中的匿名类。

这是GuessingGame的主要课程。

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());
    }

}

短而甜蜜。这堂课做了3件事。

  1. 通过调用SwingUtilities invokeLater方法将Swing GUI放在Event Dispatch thread(EDT)上。
  2. 实例化GUI模型。
  3. 实例化GUI JFrame。
  4. 接下来,让我们看一下模型类

    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;
        }
    }
    

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

    现在,让我们来看看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;
    
    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);
        }
    
    }
    

    相当标准的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;
    
    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;
        }
    
    }
    

    此类从放置在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;
    
    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);
            }
        }
    }
    

    我们扩展了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;
    
        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;
        }
    
    }
    

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

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

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