【问题标题】:Java Hangman GUI not properly displaying [closed]Java Hangman GUI 未正确显示 [关闭]
【发布时间】:2013-12-27 04:51:40
【问题描述】:

我的代码有几个不同的问题,其中大多数是基于 GUI 的问题,但我确实有一个 actionevent 问题。我将首先在部分中发布我的代码,然后我将指出每个部分的具体问题。 *请注意,我的所有代码都将按照我的 IDE 中的实际顺序排列。

如果您想复制我的代码而不包含所有其他内容,请在 pastebin 上:http://pastebin.com/HHjRRtGZ

我的进口:

import java.awt.*;
import java.awt.event.*;

import javax.swing.*; //Makes it a Japplet

import java.util.Random;

我的计划从这里开始:

public class Hangman extends JApplet implements ActionListener {

    // How many times you can guess the wrong letter till you lose
    static final int DEAD = 7;   

    private int errors;        // amount of errors
    private String message;   // Message displaying either Error or Victory
    private String information; // Secondary Message
    private String RealWord;      // The Real word
    private StringBuffer GuessWord;// The Guessed word
    private Button StartBtn;      // The Restart Button
    private Button GoBtn;         // The Go Button
    private TextField LetterBox; // The LetterBox

我的动作事件:

    public void actionPerformed(ActionEvent e){

        if (e.getSource() == StartBtn){
            initGame();
        }

        if (e.getSource() == GoBtn){

            processTurn();

            LetterBox.setText("");
            repaint();
        }
    }

问题一:

我的 Action 事件遇到的问题是,当我点击 StartBtn 时,它并没有重新初始化所有内容。什么都没有清除。什么都没做。它什么也没做。所以这就是问题所在。

我的 init() 函数(这是我的问题之一。

    public void init() {

        // Create a "Textbox" for the letter guessing
        LetterBox = new TextField();

        //Create my buttons and labels
        StartBtn = new Button("Restart");
        GoBtn = new Button("Go");

        //Add the elements to the applet

        JPanel p = new JPanel();
        p.setLayout(new FlowLayout());

        p.add(StartBtn);
        p.add(new Label("Guess a letter"));
        p.add(LetterBox);
        p.add(GoBtn);

        add(p, BorderLayout.SOUTH);

        //Make buttons event listeners
        StartBtn.addActionListener(this);
        GoBtn.addActionListener(this);

        //Startup the Game
        initGame();

    }

问题 2(主要问题):

我的初始化代码影响我的 GUI 的问题是实际的单词猜测区域和刽子手区域有点混乱。很难解释,所以我给你看一张图片。几乎所有表单的背景都是完全透明的。所以它只是使用它上面的任何东西作为背景的静止图像。

问题 3: 如您所见,图像还有一些其他问题。然而,这些部分的代码更进一步。但正如你所知道的,这些消息并没有清除,只是相互覆盖,即使我指定它们(你会在下面看到)。

问题 4: 现在,在您猜测任何字母之前,该单词会被“”隐藏,但是当您猜测该单词的正确字母时,它应该用猜到的正确字母替换“”。然而,它只是把它放在上面(你也会在下面看到代码)。

这是游戏初始化器

    public void initGame() {
        //Set the errors to 0
        errors = 0;

        //Enter the wordslist, separated by a | here
        String str = "write|program|receive|positive|variables|temporary|good|bad|test";        
        String[] temp;


        //delimiter
        String delimiter = "\\|";

        // given string will be split by the argument delimiter provided.
        temp = str.split(delimiter);

        //Create the Random Seed Generator
        Random RandGenerator = new Random();

        //Generate my Random Number
        int randomInt = RandGenerator.nextInt(temp.length);

        RealWord = new String(temp[randomInt]);

        char positions[] = new char[RealWord.length()];

就在这里,它将屏幕上未猜到的字符替换为“*”。

        for (int i = 0; i < RealWord.length(); i++) {
            positions[i] = '*';
        }


        String s = new String(positions);
        GuessWord = new StringBuffer(s);

        LetterBox.setText("");

        //Delete Messages
        message = "";
        information = "";
        repaint();
    }

我的绘画功能

    @Override
    public void paint(Graphics g) {

        int BaseY = 250;

        //THE HANGING STAND
        if (errors > 0) { //1 Error
            g.drawLine(90, BaseY, 200, BaseY); //The ground
            g.drawLine(125, BaseY, 125, BaseY-100); //The bar going up
            g.drawLine(125, BaseY-100, 175, BaseY-100); //The sidebar
            g.drawLine(175, BaseY-100, 175, BaseY-75); //The Rope
        }

        //THE PERSON
        if (errors > 1) { 
           g.drawOval(170, BaseY-75, 10, 12); // The Head       
        }

        if (errors > 2) { 
           g.drawLine(175, BaseY-62, 175, BaseY-45); // The Body    
        }

        if (errors > 3) { 
           g.drawLine(165, BaseY-65, 175, BaseY-55); // Left Arm  
        }

        if (errors > 4) { 
           g.drawLine(185, BaseY-65, 175, BaseY-55); // Right Arm 
        }

        if (errors > 5) { 
           g.drawLine(170, BaseY-30, 175, BaseY-45); //Left Leg       
        }

        if (errors > 6) {  //7 Errors
           g.drawLine(175, BaseY-45, 180, BaseY-30); // Right Left 
        }


        //Show Messages/Errors
        g.drawString(message, 40, BaseY+25);
        g.drawString(information, 25, BaseY+45);
        g.drawString(new String (GuessWord), 140, BaseY-120);

        g.drawString(new String("WELCOME TO HANGMAN!"), 75, 40);
    }

这就是许多神奇发生的地方。这是processTurn函数

    private void processTurn() {

        String s, t;
        char a;

        s = LetterBox.getText();
        a = s.charAt(0);

        if (!Character.isLetter(a)) {
            message = "Only enter letters please.";
            return;
        }

        if (s.length() > 1) {
            message = "One letter at a time please.";
            return;
        }

        //Check if letter has been used already
        t = new String(GuessWord);
        if (t.indexOf(s) != -1) {
            message = "You have already guessed with that letter!";
            return;
        }

        //If the letter you guessed does not occur in the Real Word
        if (RealWord.indexOf(s) == -1) {

            message = "";
            errors++;

            if (errors==DEAD) {
                message = "Sorry, you lose";
                information = "Click restart to try again!";

                //INSERT MOVING HANGMAN HERE.
            }

            return;
        }

这是应该用正确猜测的字母替换“*”但它不能正常工作的地方!

        //Replace stars in the Guessed Word with the found letter
        for (int i = 0; i < RealWord.length(); i++) {
            if (RealWord.charAt(i) == a) {
                GuessWord.setCharAt(i, a);
            }
        }

        t = new String(GuessWord);

        //If all of the stars have been filled, then you win!
        if (t.indexOf('*') == -1) {
            message = "You have won!";
            return;
        }

        //Delete the Message
        message = "";
        repaint();
    }

主要功能

    public static void main(String[] args) {

        JFrame frame = new JFrame();
        JApplet applet = new Hangman();

        applet.init();
        applet.start();
        frame.add(applet);

        frame.setSize(300, 400);
        frame.setLocationRelativeTo(null); // Center the frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);


    }
}

我们将不胜感激任何和所有的帮助 :) 提前致谢!

【问题讨论】:

  • 1) 你发布了太多代码 2) 你问了太多不相关的问题。尝试同时关注一个问题 3)不要覆盖paint,而是覆盖paintComponents(并在覆盖的方法中调用super.paintComponents
  • 1) 我发布了我的所有代码,因为所有这些都是相关的 2) 我问了所有这些问题,其中许多是相关的(因为除了其中一个之外,所有这些问题都是基于 GUI 的)3) 我试过了当我添加 super.paintCompenents 时,它给了我一个错误。我来这里是为了寻求帮助,而不是被告知我需要以不同的方式寻求帮助,因为我做得正确、格式化和友善。

标签: java swing user-interface awt actionevent


【解决方案1】:

这是由于您破坏了paint链的基本事实。

AWT/Swing 中的绘制由一系列方法调用组成。如果您忽略维护此链,您将开始以您所看到的形式绘制工件。

Graphics 上下文是共享资源,也就是说,在任何给定绘制周期内绘制的每个组件都将获得相同的Graphics 资源。每个组件都应该在绘制之前准备好Graphics 上下文...

要解决此问题,在您的所有 paint 方法中,您应该调用 super.paint(g) 以确保绘制链得到维护,并且 Graphics 上下文已针对各个组件的绘制需求进行了准备。

话虽如此。不建议覆盖顶级容器的paint。相反,建议您使用JPanel 之类的方法执行自定义绘制,并改写它的paintComponent 方法(确保您也调用super.paintComponent!)

这至少有两个基本好处。第一个是,您可以决定面板应该显示在哪里,例如,您可以将其添加到JApplet 或JFrame 或其他您认为合适的容器中。默认情况下它是双缓冲的。这意味着当绘画更新时您不会看到任何闪烁。

您应该考虑将您的应用程序分解为多个小面板,分别关注每个组件的需求。这将有助于降低应用程序的复杂性,并使管理应用程序每个部分的个性化需求变得更加容易。

查看Performing Custom Painting 和Painting in AWT and Swing 了解更多详情

【讨论】:

  • +1 用于详细说明油漆链损坏的原始问题。
  • @Aqua 如果你更新你的回答提到不打电话给super.paint,我会更倾向于提供赞成票;) - 因为你们其他人的回答是很好的建议......
  • @MadProgrammer 你能看看我的翻译代码吗?我修改了很多。 pastebin.com/66Q70f5X 我为我的 Hangman 类创建了一个公共构造函数,我还创建了另一个类来保存几乎所有东西。它提供了底部栏(文本框和按钮等),但其余部分是空白的(这很好,因为它之前是透明的),但它现在没有绘制任何东西:(
  • @MadProgrammer 你能看看我的新代码并告诉我我做错了什么吗? pastebin.com/66Q70f5X
【解决方案2】:

问题是您直接在JApplet 上绘画。您不应直接在顶级容器上绘画,例如 JFrame 或 JApplet。请改用JComponent 或JPanel。覆盖paintComponent() 进行绘画而不是paint(),不要忘记致电super.paintComponent(g)。

查看Performing Custom Painting 教程了解更多信息。

考虑重构您的代码,将所有当前逻辑和绘画移入一个新的JPanel,该JPanel 将用作小程序内容。然后,将此面板添加到小程序。

编辑:

问题的根源是在你的绘画实现中没有调用super.paint()。覆盖paint() 不是必需的,并且通常不建议在许多 Swing 应用程序中使用。 JComponent.paint()(所有 Swing 组件的超类)处理绘制 Swing 组件的内容、边框和子项。忽略对super.paint() 的呼叫,您正在破坏所有这些细节的绘制。

查看A Closer Look at the Paint Mechanism 了解有关绘画周期的更多详细信息。

【讨论】:

  • 好的,为了实现这个,我需要更改哪些代码以及在哪里?
  • 这是一个很好的建议,但是(从我的角度来看),问题不在于他们已经覆盖了顶级容器的 paint问题) - 但你很接近;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 2012-08-09
  • 1970-01-01
  • 1970-01-01
  • 2017-04-22
  • 2022-07-12
相关资源
最近更新 更多