简体   繁体   English

类层次结构,使JTextField输入启动方法调用

[英]Class hierarchy to have JTextField input initiate method calls

My group and I are having some issues with a project topic we chose. 我和我的小组在选择的项目主题方面遇到了一些问题。 In editing our program, I made a bit of a mess and we aren't sure how classes should communicate with one another exactly in terms of best practice or seeing the output we want. 在编辑程序时,我有些混乱,我们不确定类如何按照最佳实践或希望获得的输出准确地相互通信。

Our issue at the moment is trying to have input from a JTextField (either n,w,s,e for directions) then act as a parameter to the keyPressed method (which takes a string), to then call the appropriate move method (taking int values for the row and column of our array/maze) and move the character square in our maze. 目前,我们的问题是尝试从JTextField输入(用于方向的n,w,s,e),然后作为ke​​yPressed方法(采用字符串)的参数,然后调用适当的move方法(数组/迷宫的行和列的整数值),然后在迷宫中移动字符正方形。 We'd like the input from direction (JTextField object in the TextPanel class) act as a parameter to both the keyPressed method where it will take the string of n, w, s, e; 我们希望来自方向的输入(TextPanel类中的JTextField对象)同时充当keyPressed方法的参数,该方法将采用n,w,s,e字符串; and then ideally 然后理想地

We initially started by having all our logic without a GUI in one class, which would allow us to traverse the maze, so the issue is our GUI knowledge and how to properly increment our programming to test along the way. 最初,我们将所有没有GUI的逻辑都放在一个类中,这将使我们能够穿越迷宫,因此问题在于我们的GUI知识以及如何适当地增加编程以进行测试。

Realize this is a fairly vague question, but looking for any insight on how to better organize this program to have the JTextField input invoke the other two methods. 意识到这是一个相当模糊的问题,但是正在寻找有关如何更好地组织该程序以使JTextField输入调用其他两种方法的任何见解。

Sample code: 样例代码:

package Project;

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

//Creates a Maze Driver object, which adds a Dungeon and TextPanel 

public class MazeDriver 
{
 public static void main(String[] args)
 {
    MazeDriver mazeDriver = new MazeDriver();   
 }

public MazeDriver(){  
    JFrame frame = new JFrame();
    frame.setTitle("Maze Game");
    frame.add(new Dungeon());
    frame.setSize(180, 200);
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    TextPanel panel = new TextPanel();
    panel.setBackground (Color.white);
    panel.setPreferredSize (new Dimension (800, 400));    

    frame.getContentPane().add(panel);
    frame.pack();              
 }               
}

package Project;

//Creates the maze to be traversed 

public class Maze {
    private int[][] grid; 

    public Maze()
    {
        grid = new int[][]  { {0, 1, 0, 0, 0},
                              {0, 1, 0, 1, 0},
                              {0, 1, 0, 1, 0},
                              {0, 1, 0, 1, 0},
                              {0, 0, 0, 1, 2} };
    }

    public int[][] getGrid(){
        return grid;
    } 
}

package Project;

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

public class Dungeon extends JPanel
{
    private Image grass, wall, boss;
    private Maze m;
    private Player p;

    public Dungeon()
    {
        m = new Maze();
        p = new Player();

        ImageIcon img = new ImageIcon("grass.png");
        grass = img.getImage();

        img = new ImageIcon("wall.png");
        wall = img.getImage();

        img = new ImageIcon("boss.png");
        boss = img.getImage();

    }



    @Override
    public void paint(Graphics g)
    {
        super.paint(g);

        //for the dimensions of the maze array

        for(int x = 0; x < m.getGrid().length; x++)
        {
            for(int y = 0; y < m.getGrid()[x].length ;y++)
            {

               //if 2 meaning the boss square; 1 meaning a wall, 
                //0 meaning grass/maze path - draw the appropriate tile

               if(m.getGrid()[y][x] == 2) 
                   g.drawImage(boss, x*32, y*32, null);
               if(m.getGrid()[y][x] == 1)
                   g.drawImage(wall, x*32, y*32, null);
               if(m.getGrid()[y][x] == 0)
                   g.drawImage(grass, x*32, y*32, null);
            }
            g.drawImage(p.getPlayer(), p.getTileX()*32, p.getTileY()*32, null);
        }
    }

//public class Movement //implements ActionListener 
//{

        public int moveNorth(int row, int column){

        //if not falling off maze upwards

        if (row > 0)

          //if tile above is not a wall (1 value in array)  
        { if(m.getGrid()[row-1][column] != 1)
          {
            p.move(0, -1); 
          } else
            {
                System.out.println("You've hit a wall."); 
            }
        } else
          {
            System.out.println("You've hit a wall.");
          }
        return row;
        }

        //if not falling off maze downwards
        public int moveSouth(int row, int column){
            if (row < m.getGrid().length-1)
                //if tile below is not a wall (1 value in array)  
            { if(m.getGrid()[row+1][column] != 1)
              {
                p.move(0, 1);
              } else
                {
                    System.out.println("You've hit a wall.");
                }
            } else
              {
                System.out.println("You've hit a wall.");
              }
            return row;
        }

        //if not falling off maze to right
        public int moveEast(int row, int column){
            if (column < m.getGrid()[row].length-1)
                //if tile to right is not a wall (1 value in array)  
            { if(m.getGrid()[row][column+1] != 1)
              {
                p.move(1, 0);
              } else
                {
                    System.out.println("You've hit a wall.");
                }
            } else
              {
                System.out.println("You've hit a wall.");
              }
            return column;
        }

        //if not falling off maze to left
        public int moveWest(int row, int column){
            if (column > 0)
                //if tile to left is not a wall (1 value in array)  
            { if(m.getGrid()[row][column-1] != 1)
              {
                p.move(-1, 0);
              } else
                {
                    System.out.println("You've hit a wall.");
                }
            } else
              {
                System.out.println("You've hit a wall.");
              }
            return column;
        }

        public void keyPressed(String temp){
            Scanner scan = new Scanner(System.in);
            int row = 0, column = 0;

            while ((row != m.getGrid().length-1) || 
                    (column != m.getGrid()[0].length-1))
            {   
                temp = scan.nextLine();
                if(temp.equals("n"))
                    row = moveNorth(row, column);
                if(temp.equals("e"))
                    column = moveEast(row, column);
                if(temp.equals("s"))
                    row = moveSouth(row, column);
                if(temp.equals("w"))
                    column = moveWest(row, column);
                else
                    //TO DO: implement into GUI text field
                    System.out.println("Invalid Direction"); 
            }
        }
        /*
        @Override
        public void actionPerformed (ActionEvent e){
            Object source = e.getSource();
            if (source == 
        }
        */
//}
}
package Project;

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

public class TextPanel extends JPanel {

    //private Dungeon d;

    private JLabel directionLabel; //shows instructions for movement
    private JLabel resultLabel; //shows user input after direction is entered
    private JTextField direction; //allows direction to be entered

    //private JLabel healthLabel, potionsLabel;


    public JTextField getDirection(){
        return direction;
    }

    public TextPanel()
    {
      directionLabel = new JLabel 
            ("Enter n for north, e for east, s for south, and w for west.");
      resultLabel = new JLabel ("---");

      //healthLabel = new JLabel ("Health Points: ");
      //potionsLabel = new JLabel ("Potions Remaining: ");

      direction = new JTextField (5);
      direction.addActionListener (new TempListener());
      add (directionLabel);
      add (direction);
      add (resultLabel);
      //add (healthLabel);
      //add (potionsLabel);

    }


//stores user input for direction
private class TempListener implements ActionListener {

      @Override
      public void actionPerformed (ActionEvent e)
      {
         String directionGiven;
         directionGiven = direction.getText();

         resultLabel.setText ("You moved: " + directionGiven);

        //d.keyPressed(directionGiven);
      }
   }

}

Pass a reference of Dungeon to TextPanel Dungeon的引用传递给TextPanel

public class TextPanel extends JPanel {

    private Dungeon d;
    //...    
    public TextPanel(Dungeon d)
    {
        this.d = d;

This way, you can call the methods of Dungeon when you need to. 这样,您可以在需要时调用Dungeon的方法。 Personally, I prefer to use an interface as it limits exactly what TextPanel can do, but for simplicity, this will work. 就个人而言,我更喜欢使用一个interface因为它完全限制了TextPanel可以执行的操作,但是为了简单起见,这将起作用。

You'll need to restructure your MazeDriver 's constructor slightly as well... 您还需要稍微重构MazeDriver的构造函数。

public class MazeDriver 
{
    public MazeDriver(){  
        Dungeon dungeon = new Dungeon();

        JFrame frame = new JFrame();
        frame.setTitle("Maze Game");
        frame.add(dungeon);
        frame.setLocationRelativeTo(null); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        TextPanel panel = new TextPanel(dungeon);
        panel.setBackground (Color.white);
        panel.setPreferredSize (new Dimension (800, 400));    

        frame.getContentPane().add(panel, BorderLayout.NORTH);
        frame.setVisible(true);
        frame.pack();              
    }               
}

The simplest solution is to pass references in the constructor to the objects which needed to be invoked. 最简单的解决方案是将构造函数中的引用传递给需要调用的对象。 For Example: 例如:

//stores user input for direction
private class TempListener implements ActionListener {

  private MazeDriver driver;
  public TempListner(MazeDriver driver) {
      this.driver = driver;

  @Override
  public void actionPerformed (ActionEvent e)
  {
     String directionGiven;
     directionGiven = direction.getText();

     resultLabel.setText ("You moved: " + directionGiven);

    driver.keyPressed(directionGiven);
  }
}

As a general solution, I would make separate classes for the logic (sometimes called business logic) and the user interface. 作为通用解决方案,我将为逻辑(有时称为业务逻辑)和用户界面创建单独的类。 This separated responsibility will make the code easier to understand and maintain. 职责分立将使代码更易于理解和维护。

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

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