2016-03-21 2 views
0

все. У меня 4 класса; FrameViewerOne - это то, где я запускаю приложение, FrameBuilderOne содержит большую часть кода, включая двоичный поиск и многое другое. Класс Person реализует сопоставимые, и я переопределяю его с помощью метода compareTo(), и мой класс TimerLockout - это тот, с которым я переключаюсь с окном, которое должен заселить, заблокировать пользователя в течение 15 секунд и показать обратный отсчет, пока таймер закроется. Это должно произойти после 3 неправильных попыток пользователя. Когда таймер достигает 0 секунд, я хочу, чтобы он закрыл класс TimerLockout и снова открыл (setVisible) исходный кадр. К сожалению, мой код компилируется, но я не могу заставить таймер заполнить. Спасибо за ваше время, и любая помощь/предложения были бы очень признательны!Окно Java Swing Timer не заполняет

Вот инструкции: 1) Использование «счетчика», чтобы разрешить пользователю 3 неудачных попытки. 2) Если пользователь три раза вводит правильную информацию, система блокируется в течение 15 секунд. 2.1). Вы должны показать окно обратного отсчета только по секундам, а не по всему системному времени.

//FRAMEVIEWERONE CLASS 
import javax.swing.JFrame;//The Frame class is part of the javax.swing package.Swing is the nickname for the gui onterface library in java. 
import java.io.*; 
public class FrameViewerOne 
{ 
    public static void main(String[] args)throws IOException{//This is a warning to the compiler that we are throwing an exception! Proper syntax is to have this AFTER the method header. 
    { 
     JFrame Frame1 = new FrameBuilderOne(); 
     Frame1.setVisible(true); 
     Frame1.setSize(200,300); 
     Frame1.setTitle("Lab One GUI"); 
     Frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//This adds the x button on the top right. If you omit this step, the program will keep running even after you close the frame. 
    } 
    } 
} 

//FRAMEBUILDERONE CLASS 
import javax.swing.*;//The asterik(*) tells Java to import everything that is being used in the package. 
import java.awt.event.*;//Has the ActionEvent and KeyEvent. awt: Abstract Window Toolkit 
import java.awt.event.ActionListener; 
import java.util.*;//This does not have an asterik because I am only importing a specific tool (Scanner) from the java package,util. Scanner is the namespace of the package 
import java.io.*; //Always use IOException when working with files. FileNotFoundException is a specific IO Exception. Exceptions are objects. 
import javax.swing.BoxLayout; 
import javax.swing.JPasswordField; 
import javax.swing.border.EtchedBorder; 
import javax.swing.border.TitledBorder; 

public class FrameBuilderOne extends JFrame{ 
    private JButton loginBtn, exitBtn; 
    private JPanel newPanel, userNamePanel, passWordPanel, studentIdPanel, buttonPanel; 
    private JTextField usernameTextField; 
    private JPasswordField passwordTextField; 
    private JTextField studentIdTextField; 
    private JLabel usernameLabel, passwordLabel, studentIdLabel; 
    ArrayList<Person> personAry; 
    private int attempts; 

    public FrameBuilderOne()//Constructor 
    { 
    createPanel();//Method Call 
    personAry = checkInfo(new File("USERDATA.txt")); 
    Collections.sort(personAry); 
    } 

    private void createPanel()//Actual Method being called 
    { 
    newPanel = new JPanel();//The reserve word, new, denotes that a constructor method is being called 
    newPanel.setBorder(new EtchedBorder()); 
    newPanel.setBorder(new TitledBorder(new EtchedBorder())); 
    newPanel.setLayout(new BoxLayout(newPanel, BoxLayout.Y_AXIS)); 

    userNamePanel = new JPanel(); 
    usernameLabel = new JLabel("Username:"); 
    userNamePanel.add(usernameLabel); 

    usernameTextField = new JTextField(10); 
    userNamePanel.add(usernameTextField); 

    newPanel.add(userNamePanel); 

    passWordPanel = new JPanel(); 
    passwordLabel = new JLabel("Password:"); 
    passWordPanel.add(passwordLabel); 

    passwordTextField = new JPasswordField(10); 
    passWordPanel.add(passwordTextField); 

    newPanel.add(passWordPanel); 
    passwordTextField.setEchoChar('*'); 

    studentIdPanel = new JPanel(); 
    studentIdLabel = new JLabel("Student ID:"); 
    studentIdPanel.add(studentIdLabel); 
    studentIdTextField = new JTextField(10); 
    studentIdPanel.add(studentIdTextField); 

    newPanel.add(studentIdPanel); 

    buttonPanel = new JPanel(); 
    loginBtn = new JButton("Login"); 
    buttonPanel.add(loginBtn); 

    exitBtn = new JButton("Exit"); 
    buttonPanel.add(exitBtn); 

    newPanel.add(buttonPanel); 

    ActionListener LoginListener = new ButtonsListen();//Create One Method since since both login and exit buttons share the same/similar task. 
    loginBtn.addActionListener(LoginListener); 
    exitBtn.addActionListener(LoginListener); 

    add(newPanel); 
    } 

    public ArrayList<Person> checkInfo(File data) 
    { 
    Scanner userInput; 
    ArrayList <Person> loginAry = new ArrayList<Person>(); 
    try 
     { 
     userInput = new Scanner(data);//The reason why this isn't System.in is because you aren't taking input from the keyboard. You are scanning the file. 
     while (userInput.hasNextLine()) 
     { 
      String finder = userInput.nextLine(); 
      String [] loginInfo = finder.split(",");//This is a delimeter 
      String usernameInfo = loginInfo [0]; 
      String passwordInfo = loginInfo [1]; 
      long studentIdInfo = Long.parseLong(loginInfo[2]); 

      Person moreInfo = new Person(usernameInfo, passwordInfo, studentIdInfo); 
      loginAry.add(moreInfo); 
     } 
     userInput.close(); 
    } 
    catch (FileNotFoundException e){ 
    JOptionPane.showMessageDialog(null, "Error" + e.getMessage()); 
    } 
    return loginAry; 
    } 

    public class Verify 
    { 
    /** 
    * This method implements the binary search within the personAry which contains the user's attributes. 
    * @param Person info - this is the information of the object Person which contains the username, password, and studentID. 
    * @return - this method returns true if info within Person is found. This returns it to the other method which displays the appropriate message to the user. 
    */ 
    public boolean validate(Person info) 
    { 
     int low = 0; 
     int high = personAry.size()-1; 
     int mid; 
     while(low <= high) 
     { 
     mid = (low + high)/2; 
     Person middlePerson = personAry.get(mid); 
     int position = middlePerson.compareTo(info); 
     if(position < 0) 
     { 
      low = mid + 1; 
     } 
     else if(position > 0) 
     { 
      high = mid - 1; 
     } 
     else 
     { 
      return true; 
     } 
    } 
    return false; 
    } 
} 

    public boolean validatePassword(String passwordSaver)//Check the password minimum, case sensitivity, and number in password 
    { 
    int caseCount=0; 
    int numCount=0; 
    if(passwordSaver.length() < 10) 
    { 
     JOptionPane.showMessageDialog(null, "Password must have ten characters"); 
    } 
    else if(passwordSaver.length() >= 10) 
     for(int i = 0; i < passwordSaver.length(); i++) 
     { 
     char current = passwordSaver.charAt(i); 
     if(Character.isUpperCase(current)) {caseCount++;} 
     else if(Character.isDigit(current)){numCount++;} 
     } 
    if(caseCount == 0) 
    { 
     JOptionPane.showMessageDialog(null, "Password must have at least one uppercase character"); 
     return false; 
    } 
    else if (numCount == 0) 
    { 
     JOptionPane.showMessageDialog(null, "Password must have at least one uppercase character"); 
     return false; 
    } 
    else 
    { 
     return true; 
    } 
    } 
public void createTimerClass() 
{ 
    this.setVisible(false); 
    TimerLockout Frame2 = new TimerLockout(this); 
} 

public class ButtonsListen implements ActionListener{ 
    public void actionPerformed(ActionEvent e){ 

    if(e.getSource()==loginBtn) 
    { 
     String username = usernameTextField.getText(); 
     String id_str = studentIdTextField.getText(); 
     long number = Long.parseLong(id_str); 
     String password; 

     char[] passArray = passwordTextField.getPassword(); 
     password = new String(passArray);//Study this, write it out 

     Person txtFieldInfo = new Person(username, password, number); 

     Verify verifyLogin = new Verify(); 

     if (!validatePassword(password))//also tells the user what went wrong 
     { 
     attempts++; 
     if(attempts == 3) 
     { 
      createTimerClass(); 
      attempts = 0; 
     } 
     } 

     if (verifyLogin.validate(txtFieldInfo)) 
     { 
     JOptionPane.showMessageDialog(null, "Login Successful");//JOptionPane is in the swing package. You must include null, before the message you want to display. 
     } 

     else 
     { 
     JOptionPane.showMessageDialog(null,"Invalid Login Information"); 
     } 
    } 

    if (e.getSource()==exitBtn) 
    { 
     JOptionPane.showMessageDialog(null, "Program Shutting Down"); 
     System.exit(0); 
    } 
    } 
} 
} 

//PERSON CLASS 
public class Person implements Comparable <Object>//The Comparable interface automatiically populates an empty CompareTo method behind the scenes. 
{ 
    private String username; 
    private String password; 
    private Long StudentID; 

    public Person(String User, String Pass, Long ID) 
    { 
    this.username = User; 
    this.password = Pass; 
    this.StudentID = ID; 
    } 
    public int compareTo(Object otherPerson)//Within the CompareTo method, you must pass in an object. This is overriding the empty CompareTo Method. 
    { 
    Person other = (Person) otherPerson;//You need to cast an object. tempStorage is going to store the username, password, and studentID. 

    if(other.StudentID > this.StudentID) 
    { 
     return 1; 
    } 
    else if(other.StudentID < this.StudentID) 
    { 
     return -1; 
    } 
    else 
    { 
     return 0; 
    } 
    } 

    public String getPassword() 
    { 
    return this.password; 
    } 

    public String getUsername() 
    { 
    return this.username; 
    } 

    public Long getStudentID() 
    { 
    return this.StudentID; 
    } 
} 

//TimerLockout Class 
import javax.swing.Timer; 
import javax.swing.*; 
import java.awt.event.*; 
import java.awt.event.ActionListener; 
public class TimerLockout extends JFrame 
{ 
    private Timer timerLock; 
    private final int STARTING_TIME = 15; 
    private int currentTime = 15; 
    private final int ENDING_TIME = 0; 
    private FrameBuilderOne Frame1; 
    private JPanel secondPanel; 
    private JLabel timerMessage; 

    public TimerLockout(FrameBuilderOne previousFrame) 
    { 
    TimeListener listener = new TimeListener(); 
    timerLock = new Timer(1000, listener); 
    Frame1 = previousFrame; 
    createSecondPanel(); 
    } 

    private void createSecondPanel() 
    { 
    JPanel secondPanel = new JPanel(); 

    timerMessage = new JLabel("You Are Temporarily Locked Out"); 
    secondPanel.add(timerMessage); 

    ActionListener TimeListener = new TimeListener(); 
    } 

    public class TimeListener implements ActionListener 
    { 
    public void actionPerformed(ActionEvent t) 
    { 

     while(currentTime >= STARTING_TIME) 
     { 
     currentTime--; 
     } 
     if(ENDING_TIME == 0) 
     { 
     Frame1.setVisible(true); 
     dispose(); 
     } 
    } 
    } 
}` 
+0

ваше время цикла в вашем 'TimerListener' это плохая идея, и заставит ваш пользовательский интерфейс, чтобы стать responvie – MadProgrammer

+0

Я не понимаю, как и почему это было бы неплохо, не могли бы вы объяснить? Я реализовал цикл while, потому что я хочу уменьшить время (15 секунд) на 1 секунду, пока не достигнет 0, в котором он отобразит gui для повторения попытки пользователя. Что я должен сделать, чтобы сделать мой код более эффективным? Я изменил оператор if на –

+0

if (currentTime == ENDING_TIME) {...} –

ответ

2

К сожалению, мой код компилируется, но я не могу получить таймер для заполнения

Вы никогда не начать Timer ...

public class TimerLockout extends JFrame { 
    //... 
    public TimerLockout() { 
     TimeListener listener = new TimeListener(); 
     timerLock = new Timer(1000, listener); 
     createSecondPanel(); 
     // This would be helpful 
     timerLock.start(); 
    } 

Я надеваю Не понимаю, почему окно таймера не отображается после 3 неудачных попыток входа в систему.

Вы никогда не сделать рамку видимой ...

public void createTimerClass() { 
    this.setVisible(false); 
    TimerLockout Frame2 = new TimerLockout(); 
    // ?? 
} 

Может быть что-то вроде ...

TimerLockout Frame2 = new TimerLockout(); 
Frame2.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 
Frame2.pack(); 
Frame2.setLocationRelativeTo(null); 
Frame2.setVisible(true); 

Но мой TimerLock кадр пуст/на самом деле, очень мало (прогноз)

Этот потому что вы никогда не добавить secondPanel к TimerLockout

public TimerLockout() { 
    TimeListener listener = new TimeListener(); 
    timerLock = new Timer(1000, listener); 
    createSecondPanel(); 
    add(secondPanel); 
    timerLock.start(); 
} 

Когда TimerLockout бросает NullPointerException?! (Предсказание)

Это потому, что вы затенения secondPanel в createSecondPanel так что поле экземпляра null при добавлении его к раме ...

private void createSecondPanel() { 
    // Well, there's your problem?! 
    //JPanel secondPanel = new JPanel(); 
    secondPanel = new JPanel(); 

    timerMessage = new JLabel("You Are Temporarily Locked Out"); 
    secondPanel.add(timerMessage); 
} 

Мои TimerLockout окно закрывается через 1 секунду ?!(Предсказание)

Это потому, что логика в вашем TimeListener неправильно

public class TimeListener implements ActionListener { 

    public void actionPerformed(ActionEvent t) { 

     System.out.println(">> currentTime = " + currentTime + "; STARTING_TIME = " + STARTING_TIME); 
     while (currentTime >= STARTING_TIME) { 
      currentTime--; 
     } 
     System.out.println("<< currentTime = " + currentTime + "; STARTING_TIME = " + STARTING_TIME); 
     if (ENDING_TIME == 0) { 
      dispose(); 
     } 
    } 
} 

Давайте делать некоторые Бенчмаркинг

+--------+---------------+-------------+-------------+ 
| loop | STARTING_TIME | currentTime | ENDING_TIME | 
+--------+---------------+-------------+-------------+ 
| <init> | 15   | 15   | 0   | 
+--------+---------------+-------------+-------------+ 
| 1  | 15   | 15   | 0   | 
+--------+---------------+-------------+-------------+ 
| 2  | 15   | 14   | 0   | 
+--------+---------------+-------------+-------------+ 
| 3  | 15   | 14   | 0   | 
+--------+---------------+-------------+-------------+ 

Подождите, что? Почему обновление currentTime? Потому что когда-то currentTime больше не >=STARTING_TIME, он никогда не уменьшает ... кроме того, первый раз Timer не называет ActionListener, вы будете распоряжаться кадром (без остановки Timer), потому что ENDING_TIME всегда 0

Вместо этого, не надо больше похоже ...

public class TimeListener implements ActionListener { 

    public void actionPerformed(ActionEvent t) { 
     currentTime--; 
     if (currentTime <= ENDING_TIME) { 
      dispose(); 
      timer.stop(); 
     } 
    } 
} 

более простым решением было бы просто использовать modalJDialog вместо JFrame для TimerLockOut класса, это будет означать, что вам больше не нужно жонглировать идения Билити состояние главного окна, в диалоговом окне будет препятствовать вам взаимодействовать с дочерними окнами, пока он не расположен

Другой вариант заключается в использовании API JLayer/JXLayer и генерировать «запертой» эффект, for example и example или вы могли бы создать glassPane, который потребляет события мыши, for example

+0

Большое вам спасибо. Мне жаль, что у меня не было такого наставника, как ты. Для Frame2.pack(); - что это делает? Кроме того, что делает setLocationRelativeTo (null); делать? Почему параметр null? Это похоже на использование JOptionPaneShowMessageDialog (null, параметр)? –

+0

['pack'] (https://docs.oracle.com/javase/8/docs/api/java/awt/Window.html#pack--) *" Приводит к тому, что это окно будет иметь размер, соответствующий размеру и макеты его подкомпонентов. Полученная ширина и высота окна автоматически увеличиваются, если любой из размеров меньше минимального размера, указанного предыдущим вызовом методу setMinimumSize. »* – MadProgrammer

+0

' setLocationRelativeTo (null); 'является трюк, в том случае, когда 'null', API использует экранное устройство и будет, основываясь на текущем размере окна, центрировать его на экране – MadProgrammer

2

Я думаю, что проблема в том, что вы никогда не запускаете таймер. А также, что secondPanel нигде не отображается. Вы создаете экземпляр, но вы не добавляете его ни к какому кадру.

public TimerLockout(FrameBuilderOne previousFrame) { 
     TimeListener listener = new TimeListener(); 
     timerLock = new Timer(1000, listener); 
     Frame1 = previousFrame; 
     createSecondPanel(); 

     timerLock.start(); // <- START TIMER 
} 

private void createSecondPanel() { 
     JPanel secondPanel = new JPanel(); 

     timerMessage = new JLabel("You Are Temporarily Locked Out"); 
     secondPanel.add(timerMessage); 

     // ActionListener TimeListener = new TimeListener(); ONLY NEED ONE LISTENER 
     // we have lost secondPanel. It does not show anywhere 
}