2017-05-05 8 views
2

MVCデザインパターンを使用しています(またはしようとしています)。 私は自分のビジネスとコントローラを気にするUIクラスを持っています。コントローラは、ビューを制御します。Java Swing ActionListenerが動作せず、コンストラクタが停止しています

コントローラクラスにActionListenerを登録すると、動作しません。デバッグが表示されているように、コンストラクタはJDialogのコンストラクタを呼び出した後でさえも終了しません。多くのseneseをしない記述として

、ここで私のクラスは次のとおりです。

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); 
     } 
    } 
} 

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; 
    } 
} 

これは、ビューを担当するコントローラである:

はこれが表示されますコンストラクタでは、actionListenersは起動しません。 _parent =親行にブレークポイントを設定した場合、プログラムはAuthenticationWindowであるJDialogeを閉じると停止します。

面白いことに、このように動作する2つのクラスがあります。必要があれば、私はここに掲示するでしょう。私にお知らせください。

ありがとうございました!

答えて

3

問題は、ダイアログが閉じられるまで、モーダルダイアログの表示が現在のスレッドを「停止」することです。以下のようにこの問題を回避するには、アプリケーションを再設計する必要があります

1)show

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

3)の変更と呼ばれるAuthenticationWindowで新しい方法を)AuthenticationWindow

2のコンストラクタからライン_window.setVisible(true);を削除作成しますAuthenticationWindowController

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

fu rtherヒント:

まずは、ActionをActionListenerに置き換えてください。セカンダリ:コントローラはGUIウィジェットでは動作しません。ですから、setValidator()のような高レベルのメソッドをコントローラからUIに転送する方が良いでしょう(この場合、UIでアクションを直接作成して登録することができます)。また、パスワードとログインにアクセスするメソッドを作成します(入力するためのフィールドではありません)。

+0

素晴らしい!ありがとうございました!私はどのメソッドがスレッドを停止しているか分からなかった。 Dialogを新しいスレッドに入れるのも同じですか? – Timbo

+0

いいえ。スイングはシングルスレッドのlibです。私の答えに追加したヒントもいくつかお読みください。 –

関連する問題