【问题标题】:Calling a recursive tree method using ActionListener使用 ActionListener 调用递归树方法
【发布时间】:2014-04-16 13:02:01
【问题描述】:

我的问题有点难以表达,但基本上这就是我想要做的:我有一个家庭作业来绘制一个递归树,用户可以选择显示的节点数量。我有一个使用递归绘制树的绘制方法,我需要程序接受来自文本字段的用户输入。我是递归新手,但我和室友设法使用 Graphics2D 绘制了一些东西,但我们无法开始弄清楚如何允许用户选择节点数量。输入字段的骨架在那里,但它没有做任何事情,因为我没有 ActionListener 并且不完全知道将什么放入 ActionListener 以允许用户输入值。任何帮助将不胜感激。谢谢!

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

public class Tree extends JPanel {

    private static final long serialVersionUID = 1L;
    private JLabel num; //tells user to enter number of nodes
    private JTextField in; //text field for user input

    public Tree() {
        num = new JLabel("Number of Branches: ");
        add(num);
        in = new JTextField(5);
        add(in);
    }

    private void draw(Graphics2D g, int n, int x, int y) {
        if (n == 0) {
            return;
        } else {
            int angle = 45;
            int length = 50;
            g.drawLine(x, y, x, y - length); // trunk
            g.setColor(Color.BLACK);
            g.rotate(Math.toRadians(-angle), x, y - length); // left
            // branch
            draw(g, n - 1, x, y - length);
            g.rotate(Math.toRadians(angle), x, y - length);
            g.rotate(Math.toRadians(angle), x, y - length); // right
            // branch
            draw(g, n - 1, x, y - length);
            g.rotate(Math.toRadians(-angle), x, y - length);
        }
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D gg = (Graphics2D) g;
        draw(gg, 3, getWidth() / 2, getHeight() / 2);
    }

    public static void main(String[] args) {
        Tree tree = new Tree();
        tree.setPreferredSize(new Dimension(500, 500));
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(tree);
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

【问题讨论】:

    标签: java swing recursion tree draw


    【解决方案1】:

    我个人会使用 MVC(模型-视图-控制器)模型来组织我的代码,保持两者之间的显示、处理和通信都是分开的。这样更容易跟踪正在发生的事情。在您的情况下,树对象是绘图、标签和按钮。但是由于您已经编写了代码,因此调整它会更容易。

    要添加一个动作监听器,您需要将用户输入注册为一个事件和一个按钮来“捕获它”。这种意义上的事件将是用户按下按钮。因此,一旦用户输入节点数并按下按钮,动作监听器就会响应此事件并执行所需的代码(绘制树)。

    我会这样做:

    • 给树对象一个可变的节点号。
    • 创建一个实现 actionListener 的类。
    • 创建一个按钮并为其分配一个 actionListener。
    • 创建对绘制树的静态引用,单击按钮后更改其节点号,并在屏幕上更新它。

    导入 java.awt.*;

    导入 javax.swing.*;

    公共类树扩展 JPanel {

    private static final long serialVersionUID = 1L;
    
    // I made all components static since you only need one copy of each
    private static JLabel num; //tells user to enter number of nodes
    private static JTextField in; //text field for user input
    private static JButton enter = new JButton("Enter");// create a button to capture event
    
    private static Tree tempTree; 
    
    private int nodeNumber;   // makes a tree's node number changeable
    
    public Tree() {
    
        this.nodeNumber = 0;
        num = new JLabel("Number of Branches: ");
        add(num);
        in = new JTextField(5);
        add(in);
        add(enter);
        add(enter);
    }
    
    
    
    private void draw(Graphics2D g, int n, int x, int y) {
        if (n == 0) {
            return;
        } else {
            int angle = 45;
            int length = 50;
            g.drawLine(x, y, x, y - length); // trunk
            g.setColor(Color.BLACK);
            g.rotate(Math.toRadians(-angle), x, y - length); // left
            // branch
            draw(g, n - 1, x, y - length);
            g.rotate(Math.toRadians(angle), x, y - length);
            g.rotate(Math.toRadians(angle), x, y - length); // right
            // branch
            draw(g, n - 1, x, y - length);
            g.rotate(Math.toRadians(-angle), x, y - length);
        }
    }
    
    // I had to overload your draw method to one in which I can change the drawing multiple times later
    private void draw(Graphics2D g, int x, int y)
    {
            int n = this.nodeNumber;
           if (n == 0) {
               return;
           } else {
               int angle = 45;
               int length = 50;
               g.drawLine(x, y, x, y - length); // trunk
               g.setColor(Color.BLACK);
               g.rotate(Math.toRadians(-angle), x, y - length); // left
               // branch
               draw(g, n - 1, x, y - length);
               g.rotate(Math.toRadians(angle), x, y - length);
               g.rotate(Math.toRadians(angle), x, y - length); // right
               // branch
               draw(g, n - 1, x, y - length);
               g.rotate(Math.toRadians(-angle), x, y - length);
           }
    }
    
    //makes a tree's node number editable
    public void setNodeNumber(int number)
    {
        this.nodeNumber = number;
    }
    
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D gg = (Graphics2D) g;
    
        //this version can change node number
        draw(gg,getWidth() / 2, getHeight() / 2);
    }
    
    public static void main(String[] args) {
    
        Tree tree = new Tree();
        tree.setPreferredSize(new Dimension(500, 500));
        JFrame frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(tree);
        frame.setSize(500, 500);
    
        // stores the currently displayed tree for later changes
        Tree.tempTree = tree;
        Listener enterListener = new Listener();
    
        Tree.enter.setActionCommand("ENTER");
        Tree.enter.addActionListener(enterListener);
    
    
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    
    
    }
    
    // refreshes tree
    public static void refreshTree()
    {
    
    
    
        int inputNumber;
    
        // checks if input is a number or not
        try
        {
            //gets input node number 
            inputNumber =  Integer.parseInt(Tree.in.getText());
    
            //sets node number 
            Tree.tempTree.setNodeNumber(inputNumber);
            // updates tree
            Tree.tempTree.updateUI();
        }
        catch(NumberFormatException e)
        {
            System.out.println(" Invalid node Number " + e);
        }
    
    
    
    }
    

    }

    您还需要一个动作监听器类:

    导入 java.awt.event.ActionEvent; 导入 java.awt.event.ActionListener;

    公共类监听器实现 ActionListener{

    @Override
    public void actionPerformed(ActionEvent event) {
        String action = event.getActionCommand();
        if(action.equals("ENTER"))
        {
    
            Tree.refreshTree();
        }
    
    
    }
    

    }

    【讨论】:

    • 非常感谢您的修复,我实现了它并且效果很好。整个过程中的 cmets 非常有意义,我什至使用了你的动作监听器类示例来编写我的另一半作业,具有讽刺意味的是,我的问题为零(它是一个使用 AudioClip 和 3 个按钮播放音频的 GUI)。再次感谢!我会投票,但我没有足够的声誉:(
    猜你喜欢
    • 2023-04-10
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 2014-03-02
    • 2021-11-07
    • 2016-03-02
    • 1970-01-01
    相关资源
    最近更新 更多