java - 多次单击按钮后小型 Swing 应用程序崩溃

标签 java swing jbutton

此代码是一个问答游戏的简单引擎。这个想法是答案显示在 JButton 上。为此,我必须设置一个刷新方法来删除所有内容并重新绘制它。似乎每次调用这个方法时,它都会变得越来越慢。单击大约 10 次按钮后,它变得非常慢,以至于它会停止响应,我将不得不手动关闭该程序。

谢谢

package mainPackage;

import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class MainGame{
    static JFrame frame;
    static WindowComp w;

    public static void main(String[] args) {
        frame = new JFrame("Game");
        w = new WindowComp();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(300, 300);
        frame.setVisible(true);
        frame.setResizable(true);

        WindowComp.setAnswers( "start", "start", "start", "start");
        WindowComp.refreshAll(w, frame);

        WindowComp.setAnswers("final", "final", "final", "final");
        WindowComp.refreshAll(w, frame);
    }
}

public class WindowComp extends JComponent implements ActionListener {
    static JButton [] buttons = new JButton[4];
    static JLabel question = new JLabel("default");

    public WindowComp(){
        setAnswers("default", "default", "default", "default");
    }

    public void paintComponent(Graphics g){
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == buttons[0]){
            setQuestion("button 1");
        }
        if(e.getSource() == buttons[1]){
            setQuestion("button 2");
        }
        if(e.getSource() == buttons[2]){
            setQuestion("button 3");
        }
        if(e.getSource() == buttons[3]){
            setQuestion("button 4");
        }
        refreshAll(MainGame.w, MainGame.frame);
    }

    public void addAll(){
        setLayout(new FlowLayout());
        buttons[0].addActionListener(this);
        buttons[1].addActionListener(this);
        buttons[2].addActionListener(this);
        buttons[3].addActionListener(this);
        add(buttons[0]);
        add(buttons[1]);
        add(buttons[2]);
        add(buttons[3]);
        add(question);
    }

    public static void setAnswers( String ans1, String ans2, String ans3,String ans4){
        buttons[0] = new JButton("Answer 1 : " + ans1);
        buttons[1] = new JButton("Answer 2 : " + ans2);
        buttons[2] = new JButton("Answer 3 : " + ans3);
        buttons[3] = new JButton("Answer 4 : " + ans4);
    }

    public static void setQuestion(String q){
        question = new JLabel("Question: " + q);
    }

    public static void refreshAll(WindowComp w, JFrame frame){
        w.removeAll();
        w.addAll();
        w.revalidate();
        frame.add(w);
    }
}

最佳答案

好吧,正如评论中所说,您添加了太多的 ActionListener,从而导致了您所描述的问题。

以下是我想给您的一些建议。

首先,您不必每次想要更改按钮文本时都使用关键字new。垃圾收集将删除未使用的按钮,但为什么您需要新按钮而不是仅通过 setTest(String) 更新按钮上的文本,这不会调用任何垃圾收集。

最后,尝试更多地使用构造函数,您实际上可以在调用构造函数时创建您需要的所有内容(至少在这种情况下,而不是一般情况下)。例如,您可以在构造函数中创建所有 JButton,并将所有监听器添加到按钮(我将在下面提供一些代码)。

我稍微重写了你的代码,它没有与你的代码相同的功能,但它也不会崩溃。

package de;

import javax.swing.JFrame;

public class MainGame{
static JFrame frame;
static WindowComp w;
public static void main(String[] args) {
    frame = new JFrame("Game");
    w = new WindowComp();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 300);
    frame.add(w);
    frame.setVisible(true);
    frame.setResizable(true);
   /*WindowComp.setAnswers( "start", "start", "start", "start");
    WindowComp.refreshAll(w, frame);

    WindowComp.setAnswers("final", "final", "final", "final");
    WindowComp.refreshAll(w, frame);*/
}

}




package de;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;

@SuppressWarnings("serial")
public class WindowComp extends JComponent implements ActionListener {

static JButton [] buttons;
static JLabel question;

public WindowComp(){
    question = new JLabel("default");
    buttons = new JButton[4];
    setLayout(new FlowLayout());
    buttons[0] = new JButton("Answer 1 : " + "default");
    buttons[1] = new JButton("Answer 2 : " + "default");
    buttons[2] = new JButton("Answer 3 : " + "default");
    buttons[3] = new JButton("Answer 4 : " + "default");

    buttons[0].addActionListener(this);
    buttons[1].addActionListener(this);
    buttons[2].addActionListener(this);
    buttons[3].addActionListener(this);
    addAll();

}


@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == buttons[0]){
        setQuestion("button 1");
        setAnswers( "start", "start", "start", "start");
    }
    if(e.getSource() == buttons[1]){
        setQuestion("button 2");
        setAnswers("final", "final", "final", "final"); 
    }
    if(e.getSource() == buttons[2]){
        setQuestion("button 3");
    }
    if(e.getSource() == buttons[3]){
        setQuestion("button 4");
    }
    //refreshAll(MainGame.w, MainGame.frame);

}
public void addAll(){

    add(buttons[0]);
    add(buttons[1]);
    add(buttons[2]);
    add(buttons[3]);
    add(question);

}



public static void setAnswers( String ans1, String ans2, String ans3,String ans4){
    buttons[0].setText("Answer 1 : " + ans1);
    buttons[1].setText("Answer 2 : " + ans2);
    buttons[2].setText("Answer 3 : " + ans3);
    buttons[3].setText("Answer 4 : " + ans4);

}

public static void setQuestion(String q){
    question.setText("Question: " + q);
}

public static void refreshAll(WindowComp w, JFrame frame){
    w.removeAll();
    w.addAll();
    w.revalidate();
    frame.add(w);

}

}

编辑:就当前代码而言,您的函数 refreshAll(WindowComp w, JFrame frame) 不再被调用,因为当前不需要调用它。在没有调用的情况下测试程序后,我用此编辑注释掉了它。

关于java - 多次单击按钮后小型 Swing 应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38555827/

相关文章:

java - ArrayList<> 无法解析为类型

java - Java 可以与 System V linux 消息队列交互吗?

java - 如何定义 JPanel 的大小和位置

java - 按钮 Action 监听器

java - 如何使依赖注入(inject)对组件起作用

java - android 捕获异常后如何切换activity?

java - Actionlistener 将 Jlist 信息输出到文本区域

java - 使用 void 方法添加按钮

java - JButtons 和 JLabels 没有出现

Java GUI 创建组件