java - 卡片布局 : How to get an event to start only when a particular card is displayed?

标签 java swing timer cardlayout

我正在使用 CardLayout 来显示一系列问题。对于每个问题,标签上都会显示一个计时器。我通过了主课的问题和每个问题的时间限制。

//Reference - SynforgeTutorials
public class Quiz extends JFrame{
    JPanel p=new JPanel();
    CardLayout cards=new CardLayout();
    int numQs;


    int cardnumber;

    CL1 questions[];



    public static void main(String[] args) {

        String[] messages = {"What is area of a circle?","When does spring start?","When is the next leap year?","How many days in a week?","What causes seasons?"};
        int[] mins = {1,2,0,1,1};
        int[] secs = {30,0,30,0,0};
        new Quiz(messages,mins,secs);
    } 

    public Quiz(String messages[],int mins[],int secs[]){


        questions = new CL1[messages.length];

        for(int i=0;i<questions.length;i++)
        {
        questions[i] = new CL1(messages[i],mins[i],secs[i],this);

        }

        p.setLayout(cards);

        numQs=questions.length;
        for(int i=0;i<numQs;i++){
            p.add(questions[i],"q"+i);
        }

        cardnumber = 0;

        cards.show(p,"q"+ cardnumber);


        add(p);
        setVisible(true);


    }

    public void OK(){
        if(cardnumber==(numQs-1)){

            this.dispose();

        }
        else{

            cardnumber = cardnumber + 1;
            cards.show(p,"q"+ cardnumber);
        }
    }

}

这是构造卡片的类。它有 3 个面板 - 顶部面板显示问题,中间面板在标签上显示分钟和秒以及暂停和恢复按钮,底部面板显示确定按钮。单击“确定”按钮后,将显示下一张卡片。

public class CL1 extends JPanel implements ActionListener {

    int correctAns;

    Quiz quiz;
    int selected;
    boolean used;

    private Timer myTimer1;
    public long initialTimeInSecs;
    public long elapsedTime;
    public long convertToSecs;
    public String minutes;
    public String seconds;
    public String clockTimeString; 
    public static final int ONE_SEC = 1000;
    Font myClockFont = new Font("Serif", Font.PLAIN, 20);




    //Message
    JPanel qPanel=new JPanel();

    //Timer
    JPanel tPanel=new JPanel();
    JLabel timeLbl = new JLabel("New label");
    JButton btnPause=new JButton("Pause");
    JButton btnResume=new JButton("Resume");


    //bottom
    JPanel botPanel=new JPanel();
    JButton OK=new JButton("OK");



    public CL1(String q, int userMinutes, int userSeconds, Quiz quiz){

        this.quiz=quiz;

        setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));


        //Message
        qPanel.add(new JLabel(q));
        add(qPanel);


        //Timer
        convertToSecs = (userMinutes * 60) + userSeconds;

        initialTimeInSecs = convertToSecs;
        elapsedTime = initialTimeInSecs;

        seconds = Integer.toString((int)(elapsedTime % 60));
        minutes = Integer.toString((int)((elapsedTime % 3600) / 60));
        if (seconds.length() < 2)
            seconds = "0" + seconds;
        if (minutes.length() < 2)
            minutes = "0" + minutes;
        clockTimeString = (minutes+":"+seconds).toString();

        timeLbl.setText(clockTimeString);
        timeLbl.setFont(myClockFont);
        timeLbl.setBorder(raisedbevel);

        myTimer1 = new Timer(ONE_SEC,new ActionListener() {
            public void actionPerformed(ActionEvent evt) {

                initialTimeInSecs = initialTimeInSecs - 1;

                elapsedTime = initialTimeInSecs;

                String seconds = Integer.toString((int)(elapsedTime % 60));
                String minutes = Integer.toString((int)((elapsedTime % 3600) / 60));


                if (seconds.length() < 2)
                    seconds = "0" + seconds;

                if (minutes.length() < 2)
                    minutes = "0" + minutes;

                clockTimeString = (minutes+":"+seconds).toString();

                timeLbl.setText(clockTimeString);

                if(clockTimeString.equals("00:00"))
                {
                    myTimer1.stop();

                }
                } 

          });

        myTimer1.start(); 



        btnPause.addActionListener(new java.awt.event.ActionListener() 
        {
            public void actionPerformed(java.awt.event.ActionEvent evt) 
            {   
                PauseBtnActionPerformed(evt);
            }
        });



        btnResume.addActionListener(new java.awt.event.ActionListener() 
        {
            public void actionPerformed(java.awt.event.ActionEvent evt) 
            {   
                ResumeBtnActionPerformed(evt);
            }
        });

        tPanel.add(timeLbl);
        tPanel.add(btnPause);
        tPanel.add(btnResume);

        add(tPanel);


        //bottom

        OK.addActionListener(this);

        botPanel.add(OK);

        add(botPanel);
    }

    public void actionPerformed(ActionEvent e){
        Object src=e.getSource();
        //OK button
        if(src.equals(OK)){

            quiz.OK();}

    }

    public void PauseBtnActionPerformed(java.awt.event.ActionEvent evt)
    {
        myTimer1.stop();
    }

    public void ResumeBtnActionPerformed(java.awt.event.ActionEvent evt)
    {
        myTimer1.start();
    }
}

计时器似乎不会随着每张新卡而刷新。每张卡都是并行开始的,这样当我从一张卡转到下一张卡时,新卡会显示第一张卡上已经过去的时间。

例如,对于问题 1,时间限制为 1.30 对于问题 2,时间限制为 2.00 对于问题 3,时间限制为 3.00

对话框首先显示第一个标签,并从 1.30 开始向下滴答。假设我在该标签上停留了 10 秒,然后按“确定”。

然后显示第二个标签,并且计时器开始从 1.50 开始计时(2.00-0.10,而不是 2.00)。假设我在这个问题上停留 25 秒,然后按“确定”。

然后显示第三个标签,计时器开始从 2.25 开始计时(3.00-(0.10+0.25),而不是 3.00)。

我想做两件事:

  1. 我希望每张卡片的计时器仅在显示该卡片时启动。
  2. 我希望卡在时间限制达到 00:00 后自动更改为下一张卡。

任何建议都会有帮助。提前致谢!

最佳答案

I want the timer for each card to start only when that card is shown.

您可以使用HierarchyListener来监听每张卡片可见性的变化:

@Override
public void hierarchyChanged(HierarchyEvent e)
{
    JComponent component = (JComponent)e.getSource();

    if ((HierarchyEvent.SHOWING_CHANGED & e.getChangeFlags()) != 0
    &&  component.isShowing())
    {
        // start the Timer
    }
}

因此,您需要将 HierarchyListener 添加到添加到 CardLayout 的每个面板。

I want the card to automatically change to the next card

CardLayout 支持“下一张卡”功能,因此您只需在计时器达到 0 时调用相应的方法即可。

关于java - 卡片布局 : How to get an event to start only when a particular card is displayed?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29479134/

相关文章:

java - 我们可以在另一个类中传递注入(inject)的对象吗

java - 在 Swing 中捕获热键

java - 如何在静态方法中将 ActionLister 添加到按钮

c - 如何正确使用timerfd?

java - Android Studio 如何在屏幕上打印可变内容(数字)

java - 我恢复了已删除的 .class 文件,但是当我尝试使用 java 运行它时,它给出了 classFormatException?

java - Log4J Swing 附加程序

JavaScript 定时器性能

java - LibGDX - 尝试在我的游戏中显示可见的计时器

Java奇怪的NoClassDefFoundError