簡體   English   中英

在循環中使用Java Swing時出現問題

[英]Issue when using Java Swing in a For-Loop

我創建了一個簡單的for循環,它根據JSpinner的值更改JTextField和JLabel的數量,如以下代碼所示:

        public static ArrayList<ArrayList<JTextField>> ChangeQuestionAnswerFields(int numberOfQuestions){
        ArrayList<ArrayList<JTextField>> txtFieldArray = new ArrayList<ArrayList<JTextField>>();

        JPanel scrollPanel = new JPanel(new GridBagLayout());
        //JScrollPane scrollPane = new JScrollPane(scrollPanel);
        frame.add(scrollPanel, BorderLayout.CENTER);
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;


        for(int i = 0; i != numberOfQuestions; i++){
            JTextField tempQuestion = new JTextField(10);
            JTextField tempAnswer = new JTextField(10);
            JLabel tempQuestionHeader = new JLabel("Question " + (i + 1)+ " ");
            JLabel tempQuestionLbl = new JLabel("Question: ");
            JLabel tempAnswerLbl = new JLabel("Answer: ");

            ArrayList<JTextField> tempArrayList = new ArrayList<>();
            tempArrayList.add(tempQuestion);
            tempArrayList.add(tempAnswer);
            txtFieldArray.add(tempArrayList);

            c.gridy++;
            c.gridx = 0;
            scrollPanel.add(tempQuestionHeader, c);

            c.gridy++;
            c.gridx = 0;
            scrollPanel.add(tempQuestionLbl, c);

            c.gridx = 1;
            c.gridwidth = 3;
            scrollPanel.add(tempQuestion, c);

            c.gridy++;
            c.gridx = 0;
            scrollPanel.add(tempAnswerLbl, c);

            c.gridx = 1;
            c.gridwidth = 3;
            scrollPanel.add(tempAnswer, c);
        }
        return txtFieldArray;
    }
}

Spinner的值傳遞到方法中,並使用更改偵聽器(其中noQuestions是JSpinner的值)調用該方法:

noQuestions.addChangeListener(e -> {
        ChangeQuestionAnswerFields((int) noQuestions.getValue());
        frame.revalidate();
        frame.repaint();
    });

屏幕首次出現時,該方法首先在代碼中調用,並且可以正常工作。 但是,每當微調器的值更改時,原始標簽和字段就會保留在屏幕上,而更多文本字段只會出現或消失在頂部。

http://i.imgur.com/GBY8L3u.png-JSpinner的值為2 http://i.imgur.com/pSQsA3G.png-JSpinner的值為3

有沒有什么辦法解決這一問題? 任何幫助深表感謝。

謝謝湯姆

最小可運行示例:

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

public class MainGUI {
    static JFrame frame = new JFrame("Math Reviser");

    public static void main(String[] args) {


        frame.setSize(400, 600);
        frame.setVisible(true);

        createScreen();
        frame.revalidate();
        frame.repaint();

    public static void createScreen(){
        frame.getContentPane().removeAll();

        JSpinner noQuestions = new JSpinner(new SpinnerNumberModel(1, 1, 10, 1));
        frame.add(noQuestions, BorderLayout.NORTH);
        );
        changeQuestionAnswerFields(1);

        frame.revalidate();
        frame.repaint();

        noQuestions.addChangeListener(e -> {
            changeQuestionAnswerFields((int) noQuestions.getValue());
            frame.revalidate();
            frame.repaint();
        });

    }

    public static ArrayList<ArrayList<JTextField>> changeQuestionAnswerFields(int numberOfQuestions){
        ArrayList<ArrayList<JTextField>> txtFieldArray = new ArrayList<ArrayList<JTextField>>();

        JPanel scrollPanel = new JPanel(new GridBagLayout());
        frame.add(scrollPanel, BorderLayout.CENTER);
        GridBagConstraints c = new GridBagConstraints();
        c.gridx = 0;
        c.gridy = 0;


        for(int i = 0; i != numberOfQuestions; i++){
            JTextField tempQuestion = new JTextField(10);
            JTextField tempAnswer = new JTextField(10);
            JLabel tempQuestionHeader = new JLabel("Question " + (i + 1)+ " ");
            JLabel tempQuestionLbl = new JLabel("Question: ");
            JLabel tempAnswerLbl = new JLabel("Answer: ");

            ArrayList<JTextField> tempArrayList = new ArrayList<>();
            tempArrayList.add(tempQuestion);
            tempArrayList.add(tempAnswer);
            txtFieldArray.add(tempArrayList);

            c.gridy++;
            c.gridx = 0;
            scrollPanel.add(tempQuestionHeader, c);

            c.gridy++;
            c.gridx = 0;
            scrollPanel.add(tempQuestionLbl, c);

            c.gridx = 1;
            c.gridwidth = 3;
            scrollPanel.add(tempQuestion, c);

            c.gridy++;
            c.gridx = 0;
            scrollPanel.add(tempAnswerLbl, c);

            c.gridx = 1;
            c.gridwidth = 3;
            scrollPanel.add(tempAnswer, c);
        }
        return txtFieldArray;
    }
}

使用靜態變量和方法表明應用程序設計不良。 不需要靜態變量或方法。 建議您閱讀Swing教程中有關如何使用標簽的部分 LabelDemo.java代碼將向您展示如何創建一個包含所有組件的面板。 然后,此面板將添加到框架。 該面板還將包含程序所需的所有實例變量。

該示例不僅將向您展示如何在EDT上創建GUI組件,這是您應始終執行的操作,以防止隨機錯誤,因為Swing被設計為單線程。

但是,現有代碼的主要問題是您繼續創建新面板並將其添加到框架的內容窗格。 嘗試將微調器更改為2,然后調整框架的大小。 然后嘗試將微調器更改為3並調整框架的大小。 調整大小后,將顯示第一個面板。 這是因為Swing將繪制首先添加的最后一個組件,因此添加的第一個面板將被繪制在您創建的最后一個面板的頂部。

您可以通過在添加新面板之前刪除舊面板來更改現有代碼:

static JFrame frame = new JFrame("Math Reviser");
static JPanel scrollPanel = new JPanel();
...
frame.remove(scrollPanel);
//JPanel scrollPanel = new JPanel(new GridBagLayout());
scrollPanel = new JPanel(new GridBagLayout());

但是,我不推薦這種方法。 正如我最初建議的那樣,您需要重新設計整個課程。 當您進行重新設計時,我將在面板上使用BorderLayout,然后可以將微調器添加到PAGE_START,然后將JScrollPane添加到面板的CENTER。

然后,當您要創建新面板時,可以使用以下代碼將面板添加到滾動窗格中:

scrollPane.setViewportView( scrollPanel );

滾動面板會自動刷新,您無需擔心revalidate()或repaint()或其他任何問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM