Java CardLayout:“;JButton在以下情况下可见……”;不起作用

Java CardLayout:“;JButton在以下情况下可见……”;不起作用,java,swing,cardlayout,Java,Swing,Cardlayout,亲爱的朋友们:, 我已经试着解决这个问题两周了。提前感谢您的帮助。 我想做的事: 我有一个卡片布局,可以在不同的JPanel之间切换 Pan1有不同的按钮,如果变量Level1设置为“1”,则这些按钮应该是可见的 Pan2由Pan1启动,有一个将变量Level1设置为“1”的按钮和一个随后返回Pan1的按钮 当我回到Pan1时,我现在应该看到一个按钮,因为变量是1 问题: 变量被正确设置为1,但当我返回Pan1时,按钮不可见。我试着重新油漆,重新验证,但似乎没有任何效果 我的代码 packa

亲爱的朋友们:, 我已经试着解决这个问题两周了。提前感谢您的帮助。 我想做的事

  • 我有一个卡片布局,可以在不同的JPanel之间切换
  • Pan1有不同的按钮,如果变量Level1设置为“1”,则这些按钮应该是可见的
  • Pan2由Pan1启动,有一个将变量Level1设置为“1”的按钮和一个随后返回Pan1的按钮
  • 当我回到Pan1时,我现在应该看到一个按钮,因为变量是1
问题: 变量被正确设置为1,但当我返回Pan1时,按钮不可见。我试着重新油漆,重新验证,但似乎没有任何效果

我的代码

package prove3;

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;


public class PRINCIPAL extends Level1{
JFrame MainWindow; 
JPanel panelCont; 
Pan1 Pan1Window; 
Pan2 Pan2Window; 
CardLayout cards; 

public PRINCIPAL(){
    MainWindow = new JFrame("Game Window"); 
    panelCont = new JPanel(); 
    cards = new CardLayout(); 
    Pan1Window = new Pan1(cards, panelCont, Level1Completed); 
    Pan2Window = new Pan2(Pan1Window, cards, panelCont, Level1Completed); 

    panelCont.setLayout(cards);
    panelCont.add(Pan1Window, "1"); 
    panelCont.add(Pan2Window, "2"); 
    cards.show(panelCont, "1");

    MainWindow.add(panelCont);
    MainWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    MainWindow.setSize(800, 800);
    MainWindow.setVisible(true);

}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new PRINCIPAL();
        }
    });
}    
}

class Level1 extends JPanel{

    static int Level1Completed = 0;    

    public void setLevel1Completed (int newLevel1Completed){
        Level1Completed = newLevel1Completed;  
    }

    public int getLevel1Completed(){
        return Level1Completed; 
    }
}

class Pan1 extends Level1 {
JPanel panelCont; 
CardLayout LayoutPan1; 
JLabel label; 
JButton OpenPan2; 
JButton buttonLevel2; 
int L1Completed; 

public Pan1(
            final CardLayout LayoutPan1, 
            final JPanel panelCont, 
            final int Level1Completed)
{
    this.L1Completed = super.getLevel1Completed(); 
    this.panelCont = panelCont; 
    this.LayoutPan1 = LayoutPan1; 

    OpenPan2 = new JButton("Open Pan2 Window"); 
    buttonLevel2 = new JButton("Progress to Level 2"); 
    OpenPan2.addActionListener
    (new ActionListener()
        {
            public void actionPerformed (ActionEvent GoToPan2)
            {
                if (GoToPan2.getSource() == OpenPan2){
                    LayoutPan1.show(panelCont, "2"); 
                }
            }
        }
    );
    add(OpenPan2); 

    //this printout is to see that, at the beginning, the Level1 variable is set to 0 (see the command line)
    System.out.println(getLevel1Completed());                    

    //this is where the problem is: what I want is that this button is initially not visible as the variable is set to 0
    //but when, in the next pan, I'll set it to 1, this button becomes visible
    if (super.getLevel1Completed()==1){
        add(buttonLevel2);  
        buttonLevel2.setVisible(true);
        invalidate(); 
        revalidate(); 
    }          

    setBackground(Color.GREEN);
}   
}

class Pan2 extends Level1 {
JPanel Pan1Window; 
CardLayout LayoutPan1Window; 
JPanel panelCont;     
JButton OpenPan1; 
JButton L1Done; 
int L1Completed; 

public Pan2(
        final JPanel Pan1Window, 
        final CardLayout LayoutPan1Window, 
        final JPanel panelCont, 
        final int L1Completed
){
    this.L1Completed = super.getLevel1Completed(); 
    OpenPan1 = new JButton("Go back to Pan 1");         
    OpenPan1.addActionListener
    (new ActionListener()
        {
            public void actionPerformed(ActionEvent ApriFinestraLancio)
            {
                if(ApriFinestraLancio.getSource()==OpenPan1){
                    LayoutPan1Window.show(panelCont, "1");                        
                }
            }
        }
    );
    add(OpenPan1); 

    L1Done = new JButton("Set Level 1 as Completed"); 
    L1Done.addActionListener
    (new ActionListener()
        {
            public void actionPerformed(ActionEvent SettaL1Complet)
            {
                setLevel1Completed(1); 
                System.out.println(getLevel1Completed());//this print shows that the value of the variable is correctly changed to 1
            }
        }
    );
    add(L1Done); 

    setBackground(Color.RED);
}       
}
欢迎任何帮助

if (super.getLevel1Completed()==1){
    add(buttonLevel2);  
    buttonLevel2.setVisible(true);
    invalidate(); 
    revalidate(); 
}  
应在设置level1Completed的位置调用该代码。它可以在setter本身内部,也可以在调用

            setLevel1Completed(1); 
            System.out.println(getLevel1Completed());
无需调用invalidate()和revalidate()。重新验证就足够了。我建议最初添加按钮并使其不可见。因此,你所需要的只是打电话

buttonLevel2.setVisible(super.getLevel1Completed()==1); to change the button's visibility

问题是,您只检查在Pan1的构造函数中是否设置了level1。因此,如果调用show
LayoutPan1Window.show(panelCont,“1”)不再检查变量。
一个解决方案是为Pan1实现一个
组件监听器
。ComponentListener提供了一个方法
OnComponentShowed()
,每次显示组件时都会调用该方法。在这种方法中,您可以执行level1变量的检查。代码可能如下所示:

    import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class PRINCIPAL extends Level1 {
    JFrame MainWindow;
    JPanel panelCont;
    Pan1 Pan1Window;
    Pan2 Pan2Window;
    CardLayout cards;

    public PRINCIPAL() {
        MainWindow = new JFrame("Game Window");
        panelCont = new JPanel();
        cards = new CardLayout();
        Pan1Window = new Pan1(cards, panelCont, Level1Completed);
        Pan2Window = new Pan2(Pan1Window, cards, panelCont, Level1Completed);

        panelCont.setLayout(cards);
        panelCont.add(Pan1Window, "1");
        panelCont.add(Pan2Window, "2");
        cards.show(panelCont, "1");

        MainWindow.add(panelCont);
        MainWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        MainWindow.setSize(800, 800);
        MainWindow.setVisible(true);

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new PRINCIPAL();
            }
        });
        }
    }

    class Level1 extends JPanel {

    static int Level1Completed = 0;

    public void setLevel1Completed(int newLevel1Completed) {
        Level1Completed = newLevel1Completed;
    }

    public int getLevel1Completed() {
        return Level1Completed;
    }
    }

    class Pan1 extends Level1 implements ComponentListener {
    JPanel panelCont;
    CardLayout LayoutPan1;
    JLabel label;
    JButton OpenPan2;
    JButton buttonLevel2;
    int L1Completed;

    public Pan1(final CardLayout LayoutPan1, final JPanel panelCont,
            final int Level1Completed) {
        this.L1Completed = super.getLevel1Completed();
        this.panelCont = panelCont;
        this.LayoutPan1 = LayoutPan1;
        addComponentListener(this);

        OpenPan2 = new JButton("Open Pan2 Window");
        buttonLevel2 = new JButton("Progress to Level 2");
        OpenPan2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent GoToPan2) {
                if (GoToPan2.getSource() == OpenPan2) {
                    LayoutPan1.show(panelCont, "2");
                }
            }
        });
        add(OpenPan2);

        // this printout is to see that, at the beginning, the Level1 variable
        // is set to 0 (see the command line)
        System.out.println(getLevel1Completed());

        setBackground(Color.GREEN);
    }

    @Override
    public void componentHidden(ComponentEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentMoved(ComponentEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentResized(ComponentEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void componentShown(ComponentEvent e) {
        // this is where the problem is: what I want is that this button is
        // initially not visible as the variable is set to 0
        // but when, in the next pan, I'll set it to 1, this button becomes
        // visible
        if (super.getLevel1Completed() == 1) {
            add(buttonLevel2);
            buttonLevel2.setVisible(true);
            invalidate();
            revalidate();
        }
    }
    }

    class Pan2 extends Level1 {
    JPanel Pan1Window;
    CardLayout LayoutPan1Window;
    JPanel panelCont;
    JButton OpenPan1;
    JButton L1Done;
    int L1Completed;

    public Pan2(final JPanel Pan1Window, final CardLayout LayoutPan1Window,
            final JPanel panelCont, final int L1Completed) {
        this.L1Completed = super.getLevel1Completed();
        OpenPan1 = new JButton("Go back to Pan 1");
        OpenPan1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ApriFinestraLancio) {
                if (ApriFinestraLancio.getSource() == OpenPan1) {
                    LayoutPan1Window.show(panelCont, "1");
                }
            }
        });
        add(OpenPan1);

        L1Done = new JButton("Set Level 1 as Completed");
        L1Done.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent SettaL1Complet) {
                setLevel1Completed(1);
                System.out.println(getLevel1Completed());// this print shows
                                                            // that the value of
                                                            // the variable is
                                                            // correctly changed
                                                            // to 1
            }
        });
        add(L1Done);

        setBackground(Color.RED);
    }
    }

你好,StanislavL,感谢您抽出时间回答!我明白你说的:invalidate+revalidate太过分了,但我到了一个绝望的地步:)我不确定我是否能理解你的其他评论tho:按钮与我设置完成级别的窗口不同。你能帮我了解一下你是如何将按钮设置为从那里可见的吗?