为什么我的JLabel没有出现

时间:2015-06-18 20:49:25

标签: java swing jpanel jbutton jlabel

我在我的一个抽象类中调用这个名为check的方法,但由于某种原因,我添加到JPanel(面板)的JLabel(问题)没有显示出来。 为什么会这样?任何解释,我使用重绘和验证方法,但仍然没有显示。

2 个答案:

答案 0 :(得分:5)

您遇到的问题是您正在阻止事件调度线程,阻止更新用户界面或处理任何新事件......

从这里开始......

        for(int i = 0; i < 15; i++)
        {
             //...

            //Check to see if user has enetered anything
            // And is compounded here
            while(!answered)
            {
                Thread.sleep(duration);
                //...
            }           

你清楚地以程序的方式思考(就像你对控制台程序一样),但这不是GUI如何工作,GUI是事件驱动的,某些时间点发生的事情你回应它。

我的建议是调查Swing Timer,这将允许您在某些时间安排回调,并在触发时执行某些操作,这可以用来修改UI,如它在EDT的背景下执行。

有关详细信息,请参阅Concurrency in SwingHow to use Swing Timers

我还建议您查看CardLayout,因为它可能更容易更改不同视图之间

有关详细信息,请参阅How to Use CardLayout

基本

我非常注重&#34;代码与接口不实现的原则&#34;和Model-View-Controller。这些基本上鼓励你分离和分离责任,所以一部分的变化不会对另一部分产生不利影响。

这也意味着您可以插入实现,解耦代码并使其更灵活。

从基础开始,你需要一些有文字(问题),正确答案和一些&#34;选项&#34; (或不正确的答案)

public interface Question {

    public String getPrompt();
    public String getCorrectAnswer();
    public String[] getOptions();
    public String getUserResponse();
    public void setUserResponse(String response);
    public boolean isCorrect();

}

所以,非常基本的。问题有一个提示,一个正确的答案,一些错误的答案,并可以管理用户响应。为了便于使用,它还具有isCorrect方法

现在,我们需要一个实际的实现。这是一个非常基本的例子,但是你可能有许多不同的实现,甚至可能包含答案类型的泛型(为了论证,我将其假定为String

public class DefaultQuestion implements Question {

    private final String prompt;
    private final String correctAnswer;
    private final String[] options;

    private String userResponse;

    public DefaultQuestion(String prompt, String correctAnswer, String... options) {
        this.prompt = prompt;
        this.correctAnswer = correctAnswer;
        this.options = options;
    }

    @Override
    public String getPrompt() {
        return prompt;
    }

    @Override
    public String getCorrectAnswer() {
        return correctAnswer;
    }

    @Override
    public String[] getOptions() {
        return options;
    }

    @Override
    public String getUserResponse() {
        return userResponse;
    }

    @Override
    public void setUserResponse(String response) {
        userResponse = response;
    }

    @Override
    public boolean isCorrect() {
        return getCorrectAnswer().equals(getUserResponse());
    }
}

好的,这一切都很好,但这实际上对我们有什么影响?好吧,知道你可以创建一个简单的组件,其唯一的工作就是向用户提出问题并处理他们的响应......

public class QuestionPane extends JPanel {

    private Question question;

    public QuestionPane(Question question) {
        this.question = question;

        setLayout(new BorderLayout());

        JLabel prompt = new JLabel("<html><b>" + question.getPrompt() + "</b></html>");
        prompt.setHorizontalAlignment(JLabel.LEFT);

        add(prompt, BorderLayout.NORTH);

        JPanel guesses = new JPanel(new GridBagLayout());
        guesses.setBorder(new EmptyBorder(5, 5, 5, 5));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.weightx = 1;
        gbc.anchor = GridBagConstraints.WEST;

        List<String> options = new ArrayList<>(Arrays.asList(question.getOptions()));
        options.add(question.getCorrectAnswer());
        Collections.sort(options);

        ButtonGroup bg = new ButtonGroup();
        for (String option : options) {
            JRadioButton btn = new JRadioButton(option);
            bg.add(btn);

            guesses.add(btn, gbc);
        }

        add(guesses);

    }

    public Question getQuestion() {
        return question;
    }

    public class ActionHandler implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            getQuestion().setUserResponse(e.getActionCommand());
        }

    }

}

这是一个很好的可重用组件,可以处理一堆问题而不关心。

现在,我们需要一些方法来管理多个问题,一个测验!

public class QuizPane extends JPanel {

    private List<Question> quiz;

    private long timeOut = 5;
    private Timer timer;
    private JButton next;

    private CardLayout cardLayout;
    private int currentQuestion;

    private JPanel panelOfQuestions;

    private Long startTime;

    public QuizPane(List<Question> quiz) {
        this.quiz = quiz;
        cardLayout = new CardLayout();
        panelOfQuestions = new JPanel(cardLayout);

        JButton start = new JButton("Start");
        start.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                currentQuestion = -1;
                nextQuestion();
                timer.start();
            }
        });

        JPanel filler = new JPanel(new GridBagLayout());
        filler.add(start);
        panelOfQuestions.add(filler, "start");

        for (int index = 0; index < quiz.size(); index++) {
            Question question = quiz.get(index);
            QuestionPane pane = new QuestionPane(question);
            panelOfQuestions.add(pane, Integer.toString(index));
        }
        panelOfQuestions.add(new JLabel("The quiz is over"), "last");
        currentQuestion = 0;
        cardLayout.show(panelOfQuestions, "start");

        setLayout(new BorderLayout());
        add(panelOfQuestions);

        JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        next = new JButton("Next");
        buttonPane.add(next);
        next.setEnabled(false);

        add(buttonPane, BorderLayout.SOUTH);

        next.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                nextQuestion();
            }
        });

        timer = new Timer(250, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (startTime == null) {
                    startTime = System.currentTimeMillis();
                }
                long duration = (System.currentTimeMillis() - startTime) / 1000;
                if (duration >= timeOut) {
                    nextQuestion();
                } else {
                    long timeLeft = timeOut - duration;
                    next.setText("Next (" + timeLeft + ")");
                    next.repaint();
                }
            }
        });
    }

    protected void nextQuestion() {
        timer.stop();
        currentQuestion++;
        if (currentQuestion >= quiz.size()) {
            cardLayout.show(panelOfQuestions, "last");
            next.setEnabled(false);
            // You could could loop through all the questions and tally
            // the correct answers here
        } else {
            cardLayout.show(panelOfQuestions, Integer.toString(currentQuestion));
            startTime = null;
            next.setText("Next");
            next.setEnabled(true);
            timer.start();
        }
    }
}

好的,这有点复杂,但基本原理是,它管理当前向用户呈现的问题,管理时间并允许用户根据需要导航到下一个问题。

现在,它很容易迷失在细节中......

这部分代码使用CardLayout

实际设置主要&#34;视图&#34;
panelOfQuestions.add(filler, "start");

for (int index = 0; index < quiz.size(); index++) {
    Question question = quiz.get(index);
    QuestionPane pane = new QuestionPane(question);
    panelOfQuestions.add(pane, Integer.toString(index));
}
panelOfQuestions.add(new JLabel("The quiz is over"), "last");
currentQuestion = 0;
cardLayout.show(panelOfQuestions, "start");

start按钮,&#34;结束屏幕&#34;每个人QuestionPane都会添加到由panelOfQuestions管理的CardLayout中,这样可以轻松地“翻转”#34}。视需要。

我使用一种简单的方法转到下一个问题

protected void nextQuestion() {
    timer.stop();
    currentQuestion++;
    if (currentQuestion >= quiz.size()) {
        cardLayout.show(panelOfQuestions, "last");
        next.setEnabled(false);
        // You could could loop through all the questions and tally
        // the correct answers here
    } else {
        cardLayout.show(panelOfQuestions, Integer.toString(currentQuestion));
        startTime = null;
        next.setText("Next");
        next.setEnabled(true);
        timer.start();
    }
}

这基本上增加了一个计数器,并检查我们是否已经完成了问题。如果有,它会禁用下一个按钮并显示&#34; last&#34;查看用户,如果没有,它将移动到下一个问题视图并重新启动超时计时器。

现在,来了#34;魔术&#34; ...

timer = new Timer(250, new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        if (startTime == null) {
            startTime = System.currentTimeMillis();
        }
        long duration = (System.currentTimeMillis() - startTime) / 1000;
        if (duration >= timeOut) {
            nextQuestion();
        } else {
            long timeLeft = timeOut - duration;
            next.setText("Next (" + timeLeft + ")");
        }
    }
});

Swing Timer执行伪循环,这意味着它将在常规基础上调用actionPerformed方法,就像forwhile循环一样,但它这样做可以阻止EDT。

这个例子增加了一点魔法&#34;因为它充当倒计时器,它会检查问题对用户可见的时间长度,并在duration大于或等于等于自动移动到下一个问题时显示倒计时。 timeOut(此示例中为5秒),它调用nextQuestion方法

但是你怎么用它?您创建List Question,创建QuizPane的实例并将其添加到屏幕上显示的其他容器中,例如......

public class QuizMaster {

    public static void main(String[] args) {
        new QuizMaster();
    }

    public QuizMaster() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                List<Question> quiz = new ArrayList<>(5);
                quiz.add(new DefaultQuestion("Bananas are:", "Yellow", "Green", "Blue", "Ping", "Round"));
                quiz.add(new DefaultQuestion("1 + 1:", "2", "5", "3", "An artificial construct"));
                quiz.add(new DefaultQuestion("In the UK, it is illegal to eat...", "Mince pies on Christmas Day", "Your cousin", "Bananas"));
                quiz.add(new DefaultQuestion("If you lift a kangaroo’s tail off the ground...", "It can’t hop", "It will kick you in the face", "Act as a jack"));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new QuizPane(quiz));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

}

最后,因为我知道你想要一个完全可运行的例子

QuizMaster

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class QuizMaster {

    public static void main(String[] args) {
        new QuizMaster();
    }

    public QuizMaster() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                List<Question> quiz = new ArrayList<>(5);
                quiz.add(new DefaultQuestion("Bananas are:", "Yellow", "Green", "Blue", "Ping", "Round"));
                quiz.add(new DefaultQuestion("1 + 1:", "2", "5", "3", "An artificial construct"));
                quiz.add(new DefaultQuestion("In the UK, it is illegal to eat...", "Mince pies on Christmas Day", "Your cousin", "Bananas"));
                quiz.add(new DefaultQuestion("If you lift a kangaroo’s tail off the ground...", "It can’t hop", "It will kick you in the face", "Act as a jack"));

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new QuizPane(quiz));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class QuizPane extends JPanel {

        private List<Question> quiz;

        private long timeOut = 5;
        private Timer timer;
        private JButton next;

        private CardLayout cardLayout;
        private int currentQuestion;

        private JPanel panelOfQuestions;

        private Long startTime;

        public QuizPane(List<Question> quiz) {
            this.quiz = quiz;
            cardLayout = new CardLayout();
            panelOfQuestions = new JPanel(cardLayout);

            JButton start = new JButton("Start");
            start.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    currentQuestion = -1;
                    nextQuestion();
                    timer.start();
                }
            });

            JPanel filler = new JPanel(new GridBagLayout());
            filler.add(start);
            panelOfQuestions.add(filler, "start");

            for (int index = 0; index < quiz.size(); index++) {
                Question question = quiz.get(index);
                QuestionPane pane = new QuestionPane(question);
                panelOfQuestions.add(pane, Integer.toString(index));
            }
            panelOfQuestions.add(new JLabel("The quiz is over"), "last");
            currentQuestion = 0;
            cardLayout.show(panelOfQuestions, "start");

            setLayout(new BorderLayout());
            add(panelOfQuestions);

            JPanel buttonPane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
            next = new JButton("Next");
            buttonPane.add(next);
            next.setEnabled(false);

            add(buttonPane, BorderLayout.SOUTH);

            next.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    nextQuestion();
                }
            });

            timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (startTime == null) {
                        startTime = System.currentTimeMillis();
                    }
                    long duration = (System.currentTimeMillis() - startTime) / 1000;
                    if (duration >= timeOut) {
                        nextQuestion();
                    } else {
                        long timeLeft = timeOut - duration;
                        next.setText("Next (" + timeLeft + ")");
                        next.repaint();
                    }
                }
            });
        }

        protected void nextQuestion() {
            timer.stop();
            currentQuestion++;
            if (currentQuestion >= quiz.size()) {
                cardLayout.show(panelOfQuestions, "last");
                next.setEnabled(false);
                // You could could loop through all the questions and tally
                // the correct answers here
            } else {
                cardLayout.show(panelOfQuestions, Integer.toString(currentQuestion));
                startTime = null;
                next.setText("Next");
                next.setEnabled(true);
                timer.start();
            }
        }
    }

    public interface Question {

        public String getPrompt();

        public String getCorrectAnswer();

        public String[] getOptions();

        public String getUserResponse();

        public void setUserResponse(String response);

        public boolean isCorrect();
    }

    public class DefaultQuestion implements Question {

        private final String prompt;
        private final String correctAnswer;
        private final String[] options;

        private String userResponse;

        public DefaultQuestion(String prompt, String correctAnswer, String... options) {
            this.prompt = prompt;
            this.correctAnswer = correctAnswer;
            this.options = options;
        }

        @Override
        public String getPrompt() {
            return prompt;
        }

        @Override
        public String getCorrectAnswer() {
            return correctAnswer;
        }

        @Override
        public String[] getOptions() {
            return options;
        }

        @Override
        public String getUserResponse() {
            return userResponse;
        }

        @Override
        public void setUserResponse(String response) {
            userResponse = response;
        }

        @Override
        public boolean isCorrect() {
            return getCorrectAnswer().equals(getUserResponse());
        }
    }

    public class QuestionPane extends JPanel {

        private Question question;

        public QuestionPane(Question question) {
            this.question = question;

            setLayout(new BorderLayout());

            JLabel prompt = new JLabel("<html><b>" + question.getPrompt() + "</b></html>");
            prompt.setHorizontalAlignment(JLabel.LEFT);

            add(prompt, BorderLayout.NORTH);

            JPanel guesses = new JPanel(new GridBagLayout());
            guesses.setBorder(new EmptyBorder(5, 5, 5, 5));
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;
            gbc.anchor = GridBagConstraints.WEST;

            List<String> options = new ArrayList<>(Arrays.asList(question.getOptions()));
            options.add(question.getCorrectAnswer());
            Collections.sort(options);

            ButtonGroup bg = new ButtonGroup();
            for (String option : options) {
                JRadioButton btn = new JRadioButton(option);
                bg.add(btn);

                guesses.add(btn, gbc);
            }

            add(guesses);

        }

        public Question getQuestion() {
            return question;
        }

        public class ActionHandler implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent e) {
                getQuestion().setUserResponse(e.getActionCommand());
            }

        }

    }

}

答案 1 :(得分:-1)

如果您在此应用程序中使用了Jframe,只需检查是否已将面板添加到框架中,您刚刚将该标签添加到面板中,只需检查您是否已添加该面板到Jframe,否则它不会出现