Java:监听器子类不会更改父类(super class)按钮

标签 java swing listener subclass

我潜伏了很长时间后的第一篇文章。 我正在尝试编写一个 java 程序来训练我的计算技能,因为可汗学院删除了求和、减法等永无休止的模式。

我以某种方式设法编写了框架,但当我必须实现监听器时,我陷入了困境:如果我创建一个实现 ActionListener 的类,一切都会正常。但是,当我尝试使用实现 ActionListener 的子类时,代码会中断。 我想找出原因。

我有 3 节课。

  1. 问题:生成2个随机整数

    public class Question {
    public int rand1;
    public int rand2;
        public Question (){
        rand1 = (int) (100 +(Math.random()*900)); // to be sure I have at least 3 digits. See AnswerV2.generate()
        rand2 = (int) (100 + (Math.random()*900));
        }
    

    }

  2. Answersv2:获取 2 个随机整数 从问题中求和,创建 3 个不同的答案切换 数字,添加正确答案并打乱它们。

    导入java.util.ArrayList; 导入 javax.swing.JButton; 导入 java.util.Collections;

    公开课 Answersv2 { 公共(public)ArrayList Answer_list = new ArrayList(); 公共(public) int int1; 公共(public) int int2; 字符串 uno;

    public Answersv2 (int a, int b) {
        int1 = a;
        int2 = b;
    }
    public void generate (){
        StringBuilder due = new StringBuilder();
        StringBuilder tre = new StringBuilder();
        StringBuilder quattro = new StringBuilder();
    
        uno = Integer.toString(int1+int2); // create the string version of int1+int2
        ArrayList <Character> first_answer = new ArrayList<Character>(); // create an arraylist of char to store the chars
        for (char c : uno.toCharArray()) {
        first_answer.add(c); 
        }
    
        Collections.swap(first_answer,first_answer.size()-2,first_answer.size()-1); // switch tens with units
        for (char c : first_answer) {
            due.append(c);
        }
        String dueString = due.toString();
    
        Collections.swap(first_answer,first_answer.size()-3,first_answer.size()-2); // switchs hundres with tens
        for (char c : first_answer) {
            tre.append(c);
        }
        String treString = tre.toString();
    
        Collections.swap(first_answer,first_answer.size()-2,first_answer.size()-1); // switch tens with units
        for (char c : first_answer) {
            quattro.append(c);
        }
        String quattroString = quattro.toString();
    
        add(uno,dueString,treString,quattroString);
    }
    public void add (String one,String two,String three,String four){
        Answer_list.add(one);
        Answer_list.add(two);
        Answer_list.add(three);
        Answer_list.add(four);
        shuffle();
    }
    public void shuffle() {
        Collections.shuffle(Answer_list);
    
    }
    
    public void stampa (){ // command code line version to test the program, ignore this
    System.out.println("--------------------------------");
    System.out.println(int1 + " + " + int2 + " = : ");
    System.out.println("A " + Answer_list.get(0));
    System.out.println("B " + Answer_list.get(1));
    System.out.println("C " + Answer_list.get(2));
    System.out.println("D " + Answer_list.get(3));
    }
    public class CoolButton extends JButton{
        public CoolButton(String answer) {
        setText(answer);
        }
        public boolean checkme() { // method to check if the button pressed was the one with the right answer. I still haven't implemented this properly, ignore this too
        if (getText() == uno) {
        return true;
        } else {
        return false;
        }
    }
    }
    }
    

    3 QuizV2:创建 GUI 并启动程序。

现在...我创建了 QuizV2 的 StartListener 子类,以便使按钮能够从 QuizV2 的 main 中创建的答案对象中读取 4 个答案,并使用它来 setText() 并更改标签文本等。

这是带有子类的代码 (Quizv2):

import java.util.ArrayList;
import java.util.Collections;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;


public class Quizv2{
    public MyLabel label = new MyLabel("Click Start");
    JButton button = new JButton("Start");
    Answersv2 pinolo;
    Question domanda;
    Answersv2.CoolButton button1;
    Answersv2.CoolButton button2;
    Answersv2.CoolButton button3;
    Answersv2.CoolButton button4;

public static void main (String [] args) {
    Quizv2 quiz = new Quizv2();
    quiz.go();  
}
    public void go () {
    Question domanda = new Question();
    Answersv2 pinolo = new Answersv2(domanda.rand1,domanda.rand2);
    pinolo.generate();


    button1 = pinolo.new CoolButton(pinolo.Answer_list.get(0));
    button1.setAlignmentX(Component.CENTER_ALIGNMENT);
    button2 = pinolo.new CoolButton(pinolo.Answer_list.get(1));
    button2.setAlignmentX(Component.CENTER_ALIGNMENT);
    button3 = pinolo.new CoolButton(pinolo.Answer_list.get(2));
    button3.setAlignmentX(Component.CENTER_ALIGNMENT);
    button4 = pinolo.new CoolButton(pinolo.Answer_list.get(3));
    button4.setAlignmentX(Component.CENTER_ALIGNMENT);

    JFrame frame = new JFrame("SPI trainer - Sum");
    JPanel panel = new JPanel();


    label.setAlignmentX(Component.CENTER_ALIGNMENT);
    int R = (int) (Math.random( )*256);
    int G = (int)(Math.random( )*256);
    int B= (int)(Math.random( )*256);
    Color randomColor = new Color(R, G, B);
    label.setForeground(randomColor);
    panel.add(label);


    button.setAlignmentX(Component.CENTER_ALIGNMENT);
    panel.add(button);
    ActionListener doGreeting = new StartListener();
    button.addActionListener(doGreeting );

    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
    panel.add(button1);
    panel.add(button2);
    panel.add(button3);
    panel.add(button4);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(BorderLayout.CENTER,panel);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(BorderLayout.CENTER,panel);
    frame.setSize(300,300);
    frame.setVisible(true);
    frame.setLocationRelativeTo( null );

    }
    }
    class StartListener extends Quizv2 implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            System.out.println("boo");

            label.setLabelText("The button text changed.");

            }

        }

但是,我似乎做错了什么,因为它打印了“boo”,但它并没有改变标签文本。我想避免使用

class StartListener extends Quizv2 implements ActionListener {
        public void actionPerformed(ActionEvent e) {
                        if (buttony == e.getSource()) {
                           label.setLabelText( domanda.rand1 + " + " + domanda.rand2 + " = : ????");
                       button1.setVisible(true);
                       button2.setVisible(true);
                       button3.setVisible(true);
                       button4.setVisible(true);
                       button.setVisible(false);
                            .....
                            .....
                        else if (buttonx == e.getSource())
                        ....

            }

        }

为了找出按下了哪个按钮,以便程序知道执行哪个代码块。 然后我尝试不使用子类,一切顺利。这是代码(Quizv2)

import java.util.ArrayList;
import java.util.Collections;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;


public class Quizv2 implements ActionListener{
    public MyLabel label = new MyLabel("Click Start");
    JButton button = new JButton("Start");
    Answersv2 pinolo;
    Question domanda;
    Answersv2.CoolButton button1;
    Answersv2.CoolButton button2;
    Answersv2.CoolButton button3;
    Answersv2.CoolButton button4;

public static void main (String [] args) {
    Quizv2 quiz = new Quizv2();
    quiz.go();  
}
    public void go () {
    domanda = new Question();
    pinolo = new Answersv2(domanda.rand1,domanda.rand2);
    pinolo.generate();

    button1 = pinolo.new CoolButton(pinolo.Answer_list.get(0));
    button1.setAlignmentX(Component.CENTER_ALIGNMENT);
    button2 = pinolo.new CoolButton(pinolo.Answer_list.get(1));
    button2.setAlignmentX(Component.CENTER_ALIGNMENT);
    button3 = pinolo.new CoolButton(pinolo.Answer_list.get(2));
    button3.setAlignmentX(Component.CENTER_ALIGNMENT);
    button4 = pinolo.new CoolButton(pinolo.Answer_list.get(3));
    button4.setAlignmentX(Component.CENTER_ALIGNMENT);

    JFrame frame = new JFrame("SPI trainer - Sum");
    JPanel panel = new JPanel();


    label.setAlignmentX(Component.CENTER_ALIGNMENT);
    int R = (int) (Math.random( )*256);
    int G = (int)(Math.random( )*256);
    int B= (int)(Math.random( )*256);
    Color randomColor = new Color(R, G, B);
    label.setForeground(randomColor); // Little bit of color
    panel.add(label);


    button.setAlignmentX(Component.CENTER_ALIGNMENT);
    panel.add(button);
    button.addActionListener(this);

    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
    panel.add(button1);
    button1.setVisible(false);
    panel.add(button2);
    button2.setVisible(false);
    panel.add(button3);
    button3.setVisible(false);
    panel.add(button4);
    button4.setVisible(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(BorderLayout.CENTER,panel);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().add(BorderLayout.CENTER,panel);
    frame.setSize(300,300);
    frame.setVisible(true);
    frame.setLocationRelativeTo( null );

    }
public void actionPerformed(ActionEvent e) {
        label.setLabelText( domanda.rand1 + " + " + domanda.rand2 + " = : ????");
        button1.setVisible(true);
        button2.setVisible(true);
        button3.setVisible(true);
        button4.setVisible(true);
        button.setVisible(false);
    }
    }

最佳答案

1) 我建议你把这个程序搁置一段时间。您犯了很多基本错误,所以我不知道您如何编译任何内容。你的代码是一个迷宫,这表明该程序对于你目前的能力来说太复杂了。

2) 您的帖子还表明您需要提高调试技能。提出问题时,您确实不应该发布超过 20 行代码。将问题减少到大约 20 行代码是一项可以提高调试技能的练习。您发布的 90% 的代码与您的问题无关。例如,您的整个 Answerv2 类可以简化为:

public class Answersv2 { 
    public ArrayList<String> Answer_list = new ArrayList<String>(); 

    public Answersv2 () {
        Answer_list.add("300", "150", "160", "170");
    }
}

您真的认为您的代码计算这些字符串的方式与单击按钮无法更改标签文本的原因有关吗?事实上,你的整个 Answerv2 类(class)都是无关紧要的。

程序可以包含的代码行数与您的调试技能成正比。学完java两天就写不出500行的程序。编写 Swing 程序会增加许多 Activity 部分,因此在尝试 Swing 之前您需要牢牢掌握基础知识,例如不要尝试访问静态方法内的非静态变量。

当您在处理某些代码时遇到问题(例如继承问题)时,请启动一个新程序进行试验。使新程序尽可能简单:

1) 编写一个基本的 Swing 程序来设置相关的 swing 组件...

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

class MyGui {
    protected JLabel label = new JLabel("Hello");
    protected JButton button = new JButton("Click me");

    public MyGui() {
        JFrame frame = new JFrame("Testing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(300, 100, 500, 300);

        JPanel panel = new JPanel();
        panel.add(label);
        panel.add(button);

        Container cpane = frame.getContentPane();
        cpane.add(panel);

        frame.setVisible(true);
    }

}

public class SwingProg {
    private static void createAndShowGUI() {
        new MyGui();
    }

    public static void main(String[] args) {
         javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    } }

2)在同一个类中获取一个actionPerformed()方法来工作:

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

class MyGui implements ActionListener {  //********
    protected JLabel label = new JLabel("Hello");
    protected JButton button = new JButton("Click me");

    public MyGui() {
        JFrame frame = new JFrame("Testing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(300, 100, 500, 300);


        JPanel panel = new JPanel();
        panel.add(label);
        button.addActionListener(this);  //**********
        panel.add(button);

        Container cpane = frame.getContentPane();
        cpane.add(panel);

        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent e) {   //**************
        System.out.println("boo");
        label.setText("The button was clicked!");
    }

}

public class SwingProg {
    private static void createAndShowGUI() {
        new MyGui();
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

3) 现在尝试继承MyGui并将actionPerformed方法放在子类中。好吧,所以你不知道如何让它发挥作用。现在至少您有一个可以发布的简单示例。

您的按钮的问题是:您从未指定子类中的 actionPerformed() 方法应该是按钮的监听器。这是您问题的解决方案:

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

class MyGui {
    protected JLabel label = new JLabel("Hello");
    protected JButton button = new JButton("Click me");

    public MyGui() {
        JFrame frame = new JFrame("Testing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(300, 100, 500, 300);

        JPanel panel = new JPanel();
        panel.add(label);
        panel.add(button);

        Container cpane = frame.getContentPane();
        cpane.add(panel);

        frame.setVisible(true);
    }
}


class StartListener extends MyGui implements ActionListener {
    public StartListener(){
        super();
        button.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        System.out.println("boo");
        label.setText("The button text changed.");
    }
}

public class SwingProg {
    private static void createAndShowGUI() {
        new StartListener();
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

不要尝试在复杂的程序中解决问题。相反,将问题外推到一个新程序中,并在新程序中解决问题。

关于Java:监听器子类不会更改父类(super class)按钮,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17386887/

相关文章:

java - android ksoap2 java.lang.IllegalArgumentException : size <= 0

java - android 当回车时清除RecyclerView

java - 如何在 OS X 上安装 Tomcat 作为守护进程?

java - 复选框节点树

android - CheckBox[] 与 onClickListener[]?

javafx - 如何将节点转换为另一个对象

java - 两个 JPanel 之间的通信

java - 使用 GUI 时出错 : IllegalStateException

java - 使用 AbstractTableModel 获取 JTable 中的选定行

java - 独立 java 程序中的 JMS 队列监听器