2015-04-06 57 views
2

我正在使用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秒後再按'OK'。

然後顯示第三個標籤,並且計時器從2.25(3.00-(0.10 + 0.25),而不是3.00)開始滴答滴答。

我想要做的兩件事情:

  1. 我要當顯示卡​​每張卡計時器纔開始。
  2. 我想讓卡片在時間限制到達00:00時自動切換到下一張卡片。

任何建議將有所幫助。提前致謝!

回答

4

我希望每張卡的計時器只有在顯示該卡時才能啓動。

可以使用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面板。

我想該卡自動切換到下一張卡片

CardLayout支持「忘詞」的功能,所以你只要調用相應的方法,當計時器達到0

+0

非常感謝您的幫助。我能夠爲每張卡單獨啓動計時器。關於第二部分,一旦計時器達到0,我如何更換下一張卡?卡正在從容器類中更改,其中計時器位於被調用類的其中一個面板中。 – sanaku

+0

@sanaku,閱讀'CardLayout' API。它支持「下一個」卡功能,所以你只需調用下一個(...)方法。 – camickr

相關問題