Могу ли я запустить For Loop внутри графического интерфейса? Поскольку в настоящее время у меня есть проблемы с этим, поэтому хотел проверить это, продолжайте давать мне IndexOutofBound

Поскольку я не уверен, как это сделать, поскольку цикл for в графическом интерфейсе, похоже, не запускается, и он продолжает выдавать исключение, я нахожусь в тупике.

Это код

public static class HelpWindow extends JDialog {

    JLabel label;

    public HelpWindow(JFrame frame) {
        super(frame, "Help", true);
        setLayout(new FlowLayout());

        label = new JLabel("Hey you");
        add(label);
    }
}

public static class AddQnA extends JDialog {

    JLabel label, label2, label3, label4;
    JTextField question, answer;
    JButton input, reset;
    JTextArea textarea;

    ArrayList<String> ques = new ArrayList<>();
    ArrayList<String> ans = new ArrayList<>();

    public AddQnA(JFrame frame) {
        super(frame, "Add Question & Answer", true);
        setLayout(new FlowLayout());

        label = new JLabel("Question :");
        add(label);

        question = new JTextField(60);
        add(question);

        label2 = new JLabel("Answer   : ");
        add(label2);

        answer = new JTextField(60);
        add(answer);

        input = new JButton("Submit");
        add(input);

        reset = new JButton("Reset");
        add(reset);

        label3 = new JLabel("Please use the \"x\" on the top right to exit this section");
        add(label3);

        label4 = new JLabel("");
        add(label4);

        textarea = new JTextArea(10, 25);
        add(textarea);
        textarea.setEditable(false);

        Reset a = new Reset();
        reset.addActionListener(a);

        Submit b = new Submit();
        answer.addKeyListener(b);

        Submit c = new Submit();
        input.addActionListener(c);
    }

    public class Reset implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent a) {
            question.setText("");
            answer.setText("");
        }
    }

    public class Submit implements KeyListener, ActionListener {

        @Override
        public void keyTyped(KeyEvent e) {
            // Not in use as of now therefore no method will be here
        }

        @Override
        public void keyPressed(KeyEvent b) {
            int keycode = b.getKeyCode();
            if (keycode == KeyEvent.VK_ENTER) {
                ques.add(question.getText());
                ans.add(answer.getText());
                label4.setText("**Question & Answer has been Added**");
                textarea.append("Question:" + question.getText() + "\n");
                textarea.append("Answer:" + answer.getText() + "\n\n");
                question.setText("");
                answer.setText("");
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            // Not in use as of now therefore no method will be here
        }

        @Override
        public void actionPerformed(ActionEvent c) {
            ques.add(question.getText());
            ans.add(answer.getText());
            label4.setText("**Question & Answer has been Added**");
       for (int i = 0; i < ques.size(); i++) {
            if (ques.get(i) == null) {
                textarea.append("There are no newly added questions or answers");
            } else {
                textarea.append("Question: " + ques.get(i));
                textarea.append("Answer: " + ans.get(i) + "\n");
            }
        }
            question.setText("");
            answer.setText("");
        }

    }
}

public static class DisplayQnA extends JDialog {

    JLabel label;
    JTextArea textarea;
    JMenuBar display;
    JMenu file;
    JMenuItem show;

    ArrayList<String> ques = new ArrayList<>();
    ArrayList<String> ans = new ArrayList<>();

    public DisplayQnA(JFrame frame) {
        super(frame, "Display Question & Answer", true);
        setLayout(new FlowLayout());

        label = new JLabel("Displaying All Questions And Asnwers");
        add(label);

        AddQnA qa;
        qa = new AddQnA(frame);
        textarea = new JTextArea(10, 25);
        add(textarea);
        textarea.setEditable(false);

       for (int i = 0; i < qa.ques.size(); i++) {
            if (qa.ques.get(i) == null) {
                textarea.append("There are no newly added questions or answers");
            } else {
                textarea.append("Question: " + qa.ques.get(i));
                textarea.append("Answer: " + qa.ans.get(i) + "\n");
            }
        }


    }
}

}

я пытаюсь получить вход в мои массивы AddQnA, а затем извлечь его из DisplayQnA, но, похоже, он не работает вообще. Он просто выскакивает пустую страницу, поэтому мне также было интересно, что, так как и Add, и Display будут открывать свои собственные JFrames, значит, когда я пересекаю Add JFrame, информация о массиве останется или будет удалена?

2 ответа

У вас есть несколько проблем с размещенным кодом, но самая большая проблема, которую я вижу здесь:

    public DisplayQnA(JFrame frame) {

        // .....

        AddQnA qa;
        qa = new AddQnA(frame); // ***** Here ****

        // ....

    }

Я предполагаю, что ваш код первоначально отображает объект AddQnA JDialog, что вы подаете на него иск, чтобы попытаться заполнить вопрос и ответить на ArrayLists, и что после закрытия этого диалогового окна вы затем отображаете диалоговое окно DisplayQnA. В конструкторе DisplayQnA вы создаете совершенно новый объект AddQnA, который полностью отличается от того, который (я считаю) ранее отображался, и тот, который никогда не отображается и поэтому не имеет возможности взаимодействовать с пользователем. Если мое предположение верно (вы не показываете код, в котором фактически отображаете эти объекты), тогда у вас есть проблема с ошибочными предположениями о том, как работают Java и ООП. Ключевая концепция, которую вы упускаете, состоит в том, что объекты класса - это совершенно разные сущности. Да, вы меняете состояние ранее отображенного объекта AddQnA (я думаю), но это не имеет никакого отношения к состоянию объекта AddQnA, который вы создаете в классе DisplayQnA.

Итак, как это решить? Или как решить проблему передачи достоверной информации от одного объекта к другому? Есть несколько возможных решений:

  1. Вы можете сделать ArrayLists внутри AddQnA static так что теперь они являются полями класса, а не объекта, и, таким образом, являются общими для всего приложения. Это простое, прямое и полностью ошибочное решение, так как при этом вы выбрасываете ООП с водой из ванны, а отдельные части вашей программы теряют преимущества структуры ООП (объектно-ориентированного программирования), в том числе сниженную связь, повышенную согласованность., улучшенная тестируемость,...
  2. Вы можете передать информацию через методы установки или конструкторы. Это может сработать.
  3. Или, что лучше, но потребует больше работы, вы можете попытаться извлечь "модель" вашей программы (данные вопроса / ответа) из ее "представления" (GUI). Это приведет к наиболее надежному решению, которое будет работать лучше всего, если программа масштабируется до чего-то большего, чем просто игрушечная программа, но может оказаться излишним в академических упражнениях.

Поэтому я рекомендую перейти к решению 2 - передавать данные, где и когда это необходимо, с помощью методов установки.

Другие проблемы: избегайте использования KeyListeners в текстовых компонентах. Гораздо лучше создать один ActionListener и добавить его в JTextField, поскольку он будет реагировать на нажатие клавиши ввода.

Например, вы можете отобразить данные в JList и передать модель JList в оба диалоговых окна. Таким образом, диалоговое окно ввода данных может ввести вопрос и ответ в модель, и дисплей данных может отобразить его (или оба могут отобразить его при желании). Например:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;

public class AddDisplay {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            DefaultListModel<QuestionAnswer> qaModel = new DefaultListModel<>();

            // both share the same model
            EnterDataPanel entryPanel = new EnterDataPanel(qaModel);
            DisplayDataPanel displayPanel = new DisplayDataPanel(qaModel);

            JDialog enterDialog = new JDialog(null, "Enter Data", ModalityType.MODELESS);
            enterDialog.add(entryPanel);
            enterDialog.pack();
            enterDialog.setLocationByPlatform(true);

            JDialog displayDialog = new JDialog(null, "Display Data", ModalityType.MODELESS);
            displayDialog.add(displayPanel);
            displayDialog.pack();
            displayDialog.setLocationByPlatform(true);

            displayDialog.setVisible(true);
            enterDialog.setVisible(true);
        });
    }
}

// class to encapsulate a single question/answer pair
class QuestionAnswer {
    private String question;
    private String answer;

    public QuestionAnswer(String question, String answer) {
        this.question = question;
        this.answer = answer;
    }

    public String getQuestion() {
        return question;
    }

    public String getAnswer() {
        return answer;
    }

}

@SuppressWarnings("serial")
class EnterDataPanel extends JPanel {
    private static final int COLS = 15;
    private JTextField questionField = new JTextField(COLS);
    private JTextField answerField = new JTextField(COLS);
    private DefaultListModel<QuestionAnswer> qaModel;
    private SubmitAction submitAction = new SubmitAction();

    public EnterDataPanel(DefaultListModel<QuestionAnswer> qaModel) {
        questionField.addActionListener(submitAction);
        answerField.addActionListener(submitAction);

        this.qaModel = qaModel;
        add(new JLabel("Question:"));
        add(questionField);
        add(Box.createHorizontalStrut(10));
        add(new JLabel("Answer:"));
        add(answerField);
        add(Box.createHorizontalStrut(10));
        add(new JButton(submitAction));
    }

    // abstract action is like an actionlistener "on steroids"
    private class SubmitAction extends AbstractAction {
        public SubmitAction() {
            super("Submit");
            putValue(MNEMONIC_KEY, KeyEvent.VK_S);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // get text from text fields
            String question = questionField.getText().trim();
            String answer = answerField.getText().trim();
            if (question.isEmpty() || answer.isEmpty()) {
                // TODO:
                // if either text field is empty, show an error message
            } else {
                // both text fields hold text
                // create a QuestionAnswer object with it
                QuestionAnswer qa = new QuestionAnswer(question, answer);

                // add into our model and reset fields
                qaModel.addElement(qa);  
                questionField.setText("");
                answerField.setText("");
            }
            questionField.requestFocusInWindow();
        }
    }

}

@SuppressWarnings("serial")
class DisplayDataPanel extends JPanel {
    private static final int ROW_COUNT = 10;
    // jlist to display the data
    private JList<QuestionAnswer> qajList = new JList<>();

    public DisplayDataPanel(ListModel<QuestionAnswer> qaModel) {
        qajList.setModel(qaModel);
        // set jlist renderer to allow multi-line display
        qajList.setCellRenderer(new MyCellRenderer());

        // give a protoptype cell value so jlist is wide enough
        qajList.setPrototypeCellValue(new QuestionAnswer(
                "question question question question question question ", 
                "answer   answer   answer   answer   answer   answer   "));
        qajList.setVisibleRowCount(ROW_COUNT);
        JScrollPane qaScroll = new JScrollPane(qajList);
        qaScroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        setLayout(new BorderLayout());
        add(qaScroll);
    }

    // cell renderer to display multiple lines of text in JList
    private class MyCellRenderer extends DefaultListCellRenderer {

        @Override
        public Component getListCellRendererComponent(JList<?> list, Object value, int index,
                boolean isSelected, boolean cellHasFocus) {
            if (value == null) {
                value = "";
            } else {
                QuestionAnswer qa = (QuestionAnswer)value;
                String q = "Q: " + qa.getQuestion();
                String a = "A: " + qa.getAnswer();

                // use simple HTML formatting to allow multiple lines
                value = String.format("<html>%s<br/>%s<html>", q, a);                        
            }            

            Component superComp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            return superComp;
        }        
    }
}

qa.ques а также qa.ans относятся, вероятно, к различным Lists.
Вы перебираете qa.ques но вы также обращаетесь к qa.ans во время цикла:

 textarea.append("Answer: " + qa.ans.get(i) + "\n");

Как два ListСкорее всего, это относится к двум разным объектам, которые необязательно могут быть заполнены по одним и тем же индексам List,
Лучше было бы использовать один List параметризован с помощью пользовательского класса.
Например: List<QuestionAndAnswers> questionAndAnswersList,

Затем вы можете зациклить:

for (QuestionAndAnswers questionAndAnswers : questionAndAnswersList) {
    if (questionAndAnswers  == null) {
        textarea.append("There are no newly added questions or answers");
    } else {
        textarea.append("Question: " + questionAndAnswers.getQuestion());
        textarea.append("Answer: " +  questionAndAnswers.getAnswer() + "\n");
    }
}
Другие вопросы по тегам