Связывание одного компонента свинга с другим - PullRequest
3 голосов
/ 17 апреля 2020

Я создаю GUI утилиту, которая позволит создавать вопросник через него. Вопрос может состоять из нескольких частей. Для этого я создал базовый c каркас: enter image description here

Моя проблема в том, что я могу легко создавать текстовые поля для вопросов и добавлять дополнительные вопросы, но как мне связать части вопроса к нему? В основном у меня есть массив JSON в конце, где вопрос будет храниться вместе с его частями.

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

QuestionModel представляет данные вопроса, где все строки, составляющие вопрос, хранятся в коллекции. QuestionView представляет вид одного вопроса. Questionnaire действует как контроллер, который также создает динамическое c представление QuestionView с. Для удобства весь код можно скопировать в Questionnaire.java и запустить:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.TextField;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

//Questionnaire acts as a controller which also creates a dynamic view of QuestionViews.
public class Questionnaire implements ChangeListener{

    private final List<QuestionView> questions;
    private final List<QuestionModel> questionModels;
    private JPanel questionPanel;
    private JFrame frame;

    Questionnaire() {
        questions = new ArrayList<>();
        questionModels = new ArrayList<>();
        createAndShowGui();
    }

    private void createAndShowGui() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        questionPanel = new JPanel();
        BoxLayout layout = new BoxLayout(questionPanel, BoxLayout.Y_AXIS);
        questionPanel.setLayout(layout);
        addQuestion();

        JButton addQuestionButton = new JButton("Add Question");
        addQuestionButton.addActionListener(e->addQuestion());

        JButton submitButton = new JButton("Submit");
        submitButton.addActionListener(e->collectQuestion());

        JPanel buttonsPanel = new JPanel(new BorderLayout(10,10));
        buttonsPanel.add(addQuestionButton, BorderLayout.WEST);
        buttonsPanel.add(submitButton, BorderLayout.EAST);

        JPanel mainPane = new JPanel(new BorderLayout(10,10));
        mainPane.add(questionPanel,BorderLayout.CENTER);
        mainPane.add(buttonsPanel,BorderLayout.SOUTH);
        frame.add(mainPane);

        frame.pack();
        frame.setVisible(true);
    }

    //adds a question to the questionnaire 
    private void addQuestion() {

        QuestionModel model = new QuestionModel();
        QuestionView view = new QuestionView(model);
        view.setListener(this);
        questions.add(view);
        questionModels.add(model);
        questionPanel.add(view.getView());
        refresh();
    }

    //refresh view whan something changed 
    void refresh(){
        frame.pack();
    }

    // ChangeListener implementation 
    @Override
    public void changed() {
        refresh();
    }

    //collect all strings from text fields and update models 
    private void collectQuestion() {

        for(QuestionView view : questions){
            view.collectQuestions();
        }

        //for testing
        printQuestions();
    }

    void printQuestions(){
        for(QuestionModel model : questionModels){
            System.out.println(model.getQuestion());
        }
    }

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

//QuestionModel represents question-data where all strings forming a question are stored in a collection.
class QuestionModel {

    private final List<String> questionParts;

    QuestionModel() {
        questionParts = new ArrayList<>();
    }

    void addQuestionPart(String text){
        questionParts.add(text);
    }

    List<String> getQuestionParts() {
        return questionParts;
    }

    //return the whole question as one string 
    String getQuestion(){
        StringBuilder sb = new StringBuilder();
        for(String part : questionParts){
            sb.append(part).append(" ");
        }
        return sb.toString();
    }
}

//QuestionView represents a view of a single question
class QuestionView {

    private final List<TextField> questionPartsTf;
    private final JPanel tfPanel, mainPanel;
    private  ChangeListener listener;   //used to notify that view changed 
    private final QuestionModel model;

    QuestionView(QuestionModel model) {

        this.model = model;
        questionPartsTf = new ArrayList<>();

        tfPanel = new JPanel(new GridLayout(1, 0, 0, 10));
        JLabel addLabel = new JLabel("Add question: ");
        tfPanel.add(addLabel);
        addTextField();

        JButton addButton = new JButton("Add question part");
        addButton.addActionListener(e->addTextField());

        mainPanel = new JPanel(new BorderLayout(10,10));
        mainPanel.add(tfPanel, BorderLayout.WEST);
        mainPanel.add(addButton, BorderLayout.AFTER_LINE_ENDS);
    }

    private void addTextField() {
        TextField tf= new TextField(15);
        tfPanel.add(tf);
        questionPartsTf.add(tf);
        if(listener != null){
            listener.changed();
        }
    }

    //collect all strings from text fields and update model
    void collectQuestions(){
        for(TextField tf : questionPartsTf){
            if(!tf.getText().isEmpty()){
                model.addQuestionPart(tf.getText());
            }
        }
    }

    JComponent getView(){
        return mainPanel;
    }

    void setListener(ChangeListener listener) {
        this.listener = listener;
    }
}

//interface for listening to view changes 
interface ChangeListener{
    void changed();
}

Запустить его в строке: https://repl.it/repls/VastNaiveModules

1 голос
/ 17 апреля 2020

Если я правильно понимаю ваш вопрос, вы хотите связать части с вопросами. Вот простой класс Java, который содержит один вопрос и столько частей, сколько необходимо.

import java.util.ArrayList;
import java.util.List;

public class Question {

    private String question;

    private List<String> parts;

    public Question(String question) {
        this.question = question;
        this.parts = new ArrayList<>();
    }

    public String getQuestion() {
        return question;
    }

    public void setQuestion(String question) {
        this.question = question;
    }

    public void addPart(String part) {
        this.parts.add(part);
    }

    public List<String> getParts() {
        return parts;
    }

}

Вы должны хранить экземпляры списка вопросов в другом классе, в классе модели вашего приложения.

Что касается представления, вы будете создавать дополнительный JTextField каждый раз, когда пользователь нажимает на кнопку добавления JButton. Вы связываете эти JTextFields с частями в классе Question.

...