简体   繁体   English

Java文字冒险游戏摆动组件未正确更新,并且每次函数运行都枚举两次

[英]Java text-adventure game swing components not updating correctly and enum gets selected twice per function run

I am intrigued by the bug that's appearing in the code that I've written. 我对编写的代码中出现的错误很感兴趣。 It works perfectly in C# but somehow it doesn't work in Java. 它在C#中可以完美地工作,但是在Java中却不起作用。 I'm not sure if it has something to do with the second time I set it. 我不确定它是否与我第二次设置有关。 I've checked it with my other class that passes the buttons into this class and I find nothing that would affect this class. 我已经与将按钮传递到该类的其他类进行了检查,但发现没有任何影响该类的内容。 Another thing to note is that all the Swing components aren't null when they're passed into this class. 要注意的另一件事是,所有Swing组件在传递给此类时都不为null。

My main problem is that all buttons do not update after setting the text for the second time. 我的主要问题是, 第二次设置文本后,所有按钮都不会更新。

public class StoryManager extends Text{
    // this is the body of the story
    private JTextPane textPane;
    // the choices that the user can make
    private JButton btnChoice1;
    // this would determine which ending the user will get
    private short ending = 0;

/**
 * checkpoint for each part of the story
 * */
public enum Part{
    START, A_JOKE, B_BASE
}
// the part that the user is currently in
Part userPart;

/**
 * This runs the story.
 * */
public void PlayStory() {
    printText();
    processDecision();
}
/**
 * This attaches the buttons and the textPane to their corresponding variables in the class.
 * */
public StoryManager(WindowHandler windowHandler) {
    // pane
    textPane = windowHandler.getTextPane();
    // buttons
    btnChoice1 = windowHandler.getBtnChoice1();
    // set the user to start the story from the beginning
    userPart = Part.START;
}

@Override
public void printText() {
    switch(userPart) {
    case START:
        System.out.println("Start event started");
        textPane.setText("some text"
                + "[1] option 1\n");
        break;
    case A_JOKE:
        System.out.println("A_JOKE event started");
        textPane.setText("another text 1"
                + "[1] option 1\n");
        break;
    case B_BASE:
        System.out.println("B_BASE event started");
        textPane.setText("another text 2"
                + "[1] option 1\n");

        break;
    default:
    }
    textPane.setCaretPosition(0);
    textPane.repaint();
}
/**
 * Enables all the buttons.
 * */
private void EnableAllButtons() {
    if(!btnChoice1.isEnabled()) {
        btnChoice1.setEnabled(true);
        btnChoice1.setOpaque(true);
        btnChoice1.setContentAreaFilled(true);
        btnChoice1.setBorderPainted(true);
    }
    btnChoice1.repaint();
    //System.out.println("Button1: "+btnChoice1.isEnabled());
}
/**
 * Temporarily disables the other buttons and runs the PlayStory() again to continue the story.
 * 
 * @param button The button that is clicked.
 * */
private void SetDecisionText(JButton button) {
    button.setText("Next");
    btnChoice1.revalidate();
    PlayStory();
}
/**
 * Sets the action of the button per part.
 * */
@Override
public void processDecision() {
    switch(userPart) {
    case START:
        btnChoice1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                ending -= 10;
                userPart = Part.A_JOKE;
                SetDecisionText(btnChoice1);
            }
        });
        break;
    case A_JOKE:
        btnChoice1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                btnChoice1.setText("Choice 1");
                //btnChoice1.revalidate(); <- tried this but it isn't working
                GoToBase();
            }
        });
        break;
    case B_BASE:
        System.out.println("Updated with B_BASE");
        btnChoice1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                ending -= 10;
                userPart = Part.B_ARGUE;
                SetDecisionText(btnChoice1);
            }
        });
    }

}
private void GoToBase() {
    EnableAllButtons();
    switch(userPart) {
    case A_JOKE:
        userPart = Part.B_BASE;
        System.out.println("GotoBase: " + userPart);
        break;
    default:
        System.out.println("Error");
    }
    PlayStory();
}

}

I'll share the output of my program here. 我将在这里共享程序的输出。 I selected the first button twice then this happens. 我选择了第一个按钮两次,然后发生这种情况。 When I press it again, userPart becomes null or something. 当我再次按下它时, userPart变为null或其他内容。

// pressed play
Start event started

// click 1st button
A_JOKE event started

// click 1st button again
GotoBase: B_BASE
B_BASE event started
Updated with B_BASE
A_JOKE event started

// click 1st button for the third time
GotoBase: B_BASE
B_BASE event started
Updated with B_BASE
Error
A_JOKE event started

You appear to be adding ActionListeners to your buttons within the logical portion of your code, and your doing this means that buttons will have ActionListeners added to them multiple times, whenever the processDecision() method is called, resulting eventually in buttons with multiple listeners added to them which is not what you want. 您似乎在代码的逻辑部分中向按钮添加了ActionListeners,并且这样做意味着每次调用processDecision()方法时,按钮都会多次添加ActionListeners,最终导致添加了多个侦听器的按钮给他们,那不是你想要的。 The listeners should be added once, at component creation. 侦听器应在组件创建时添加一次。

Or if you are going to want to swap ActionListeners, then be sure to remove the old listeners when replacing with the new. 或者,如果您要交换ActionListener,则在替换为新侦听器时,请确保删除旧的侦听器。

There are likely other logical problems in your code, but this is the limit of what I can suggest until you are able to provide a valid Minimal, Complete, and Verifiable Example Program for us. 您的代码中可能还存在其他逻辑问题,但这是我建议的限制,直到您能够为我们提供有效的最小,完整和可验证的示例程序 This is where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem. 在这里,您可以将代码压缩为仍可编译和运行的最小位,没有外部依赖项(例如,需要链接到数据库或图像),没有与您的问题无关的额外代码,但仍然可以演示您的问题。

A large problem that I see is that your code has very high coupling and low cohesion, making for very brittle code, and code that is hard to debug. 我看到的一个大问题是您的代码具有很高的耦合度和较低的内聚性,这使代码非常脆弱,并且代码难以调试。 Consider refactoring, separating your model (the logic portion of your program) from your view (the GUI portion) and separating the data from the code, getting rid of the hard-coded display text for instance, and putting it into a data repository, be it a text file, database or whatever works best. 考虑进行重构,将模型(程序的逻辑部分)与视图(GUI部分)分离,并将数据与代码分离,例如摆脱硬编码的显示文本,然后将其放入数据存储库,无论是文本文件,数据库还是效果最好的文件。

example of removing listeners: 删除侦听器的示例:

case A_JOKE:
    for (ActionListener l : btnChoice1.getActionListeners()) {
        btnChoice1.removeActionListener(l);
    }
    btnChoice1.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            btnChoice1.setText("Choice 1");
            // btnChoice1.revalidate(); <- tried this but it isn't
            // working
            GoToBase();
        }
    });
    break;

As an aside, you will want to learn and use Java naming conventions which are different than those used for C#. 顺便说一句,您将要学习和使用与C#所使用的Java命名约定不同的Java命名约定 Variable names should all begin with a lower letter while class names with an upper case letter. 变量名都应以小写字母开头,而类名应以大写字母开头。 Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others. 学习并遵循此规则将使我们能够更好地理解您的代码,并使您能够更好地理解其他人的代码。

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

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