Я вызываю этот метод под названием check в одном из моих абстрактных классов, но по какой-то причине JLabel (проблема), которую я добавляю на панель JPanel (панель), не отображается. Почему это происходит? Любые объяснения, я использую как перерисовку, так и проверку методов, но пока ничего не появляется.Почему мой JLabel не отображается
ответ
Если вы использовали Jframe для этого приложения, просто проверьте, добавили ли вы панель в рамку, вы только что добавили метку на панель, просто проверьте, добавили ли вы панель в Jframe , в противном случае он не будет отображаться
уже сделали это. – user2451511
проблемы вы испытываете это вы блокирование события диспетчерские темы, предотвратить UI от обновлялись или какие-либо новые события из обработаны ...
он начинается здесь ...
for(int i = 0; i < 15; i++)
{
//...
//Check to see if user has enetered anything
// And is compounded here
while(!answered)
{
Thread.sleep(duration);
//...
}
Вы явно думаете о процедуре (как и для консольной программы), но это не то, как работают графические интерфейсы, графические интерфейсы управляются событиями, что-то происходит в какой-то момент времени, и вы отвечаете на него.
Мое предложение состоит в том, чтобы расследовать Swing Timer
, что позволит вам запланировать обратный вызов в какой-то момент в будущем и выполнить какое-либо действие при его запуске, которое может быть использовано для изменения пользовательского интерфейса, поскольку оно выполнено в контекст EDT.
См Concurrency in Swing и How to use Swing Timers для получения более подробной информации
Я также рекомендую вам взглянуть на CardLayout
, как это может сделать легче изменить между различными видами
См How to Use CardLayout для более подробной информации
Основы
Я очень много работаю над принципом «Код для интерфейса не реализации» и Model-View-Controller. Они в основном побуждают вас разделить и изолировать ответственность, поэтому изменение одной части не будет отрицательно влиять на другую.
Это также означает, что вы можете использовать plug'n'play, развязать код и сделать его более гибким.
Начните с основным, вам нужно что-то, что имеет какой-то текст (вопрос), правильный ответ и некоторые «параметры» (или неправильные ответы)
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
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
" конечный экран ", и каждый отдельный QuestionPane
добавлен в panelOfQuestions
, который управляется CardLayout
, что позволяет легко« перевернуть »просмотры по мере необходимости.
Я использую простой метод, чтобы перейти к следующему вопросу
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();
}
}
В основном это увеличивает счетчик и проверяет, чтобы увидеть, если мы исчерпали вопросы или нет. Если у нас есть, он отключает следующую кнопку и отображает «последний» вид для пользователя, если нет, он переходит к следующему представлению вопроса и перезапускает таймер тайм-аута.
Теперь здесь приходит «волшебство» ...
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 + ")");
}
}
});
Свинг Timer
действует цикл псевдо, что означает, что он будет вызывать метод actionPerformed
на регулярных базах, так же, как for
или while
цикла будет , но он делает это так, что он не блокирует EDT.
Этот пример добавляет немного больше «волшебства» в том, что он действует как таймер обратного отсчета, он проверяет, как долго вопрос был видимым для пользователя, и показывает отсчет до тех пор, пока он автоматически не перейдет к следующему вопросу, когда 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);
}
});
}
}
И, наконец, потому что я знаю, что вы хотите один, полностью runable пример
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());
}
}
}
}
, но почему это не отображается, и какой код я мог бы добавить/удалить, чтобы исправить эту проблему? – user2451511
Почему не появляется? Поскольку вы блокируете поток Dispatching Event, который отвечает за обработку, среди прочего, запросы на рисование. Какой код следует добавить/удалить? Удалите все, серьезно, вы должны полностью переосмыслить процесс. Вы не можете использовать циклы 'for' /' while' для управления потоком вопросов, вместо этого вам нужно использовать Swing 'Timer' в качестве псевдо-цикла для управления потоком. Это потребует, чтобы вы переосмыслили, как задаются вопросы и как вы отслеживаете вход пользователей. – MadProgrammer
. Я бы начал с выяснения того, как вы собираетесь создавать пользовательский компонент, который мог бы спросить пользователя о вопросе и записать свой ответ как единый блок работы, таким образом, вы можете заранее создать вопросы заранее (прежде чем вы начнете показывать их пользователю) и просто используйте «Список» или массив в качестве механизма управления. Это позволит вам использовать «CardLayout», чтобы просто перевернуть между ними. – MadProgrammer
- 1. Почему мой JLabel не показан?
- 2. Почему мой JFrame не отображается?
- 3. Почему мой JTable не отображается?
- 4. Почему мой JTable не отображается?
- 5. Почему в панели не отображается массив jlabel?
- 6. Почему мой JLabel никогда не окрашивается?
- 7. Почему мой JmenuBar не отображается
- 8. JLabel не отображается
- 9. Почему мой JLabel не создает изображение?
- 10. JLabel экземпляр не отображается
- 11. JLabel Не отображается
- 12. JLabel текст не отображается
- 13. только JLabel не отображается
- 14. JLabel не отображается
- 15. Swing, JLabel не отображается
- 16. Java JLabel не отображается
- 17. JLabel не отображается на JPanel
- 18. Почему мой фон не отображается?
- 19. Почему мой тост не отображается
- 20. Почему мой список не отображается?
- 21. Почему мой график не отображается?
- 22. Почему мой список не отображается?
- 23. Почему мой NSBezierPath не отображается?
- 24. Почему мой список не отображается?
- 25. Почему мой CSS не отображается?
- 26. Почему мой спрайт не отображается?
- 27. Почему мой массив не отображается?
- 28. Почему мой UIpageControl не отображается?
- 29. Почему мой стол не отображается?
- 30. Почему мой флажок не отображается?
Просьба представить [MCVE] (http://stackoverflow.com/help/mcve) или [SSCCE] (http://sscce.org/) что мы можем скопировать-вставить и увидеть ту же проблему, что и вы. Этот код требует исправления путем удаления некоторых ненужных переменных, добавления библиотек и т. Д. Пожалуйста, помогите нам помочь вам. – Frakcool
Ваш код меня беспокоит, либо вы нарушаете правила одиночного потока качания, либо блокируя EDT с помощью yr, тогда как петли и thread.sleep или изменение пользовательского интерфейса извне контекста EDT – MadProgrammer