【问题标题】:When JPanel changes, elements of the old JPanel are left behind当 JPanel 发生变化时,旧 JPanel 的元素会被留下
【发布时间】:2011-11-11 01:26:47
【问题描述】:

我正在使用 JTabbedPane,每个选项卡上都有一个面板,当用户执行诸如单击按钮之类的操作时,该面板会发生变化。我遇到的问题是上一个面板中的元素被遗忘了。通常在将鼠标移到它们上之前您是看不到它们的,但有时在将鼠标移到它们应该的位置之前,您看不到 new 面板的元素是。所以很多时候一开始只有一点点可见,然后:

when you run your mouse over more stuff it becomes visible

Then for some reason when you hit 'multiple choice', which is supposed to create the four new buttons, everything becomes perfectly visible.

repaint(); 几乎与其他所有行一样,在我更改 GUI 上的任何内容之前,我先执行removeAll();,但一切都会回来!有什么建议么?此面板的代码如下,如果它可能有帮助...

package com.GC01.gui;

import java.awt.Color;

public class PracticeQuizPanel extends JPanel implements MouseListener {
    /**
     * This panel will allow the user to practice quiz questions.
     */
private static final long serialVersionUID = 1L;

private User user = new User("misha");

boolean isMultipleChoice=false;
boolean usedClue=false;
boolean isStarted=false;

Calendar calendar = Calendar.getInstance();
AnswerAnalysis aA = new AnswerAnalysis();   
private Quiz qz = new Quiz( Quiz.getQuestionsFromDisk(), 4, TabbedQuiz.getUser().getNumLogins() );

private JTextArea questionArea;
private JTextArea clueArea;
private JTextArea answerArea;

private JButton clueButton;
private JButton multiButton;
private JButton answerButton;
private JButton startButton; 

private int index=0;
private Calendar startCalendar, endCalendar;

private JPanel backPanel;

public PracticeQuizPanel(){
    add(new StartButtonPanel());
}

PracticeQuizPanel(int index) {
    createVisualElements(index);
}

public void offerAnswer(){
    endCalendar = Calendar.getInstance();
    aA.setTimeSpent((int) (endCalendar.getTimeInMillis()-startCalendar.getTimeInMillis()));
    aA.setRight(answerArea.getText());
    JOptionPane.showMessageDialog(null, aA.toString());
    answerArea.setEditable(false);
    qz.setAnswersAnalysis(index, aA);
    index++;
    removeAll(); 
    if( index<qz.getLength() ) createVisualElements(index);
    else {
        removeAll();
        JOptionPane.showMessageDialog(null, qz.toFriendlyString());
        addQuizResultsToUserProgress();
        JOptionPane.showMessageDialog(null, qz.toFriendlyString());
        UserProgress uP = new UserProgress(user);
        System.out.println(uP.toString());
    }
    repaint();
    startCalendar = Calendar.getInstance();
    //JOptionPane.showMessageDialog(null, isStarted);
}

public void addQuizResultsToUserProgress(){
    UserProgress userProgress = new UserProgress(user);
    ArrayList<AnswerAnalysis> asA = userProgress.getAnswersAnalysis();
    for (int i=0; i<qz.getLength(); i++){
        asA.add( qz.getAnswersAnalysis()[i]);
    }
    userProgress.setAnswersAnalysis(asA);
    userProgress.saveProgress();
}



/**
 * This method creates/recreates all the text boxes, buttons etc. without resetting the quiz and
 * the objects in memory.
 */
private void createVisualElements(int index){
    if (TabbedQuiz.getUser().getNumLogins()<0) 
        JOptionPane.showMessageDialog(null, "There was an error. You may have done this quiz before.");
    removeAll();
    repaint();
    startCalendar = Calendar.getInstance();
    this.index=index;
    setBackground(new Color(112, 128, 144)); 
    setBounds(0,0,728,380);
    setLayout(null);

    questionArea = new JTextArea();
    questionArea.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));//new Font("Courier New", 0, 20));
    questionArea.setEditable(false);
    questionArea.setLineWrap(true);
    questionArea.setWrapStyleWord(true);
    questionArea.setBounds(295, 11, 423, 74);
    add(questionArea);
    //int index=0;
    Question q = qz.getQuestions().get(index);
    aA = new AnswerAnalysis(q.getQuestionID());
    questionArea.setText(q.getQuestionText() );

    clueArea = new JTextArea();
    clueArea.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));
    clueArea.setEditable(false);
    clueArea.setLineWrap(true);
    clueArea.setWrapStyleWord(true);
    clueArea.setBounds(295, 104, 423, 55);
    add(clueArea);

    JLabel lblQuestion = new JLabel("QUESTION:");
    lblQuestion.setFont(TabbedQuiz.getDefaultFont().deriveFont(40));
    lblQuestion.setBounds(43, 11, 216, 61);
    add(lblQuestion);

    answerArea = new JTextArea();//index+"");
    answerArea.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));
    answerArea.setLineWrap(true);
    answerArea.setWrapStyleWord(true);
    answerArea.setBounds(295, 301, 423, 50);
    answerArea.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyCode() == KeyEvent.VK_ENTER) offerAnswer();
        }
    });

    add(answerArea);
    answerArea.setFocusable(true);
    answerArea.requestFocusInWindow();

    clueButton = new JButton("CLUE?");
    clueButton.setFont(TabbedQuiz.getDefaultFont().deriveFont(40));
    clueButton.addMouseListener(this);
    clueButton.setBounds(15, 104, 244, 55);
    add(clueButton);

    multiButton = new JButton("MULTIPLE CHOICE?");
    multiButton.setFont(TabbedQuiz.getDefaultFont().deriveFont(20));
    multiButton.addMouseListener(this);
    multiButton.setBounds(15, 195, 244, 55);
    add(multiButton);

    answerButton = new JButton("ANSWER!");
    answerButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
        }
    });
    answerButton.setFont(TabbedQuiz.getDefaultFont().deriveFont(40));
    answerButton.setBounds(15, 301, 244, 55);
    answerButton.addMouseListener(this);
    add(answerButton);

    backPanel = new JPanel();
    backPanel.setBounds(0, 0, 728, 380);
    //add(backPanel);

    this.setVisible(true);
    repaint();
}

@Override
public void mouseClicked(MouseEvent e) {
    if      ( e.getSource().equals(startButton)  ) {
        remove(startButton); repaint(); isStarted=true;
        startCalendar = Calendar.getInstance();
    }
    else if ( e.getSource().equals(answerButton) ) offerAnswer();
    else if ( e.getSource().equals(clueButton )  ) {
        clueArea.setText(clueArea.getText() + qz.getQuestions().get(index).getClueText() + "\n");
        aA.setUsedClue(true);
        //JOptionPane.showMessageDialog(null, "hi");
        }
    else if ( e.getSource().equals(multiButton)  ) {            
        String[] answerOptions = qz.getQuestions().get(index).getAnswerOptions(3);
        JButton[] optionsButtons = new JButton[4];
        for(int j=0;j<4;j++){
            optionsButtons[j]=new JButton(answerOptions[j]);
            if(optionsButtons[j].getText().length()>13) 
                optionsButtons[j].setFont(TabbedQuiz.getDefaultFont().deriveFont(10));
            else optionsButtons[j].setFont(TabbedQuiz.getDefaultFont().deriveFont(15));
            if(j<2) optionsButtons[j].setBounds(295+211*j       , 170, 211, 55);
            else    optionsButtons[j].setBounds(295+211*(j-2)   , 226, 211, 55);
            optionsButtons[j].addMouseListener(this);
            optionsButtons[j].setName("optionsButton"+"["+j+"]");
            add(optionsButtons[j]);
            repaint();
        }
        aA.setMultipleChoice(true);
    }
    else if ( ( (JButton) e.getSource() ).getName().startsWith("optionsButton") ) {
        String answerOffered = ( (JButton) e.getSource() ).getText();
        answerArea.setText(answerOffered);
        offerAnswer();
    }
}

@Override
public void mouseEntered(MouseEvent e) {
    if(e.getSource()!=startButton && e.getSource().getClass().equals( answerButton.getClass()) ){
        ( (JButton) e.getSource() ).setBackground(Color.green);
    }if(index>0 && e.getSource()==startButton) remove(startButton);
}

@Override
public void mouseExited(MouseEvent e) {
    if(e.getSource()!=startButton && e.getSource().getClass().equals( answerButton.getClass()) ){
        ( (JButton) e.getSource() ).setBackground(UIManager.getColor("control"));
    }
}

@Override
public void mousePressed(MouseEvent e) {
}

@Override
public void mouseReleased(MouseEvent e) {
}
}

【问题讨论】:

    标签: java swing jpanel jbutton jtabbedpane


    【解决方案1】:

    每个选项卡上都有一个面板,当用户执行点击按钮等操作时,面板会发生变化。

    在我更改 GUI 上的任何内容之前,我会做 removeAll();

    每当我看到这样的 cmets 时,我觉得您应该使用 Card Layout,这样您就不必担心所有这些问题。

    【讨论】:

      【解决方案2】:

      如果使用布局管理器,您需要在移除或添加组件到容器后调用revalidate。然后你打电话给repaint

      您发布了很多代码,其中大部分与手头的问题完全无关,但另一方面,发布的代码不完整,无法编译,因此不是我们可以使用的代码测试。下次请尽量不要发布很多与问题无关的代码。尝试通过不断删减代码来隔离问题,如果仍然卡住,请发布一个最小的可兼容程序,我们可以自己研究、测试、运行和修改,sscce

      我浏览了您的一些 GUI 代码(天哪,不是全部!),并且在您踩到 Swing 绘画的地方存在一些严重的问题,例如 ProgressPanel.java 中的这段代码:

         public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            createAndShowGUI(g2d);
            // drawDifficultyChart(g2d, fontComboBox.getSelectedIndex());
         }
      
         private void createAndShowGUI(Graphics2D g2d) {
            JButton showChartButton = new JButton("Show new chart!");
            user = TabbedQuiz.getUser();
            showChartButton.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                  try {
                     if (categoryComboBox.getSelectedIndex() == 0
                           && difficultyComboBox.getSelectedIndex() != 0) {
                        drawDifficultyChart((Graphics2D) getGraphics(),
                              difficultyComboBox.getSelectedIndex());
                     } else if (difficultyComboBox.getSelectedIndex() == 0
                           && categoryComboBox.getSelectedIndex() != 0) {
                        drawCategoryChart((Graphics2D) getGraphics(),
                              (String) categoryComboBox.getSelectedItem());
                     } else
                        drawGeneralChart((Graphics2D) getGraphics(),
                              (String) categoryComboBox.getSelectedItem(),
                              difficultyComboBox.getSelectedIndex());
                  } catch (NullPointerException e1) {
                     JOptionPane.showMessageDialog(null, "Sign in first.");
                  }
               }
            });
            showChartButton.setBounds(10, 90, 96, 26);
            showChartButton.setFont(font);
            add(showChartButton);
         }
      

      问题是您正在从paint/paintComponent 方法中创建组件并将其添加到容器中,这是您永远不应该做的事情,而且肯定会弄乱程序的图形。

      【讨论】:

      • 我知道,抱歉,我刚刚创建了一个庞大而庞大的项目。我现在就试试revalidate()。谢谢!
      • @user1002973:我正在尝试通过您的大量代码帖子,但是有太多悬空引用无法理解逻辑。我看到的一个不相关的问题是,为什么要将 MouseListeners 添加到 JButtons?没有意义,以后可能会导致问题。为什么不使用 Actionlisteners 呢?
      • 我使用 MouseListeners 是因为我希望当鼠标悬停在按钮上时按钮会改变颜色。然后为实际单击设置单独的 ActionListener 似乎是不必要的。 revalidate() 似乎没有解决问题,我可能用错了......如果我仍然无法解决它,我将尝试在单类项目中重现该问题。
      • 不是使用 MouseListener 的好理由。通过这样做,如果您尝试禁用按钮会发生什么?换句话说,它会让你的按钮失去必要的行为。最好使用 ChangeListener 来监听按钮的模型,然后在 isRollover() 为真时做出响应。
      • 我到处都放了revalidate,但它似乎没有达到预期的效果。我无法在 JPanel 中重现该问题,因此我还没有弄清楚如何将代码减少到可在此站点上阅读的可管理大小。不过,我已将程序放入runnable .jar file。我原以为它只能在 Windows 上运行,并且会创建一个目录 C://Dummy/,但它是无害的!唯一真正起作用的选项卡是“欢迎”、“练习”、“查看性能”和“设置”。这看起来像是 JTabbedPane 的错吗?
      【解决方案3】:

      致有此问题的其他人:我最终解决了这个问题。 setVisible(false); setVisible(true);。随处可见。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 2023-03-17
        • 2016-06-16
        • 2021-01-18
        • 2019-04-01
        • 1970-01-01
        相关资源
        最近更新 更多