проблеми:
- Първо и най-важно, вие смесвате Swing и конзолен код в една и съща програма и по лош начин. Разберете, че конзолата (използваща обект на скенер, базиран на System.in) е "линеен" код, код, при който програмистът изцяло насочва посоката на потока на програмата, където често използваме "блокиращ" код, за да получим въвеждане от потребителя, код, който напълно блокира програмата поток, докато не бъде въведен вход, и това работи добре с вашия цикъл while. Кодът на Swing GUI (и повечето GUI) от друга страна е предимно нелинеен код, управляван от събития, код, при който потребителят има много по-голям контрол върху това кой код кога се извиква, код, който най-вече избягва блокиране на потока от код (с изключение на на модални диалози).
- Ако абсолютно трябва да комбинирате двете, тогава не трябва да не използвате JFrame, тъй като показването на JFrame няма да постави на пауза цикъла while и ще се повтаря безкрайно, а не в добър смисъл. Вместо това ще трябва да използвате Swing версията на блокиращия код, модален диалог, или с JDialog, или с JOptionPane. Те ще поставят на пауза цикъла while, позволявайки много по-чист и линеен вход.
- И без значение кой използвате, никой от кода на потребителския интерфейс не трябва да бъде в рамките на потребителския клас. Този клас трябва да съдържа състоянието (полета) и поведението (методи) на отделен потребител, но отново не трябва да включва UI код. Това принадлежи другаде; в противен случай ще се окажете с ужасна смесица от спагети код, който трудно се отстранява и подобрява. Затова дайте на вашия потребител неговите полета, включително име и ранг, дайте му потребителски методи, които главната програма може да извика, когато иска потребителят да направи нещо, но поставете вашия UI код в главния метод.
- Насочете своя Swing GUI към създаване на JPanel, след което можете да поставите JPanel навсякъде, където е необходимо, което прави кода много по-гъвкав. Например, ако сте направили това, можете да поставите JPanel в JOptionPane, което означава, че ще се покаже като модален диалогов прозорец, блокиращ цикъла while, точно както искате.
- Малка забележка: избягвайте използването на полета String за пароли. Това прави вашата програма много лесна за проникване и не е добър навик.
Така че отново, ако абсолютно трябва да смесвате Swing и конзола, бих направил нещо подобно:
Първо класът User.java. Отново, фокусирайте се само върху състоянието и поведението на потребителя:
public class User {
private int rank;
private String name;
private char[] pass; // ***** Don't store password as a String
// ?? other fields if needed
public User(String name, char[] pass) {
this.name = name;
this.pass = pass;
}
public void setRank(int rank) {
this.rank = rank;
}
public int getRank() {
return rank;
}
public String getName() {
return name;
}
// again, if this were a real-world program, you wouldn't make password accessible
public char[] getPass() {
return pass;
}
// other User methods would go here
@Override
public String toString() {
return "User [rank=" + rank + ", name=" + name + "]";
}
// you'll want to override equals(Object o) and hashCode() here
}
След това можете да създадете JPanel, който се използва за получаване на информация за влизане на потребителя. Харесва ми да използвам GridBagLayout, когато искам да покажа този тип панел. Например:
// inports here....
@SuppressWarnings("serial")
public class GetUserInfo extends JPanel {
private static final Insets INSETS = new Insets(4, 4, 4, 4);
private JTextField nameField = new JTextField(10);
private JPasswordField passField = new JPasswordField(10);
public GetUserInfo() {
// gridbaglayout works well for your needs
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = INSETS;
gbc.anchor = GridBagConstraints.WEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(new JLabel("Name:"), gbc);
gbc.gridy = 1;
add(new JLabel("Password:"), gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.EAST;
add(nameField, gbc);
gbc.gridy = 1;
add(passField, gbc);
}
// allow classes to query this JPanel for the user name
public String getName() {
return nameField.getText();
}
// and password data
public char[] getPass() {
return passField.getPassword();
}
}
И след това, за да комбинирате горното в конзолна програма, покажете този JPanel в JOptionPane, тъй като това създава модален диалогов прозорец, който блокира потока на програмата, докато не бъде обработен. Можете да използвате код като този:
// user interface code can go here
Scanner s = new Scanner(System.in);
System.out.println(" Login\n1.New user\n2.Old user: ");
int in = s.nextInt();
s.nextLine();
User user = null; // hold our user object
boolean inputNotOK = true; // keep looping until this is false
GetUserInfo getUserInfo = new GetUserInfo(); // our JPanel for getting user sign in information
if (in == 1) {
// code to get a new user
} else if (in == 2) {
// code to sign in existing user
while (inputNotOK) {
String title = "Get User Name and Password";
int optionType = JOptionPane.OK_CANCEL_OPTION;
int msgType = JOptionPane.PLAIN_MESSAGE;
int value = JOptionPane.showConfirmDialog(null, getUserInfo, title, optionType, msgType);
if (value == JOptionPane.OK_OPTION) {
// if the user presses "OK" on the dialog
String name = getUserInfo.getName();
char[] pass = getUserInfo.getPass();
// validUser is a method that you have that checks if the user sign in is appropriate
if (validUser(name, pass)) {
user = new User(name, pass);
System.out.println("new user: " + user);
inputNotOK = false;
} else {
// show an error JOptionPane here to warn the user
// that their sign-on information was incorrect
}
}
}
}
s.close();
// method that should check to see if user name and password are acceptable
private static boolean validUser(String name, char[] pass) {
// TODO code to test if username and password are OK
// TODO: change this to an actual test
return true;
}
С код като този, ако по-късно решите, че искате да премахнете всички кодове на конзолата (скенера), можете, тъй като вече имате JPanel, който може да се използва в десктоп Swing GUI.
person
Hovercraft Full Of Eels
schedule
22.11.2017