我开发了一个登录窗口,因为我的程序连接到SSH服务器。
启动程序时打开此窗口。但我需要稍后再打开另一台服务器。第二次打开它时,登录窗口冻结了......
有关信息
这是LoginWindow代码:
package com.maxbester.test;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import org.apache.log4j.Logger;
import com.maxbester.test.Server;
@SuppressWarnings("serial")
public class LoginWindow extends JFrame {
private static final Logger LOG = Logger.getLogger(LoginWindow.class);
private Server _server;
private Object _parent;
private JPanel _panel;
private JLabel _loginLabel;
private JTextField _loginInput;
private JLabel _passwordLabel;
private JPasswordField _passwordInput;
private JPanel _buttonPanel;
private JButton _okButton;
private JButton _cancelButton;
public LoginWindow(Object parent, Server server) {
_server = server;
_parent = parent;
initComponents();
}
private void initComponents() {
setTitle("Connection window");
setLayout(new BorderLayout());
_loginLabel = new JLabel("Login: ");
_loginInput = new JTextField(System.getProperty("user.name"), 15);
_passwordLabel = new JLabel("Password: ");
_panel = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
// external padding
c.insets = new Insets(5,5,5,5);
_panel.add(_loginLabel,c);
c.gridx = 1;
_panel.add(_loginInput,c);
c.gridy = 1;
_panel.add(_passwordLabel,c);
c.gridx = 0;
_panel.add(getPasswordLabel(),c);
add(_panel, BorderLayout.CENTER);
_okButton = new JButton("Ok");
_okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
okActionPerformed();
}
});
_cancelButton = new JButton("Cancel");
_cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
_buttonPanel = new JPanel(new FlowLayout());
_buttonPanel.add(_okButton);
_buttonPanel.add(_cancelButton);
add(_buttonPanel, BorderLayout.SOUTH);
pack();
}
/**
* @return the _passwordInput
*/
private JPasswordField getPasswordInput() {
if (LOG.isTraceEnabled()) {
LOG.trace("getPasswordInput()");
}
if (_passwordInput == null) {
_passwordInput = new JPasswordField(15) {
// Give the focus to this field
public void addNotify() {
super.addNotify();
requestFocusInWindow();
}
};
_passwordInput.addKeyListener(new KeyListener() {
@Override public void keyTyped(KeyEvent arg0) {}
@Override
public void keyReleased(KeyEvent keyEvent) {
if (keyEvent.getKeyChar() == KeyEvent.VK_ENTER) {
if (LOG.isTraceEnabled()) {
LOG.trace("Click enter in password field");
}
okActionPerformed();
}
}
@Override public void keyPressed(KeyEvent arg0) {}
});
}
return _passwordInput;
}
protected void okActionPerformed() {
if (LOG.isTraceEnabled()) {
LOG.trace("okActionPerformed()");
}
if (_server != null) {
String login = _loginInput.getText();
if (login != null && !login.isEmpty()) {
_server.setLogin(login);
char[] password = _passwordInput.getPassword();
if (password != null && password.length > 0) {
_server.setPassword(new String(password));
setVisible(false);
synchronized (_parent) {
if (LOG.isTraceEnabled()) {
LOG.trace("syncronized with "+_parent);
}
_parent.notifyAll();
}
} else {
JOptionPane.showMessageDialog(LoginWindow.this,"Please enter a password", "Password required", JOptionPane.WARNING_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(LoginWindow.this,"Please enter your login", "Login required", JOptionPane.WARNING_MESSAGE);
}
} else {
LOG.error("Server is null");
JOptionPane.showMessageDialog(LoginWindow.this,"Server is null.", "An error has occured", JOptionPane.ERROR_MESSAGE);
System.exit(-1);
}
}
}
我存储父类,以便在用户输入登录名和密码时通知它。
Server类非常简单:
package com.maxbester.test;
public class Server {
private String _url;
private String _login = "root";
private String _password = "";
public Server(String url) {
_url = url;
}
public Server(String url, String login, String password) {
_url = url;
if (login != null) {
_login = login;
}
if (password != null) {
_password = password;
}
}
public String getUrl() {
return _url;
}
public String getLogin() {
return _login;
}
public String getPassword() {
return _password;
}
public void setUrl(String url) {
if (url != null) {
_url = url;
}
}
public void setLogin(String login) {
_login = login;
}
public void setPassword(String password) {
_password = password;
}
public boolean hasLogin() {
return _login != null;
}
public boolean hasPassword() {
return _password != null;
}
public String toString() {
return _url;
}
/**
* Test if the server has a login and a password.
* @return Return true if the server has a login and a password, false otherwise.
*/
public boolean hasConnectionId() {
return _login != null && !_login.isEmpty() && _password != null && !_password.isEmpty();
}
}
此窗口由Controller启动:
package com.maxbester.test;
public class Controller {
public Controller() {
Server server = new Server("myserver");
login(server);
}
/**
* <p>This method opens a login window and waits until a signal is receive from
* that window. When the signal is received, closes the window.</p>
* <p>The login window has to update the login and password of 'Server'.</p>
* @param server
*/
private synchronized void askLoginPassword(final Server server) {
server.setLogin(null);
server.setPassword(null);
while (server.hasConnectionId() == false) {
LoginWindow loginWindow = new LoginWindow(Controller.this, server);
try {
loginWindow.setVisible(true);
wait();
} catch (InterruptedException e) {
LOG.error("Thread exception", e);
JOptionPane.showMessageDialog(loginWindow, "Thread exception", "Error", JOptionPane.ERROR_MESSAGE);
} finally {
loginWindow.dispose();
loginWindow = null;
}
}
}
/**
* <p>First of all, this method tests if the server is reachable.</p>
* <p>If it is, the method opens a LoginWindow in order to ask the user ids.</p>
* <p>When we have the information, the function checks if the
* login and password are correct. If they are not, the function repeats the operation.</p>
* @param server
*/
private void login(Server server) {
boolean badLogin = true;
do {
askLoginPassword(server);
try {
// test if password is OK, if it is not, throw exception
badLogin = false;
} catch (Exception e) {
badLogin = true;
LOG.error(e.getMessage(), e);
JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
} while(badLogin);
}
}
答案 0 :(得分:0)
有点不清楚精确发生了什么(特别是wrt线程) - 但我认为你应该去看看SwingWorker文档,看看如何处理长时间运行的任务,
很难看出哪个是长时间运行的方法(我假设这已被注释掉了) - 但这可能需要与GUI线程保持分离。
此外,您何时期望登录窗口消失? - 在您收到服务器的回复之后或之前。
(根据评论编辑)