2017-05-05 35 views
2

我正在使用(或試圖)使用MVC設計模式。 所以我有一個UI類,只是介意自己的業務和一個控制器,以及控制視圖。Java Swing ActionListener不工作並停止構造函數

當我在控制器類中註冊一個ActionListener時,它不起作用。調試似乎顯示,構造函數甚至在調用JDialog的構造函數後都沒有變化。

作爲描述並沒有太大的senese,這裏有我的課:

這是視圖:

package view; 

import javax.swing.*; 
import java.awt.*; 

/** 
* Created by Timbo on 04.05.17. 
* This window will be used to authenticate library members and allow them to access staff functions 
*/ 
public class AuthenticationWindow 
{ 
    /** 
    * The window that holds the authentication content 
    */ 
    private JDialog _window; 

    /** 
    * This Panel holds the fields required for the input of username and password 
    */ 
    private JPanel _textFieldPanel; 

    /** 
    * This panel will hold the buttons 
    */ 
    private JPanel _buttonPanel; 

    /** 
    * The textfield in which the username can be entered 
    */ 
    private JTextField _userName; 

    /** 
    * The field, in which the password can be entered 
    */ 
    private JPasswordField _password; 

    /** 
    * Holds a string to hint for the username 
    */ 
    private JLabel _usernameHint; 

    /** 
    * Holds a string to hint for the password 
    */ 
    private JLabel _passwordHint; 

    /** 
    * A Button that will trigger the login process 
    */ 
    private JButton _confirm; 

    /** 
    * A Button that will cancel the login process 
    */ 
    private JButton _cancel; 


    /** 
    * Creates a new Authentication Window in which a user can authenticate to get staff clearance 
    * @param parent The parent frame of this Window 
    */ 
    public AuthenticationWindow(Frame parent) 
    { 
     //Initialize all the components 
     _window = new JDialog(parent, "Please Authenticate", true); 
     _textFieldPanel = new JPanel(new GridLayout(2, 2)); 
     _buttonPanel = new JPanel(new FlowLayout()); 
     _userName = new JTextField(); 
     _password = new JPasswordField(); 
     _passwordHint = new JLabel("Password"); 
     _usernameHint = new JLabel("Username"); 
     _confirm = new JButton("Confirm"); 
     _cancel = new JButton("Cancel"); 

     //Assemble the textfield panel 
     _textFieldPanel.add(_usernameHint); 
     _textFieldPanel.add(_userName); 
     _textFieldPanel.add(_passwordHint); 
     _textFieldPanel.add(_password); 

     //Assemble the button panel 
     _buttonPanel.add(_cancel); 
     _buttonPanel.add(_confirm); 

     //Assemble the window 
     _window.setLayout(new BoxLayout(_window.getContentPane(), BoxLayout.PAGE_AXIS)); 
     _window.add(_textFieldPanel); 
     _window.add(_buttonPanel); 

     //Configure the window 
     Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 
     _window.setLocation(dim.width/2-_window.getSize().width/2, dim.height/2-_window.getSize().height/2); 
     _window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); 
     _window.pack(); 

     //Show window 
     _window.setVisible(true); 
    } 

    //All the getter methods for this class 
    public JDialog getWindow() 
    { 
     return _window; 
    } 

    public JTextField getUsernameInput() 
    { 
     return _userName; 
    } 

    public JPasswordField getPasswordInput() 
    { 
     return _password; 
    } 

    public JButton getConfirm() 
    { 
     return _confirm; 
    } 

    public JButton getCancel() 
    { 
     return _cancel; 
    } 
} 

這是負責的視圖控制器:

package controller.start.viewController; 

import view.AuthenticationWindow; 
import view.ErrorScreen; 

import javax.swing.*; 
import java.awt.*; 
import java.util.Observable; 

/** 
* Created by Timbo on 05.05.17. 
* This is the controller class for the Authentication window. It handles updates and functionality for the view 
*/ 
public class AuthenticationWindowController extends Observable 
{ 
    private static final char[] PASSWORD = {'T', 'o', 'r', 'v', 'a', 'l', 'd', 's'}; 
    /** 
    * The view that holds the components 
    */ 
    private AuthenticationWindow _ui; 

    /** 
    * The parent frame of this view 
    */ 
    private Frame _parent; 

    public AuthenticationWindowController(Frame parent) 
    { 
     _ui = new AuthenticationWindow(parent); 
     _parent = parent; 
     registerListener(); 
    } 

    private void registerListener() 
    { 
     _ui.getConfirm().addActionListener(e -> {checkInput();}); 
     _ui.getCancel().addActionListener(e -> {_ui.getWindow().dispose(); System.out.println("Window disposed");}); 
    } 

    /** 
    * This method checks the input and gives feedback to the user in case the input was wrong 
    * If the input was correct the user is being authenticated as staff and can access the staff view in the start window 
    */ 
    private void checkInput() 
    { 
     String username = _ui.getUsernameInput().getText(); 
     char[] password = _ui.getPasswordInput().getPassword(); 

     if (username.isEmpty()) 
     { 
      new ErrorScreenController(_parent, ErrorScreen.USERNAME_ERROR); 
     } 
     else if (password.length == 0) 
     { 
      new ErrorScreenController(_parent, ErrorScreen.PASSWORD_ERROR); 
     } 
     else if ((username.equalsIgnoreCase("linus")) || (password.equals(PASSWORD))) 
     { 
      this.setChanged(); 
      this.notifyObservers(); 
     } 
     else 
     { 
      new ErrorScreenController(_parent, ErrorScreen.WRONG_CREDENTIALS); 
     } 
    } 
} 

在構造函數中,actionListener不會觸發。 如果我爲_parent = parent行設置了一個斷點,那麼當我關閉作爲AuthenticationWindow的JDialoge時,程序只會停止。

有趣的是我有兩個其他類以這種方式工作。如果需要,我會在這裏發佈。請告訴我。

謝謝你的幫助!

回答

3

你的問題是顯示一個模態對話框「停止」當前線程,直到對話框關閉。爲了避免這個問題,你應該重新設計你的應用程序如下:

1)從AuthenticationWindow

2構造函數刪除行_window.setVisible(true);)創建AuthenticationWindow一種新的方法叫做show

public void show() { 
    _window.setVisible(true); 
} 

3)改變AuthenticationWindowController的構造函數

public AuthenticationWindowController(Frame parent) 
{ 
    _ui = new AuthenticationWindow(parent); 
    _parent = parent; 
    registerListener(); 
    _ui.show(); 
} 

有些fu另外提示:

首先將Action更改爲ActionListener。次要的:您的控制器不應該使用GUI小部件。因此,最好爲您的UI提供一些高級方法,如setValidator()將您的驗證功能從控制器傳輸到UI中(在這種情況下,您可以直接在UI中創建並註冊操作)。還要使該方法訪問密碼和登錄(而不是輸入它們的文件)。

+0

太棒了!謝謝!我不確定哪種方法會停止線程。將對話框放在一個新的線程中是否也一樣? – Timbo

+0

編號Swing是單線程庫。還請閱讀我已添加到我的答案中的一些其他提示。 –