刽子手游戏背景图像不高效?

时间:2013-12-22 18:50:53

标签: swing jframe jpanel jlabel

我正在制作一个Hangman游戏,似乎我的代码并没有为我提供使用布局的自由。我在我的JFrame中添加了一个图像,然后我在我的图像中添加了一个JPanel,我用于所有JLabel和JTextFields,但在我看来它效率低,因为为了改变我的JTextFields或JLabel的布局,我必须改变我的图像布局混淆了整个游戏的外观。如何让这段代码更有效率,让自己更自由地更改JLabel和JTextFields的布局而不会搞砸一切?感谢先进的帮助。

 /*PACKAGE DECLARATION*/
    package Game;

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


    /************************
     * GAME MECHANICS CLASS *
     * **********************/
    public class GameStructure {

        /* INSTANCE DECLARATIONS */
        private String []wordList = {"computer","java","activity","alaska","appearance","article",
               "automobile","basket","birthday","canada","central","character","chicken","chosen",
               "cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
               "establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
               "hurried","identity","importance","impossible","invented","italian","journey","lincoln",
               "london","massage","minerals","outer","paint","particles","personal","physical","progress",
               "quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
               "strike","successful","sudden","terrible","traffic","unusual","volume","yesterday"};
        private int []length = new int [64];
        private JTextField tf;//text field instance variable (used)
        private JLabel jl2;//label instance variable (used)
        private JLabel jl3;//label instance (working on)
        private String letter;


        /*****************
         * LENGTH METHOD *
         * ***************/
        public void length(){

            jl3 = new JLabel();

            int j = 0;
            for(j = 0; j<64; j++) {

                length[j] = wordList[j].length();//gets length of words in wordList
            }//end for

            int l = 0;
            String line = "";
            //create line first then put into .setText
            for(int m = 0; m<length[l]; m++) {

                line += "__ ";
                l++;
            }//end for
            jl3.setText(line);

            }//end length method


        /*****************
         * WINDOW METHOD *
         * ***************/
        public void window() {

        LoadImageApp i = new LoadImageApp();//calling image class

        JFrame gameFrame = new JFrame();//declaration
        JPanel jp = new JPanel();
        //JPanel jp2 = new JPanel();//jpanel for blanks
        JLabel jl = new JLabel("Enter a Letter:");//prompt with label

        jl.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font

        tf = new JTextField(1);//length of text field by character
        jl2 = new JLabel("Letters Used:    ");

        tf.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font
        jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));//set font

        jp.add(jl);//add label to panel
        jp.add(tf);//add text field to panel
        jp.add(jl2);//add letters used

        gameFrame.add(i); //adds background image to window
        i.add(jp); // adds panel containing label to background image panel

        gameFrame.setTitle("Hangman");//title of frame window
        gameFrame.setSize(850, 600);//sets size of frame
        gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit when 'x' button pressed
        gameFrame.setIconImage(new ImageIcon("Hangman-Game-grey.png").getImage());//set the frame icon to an image loaded from a file
        gameFrame.setLocationRelativeTo(null);//window centered
        gameFrame.setResizable(false);//user can not resize window
        gameFrame.setVisible(true);//display frame

      }//end window method


        /*********************
         * USER INPUT METHOD *
         * *******************/
        public void userInput() {

            tf.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {//when enter key pressed

                JTextField tf = (JTextField)e.getSource();

                letter = tf.getText();
                jl2.setText(jl2.getText() + letter + " ");//sets jlabel text to users entered letter

                }//end actionPerformed method

            });

        }//end userInput method

    }//end GameMechanics class



    /*PACKAGE DECLARATION*/
    package Game;


    /***********************
     * IMPORT DECLARATIONS *
     * *********************/
    import java.awt.BorderLayout;
    import java.awt.Graphics;
    import javax.swing.ImageIcon;
    import javax.swing.JPanel;


    /***************
     * IMAGE CLASS *
     * *************/
    public class LoadImageApp extends JPanel {

        private static final long serialVersionUID = 1L;

            private ImageIcon image;


            /***********************
             * PAINT IMAGE METHOD *
             * *********************/
            public void paintComponent (Graphics g) {

                //setLayout(new BorderLayout());

                super.paintComponent(g);
                image = new ImageIcon("hangman.png");//image name & type
                image.paintIcon(this, g, 270, 20);

            }//end paintComponent method

    }//end LoadImageApp class

    /*PACKAGE DECLARATION*/
    package Game;


    /*******************
     * GAME MAIN CLASS *
     * *****************/
    public class GameMain {


        /***************
         * MAIN METHOD *
         * *************/
        public static void main (String []args) {

            GameStructure game = new GameStructure();//declaration
            game.length();
            game.window();
            game.userInput();

        }//end main method

    }//end GameMain class

1 个答案:

答案 0 :(得分:2)

一些建议:

  • 不要覆盖JPanel的paint(...)方法,而是覆盖其paintComponent(Graphics g)方法,除非您需要更改其子组件或其边框的渲染方式(您不需要)。通过这样做,您可以获得一些Swing图形优势,包括自动双缓冲。
  • 切勿将图片读入paintpaintComponent方法。这些方法是GUI对用户响应的主要决定因素之一,因此您永远不想在方法中执行文件I / O.而且,为什么在调用paint或paintComponent时,代码会无效地重新读取相同的图像?为什么不简单地将图像或ImageIcon存储在变量中一次,并完成它?
  • 了解并使用布局管理器
  • 通过绘图或图像渲染JPanels的JPanels通常应该是非透明的 - 因此请务必在它们上面调用setOpaque(false),并在其他一些覆盖的Swing组件上调用它。

__ _ __ _ __ _ __ _ __ _ __ _ __ _ __ _ _

修改

例如,这是我的SSCCE,它显示了在类构造函数中获取图像(此处不在Internet上)的示例。另请注意,我的SSCCE可以在连接到互联网的任何计算机上运行,​​因为它不需要图像文件,与您的不同。此外,与显示GUI无关的代码已被删除,使得剩余代码与问题更相关。考虑下次发布SSCCE时这样做。

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.*;

class GameStructure {
   private JTextField tf;
   private JLabel jl2;

   public void window() {
      LoadImageApp loadImageApp = new LoadImageApp();
      JFrame gameFrame = new JFrame();
      JPanel jp = new JPanel();
      jp.setOpaque(false); //!!
      jp.setBorder(BorderFactory.createTitledBorder("jp"));
      JLabel jl = new JLabel("Enter a Letter:");
      jl.setFont(new Font("Rockwell", Font.PLAIN, 20));
      tf = new JTextField(1);
      jl2 = new JLabel("Letters Used:    ");
      tf.setFont(new Font("Rockwell", Font.PLAIN, 20));
      jl2.setFont(new Font("Rockwell", Font.PLAIN, 20));
      jp.add(jl);
      jp.add(tf);
      jp.add(jl2);
      gameFrame.add(loadImageApp);
      loadImageApp.add(jp);
      gameFrame.setTitle("Hangman");
      gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      // gameFrame.setIconImage(
      // new ImageIcon("Hangman-Game-grey.png").getImage());
      gameFrame.setResizable(false);
      gameFrame.pack();
      gameFrame.setLocationRelativeTo(null);
      gameFrame.setVisible(true);
   }
}

class LoadImageApp extends JPanel {
   private static final long serialVersionUID = 1L;
   private static final int PREF_W = 850;
   private static final int PREF_H = 600;
   private BufferedImage img;

   public LoadImageApp() {
      // just used as an example public image
      String spec = "https://duke.kenai.com/"
            + "SunRIP/.Midsize/SunRIP.png.png";    
      URL url;
      try {
         url = new URL(spec);
         img = ImageIO.read(url);
      } catch (MalformedURLException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      }
   }

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

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      if (img != null) {
         g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
      }
   }
}

public class GameMain {
   public static void main(String[] args) {
      GameStructure game = new GameStructure();
      game.window();
   }
}