2017-05-05 33 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是单线程库。还请阅读我已添加到我的答案中的一些其他提示。 –