I'm playing around with JavaFX and created a login form. So I want to test the inevitable, insert usernmae and password to check if correct. The problem is that it doesn't run as expected. It will always go to the else body no matter what. Code below:
public class Controller {
#FXML PasswordField pass;
#FXML TextField name;
#FXML javafx.scene.control.Button login;
#FXML Hyperlink signup;
#FXML Label errormessage;
#FXML private void buttonPressed() {
checkUser();
}
#FXML private void ifEnterIsPressed(KeyEvent k) {
if (k.getCode() == KeyCode.ENTER)
checkUser();
}
#FXML private void checkUser() {
System.out.println(name.getCharacters());
System.out.println(pass.getCharacters());
if (name.getCharacters().equals("Marios") && pass.getCharacters().equals("19981998")) {
errormessage.setVisible(false);
System.out.println("Access granted!");
}
else {
errormessage.setText("Wrong username or password");
System.out.println("Access denied");
}
}
}
I don't know if I'm missing something completely obvious here or what...
Thanks in advance!
The issue is your use of the TextField.getCharacters() method. This isn't the same thing as calling TextField.getText(). Currently, for Java 10, the method TextField.getCharacters() returns a StringBuilder (which is a CharSequence) rather than a String. This is can be expected because the Javadoc states:
Returns the character sequence backing the text field's content.
By "content" it most likely means the backing TextInputControl.Content and the source code of TextField seems to confirm this. What you want to compare, however, is the String contained in the textProperty() of the TextField.
Apparently, and I didn't know this (though its understandable), a StringBuilder does not equals a String even if they contain the same characters. Or, to put it in code:
StringBuilder sb = new StringBuilder("Hello, World!");
String s = "Hello, World!";
sb.equals(s); // FALSE
sb.toString().equals(s); // TRUE
So, to answer directly, change name.getCharacters() and pass.getCharacters() to name.getText() and pass.getText(), respectively.
Related
Im trying to prevent backspace from deleting characters in a javafx textarea. KeyEvent.consume should do this but it doesn't prevent the key event from happening. It does set the property of the key event and KeyEvent.isConsumed() gives back true after consuming the event. The backspace still gets executed. I tried other keys and there is the same effect.
This is my current fxcontroller class:
public class Terminal {
#FXML
private TextArea ta_console;
#FXML
private AnchorPane ap_main;
#FXML
protected void initialize(){
ta_console.setText(">");
ta_console.positionCaret(1);
}
public void keyStroke(KeyEvent keyEvent) {
if (keyEvent.getCode() == KeyCode.BACK_SPACE || keyEvent.getCode() == KeyCode.DELETE) {
keyEvent.consume();
}
}
}
The keyStroke method gets executed by the textarea on key pressed.
Am i missing something or is consume bugged or somehow not functional the way the documentation says? Is there a way i can still get the desired outcome?
If you want to prevent the user deleting text, that should be done with a TextFormatter instead of trying to guess which key events the control is handling internally, and in what order all those events are handled, etc. etc., for its default behavior.
It's not clear exactly what you want to achieve, but here is an example, which prevents any deletion (or replacement) of text:
public class Terminal {
#FXML
private TextArea taConsole;
#FXML
protected void initialize(){
taConsole.setText(">");
taConsole.positionCaret(1);
taConsole.setTextFormatter(new TextFormatter(change -> {
if (change.getRangeStart() == change.getRangeEnd()) { // nothing deleted
return change ;
}
// change represents a deletion of some text, veto it:
return null ;
});
}
}
See the Javadocs for TextFormatter.Change for details.
How can I enable my CheckBox when I type into the TextField a value other than zero?
By default, I've set my CheckBox to disable in the Scene Builder.
In my MainController class:
#FXML
private CheckBox cb1;
#FXML
private TextField txt1;
public void enableCB() {
if (txt1.getText() == "0") {
cb1.setDisable(true);
} else {
cb1.setDisable(false);
}
}
In Scene Builder I've set the "enableCb Method" to the On Action and On Key Typed, but still it did not provide the right condition and output.
This can be accomplished with a fairly simple, one-statement binding:
cb1.disableProperty().bind(
txt1.textProperty().isEmpty()
.or(txt1.textProperty().isEqualTo("0")));
This will enable the CheckBox only if a value other than "0" has been entered into the TextField. So it will be disabled if the text is either empty or "0".
I suggest writing a ChangeListener for the text property of the TextField.
txt1.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable,
String oldValue,
String newValue) {
if ("0".equals(newValue)) {
cb1.setDisable(true);
}
else {
cb1.setDisable(false);
}
}
});
Every time the text in the TextField is changed, the above code will execute, regardless of how the text is changed.
Also note that the way to compare different strings in Java is with method equals and not with the equals operator, i.e. ==.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am trying to build an application that requires users to log in. When they register I store their information in the MySQL database. (For now, I am just using localhost) I don't want users to write their login details every time they open up the application. How can I avoid this? I am totally clueless. I will be very thankful if someone helps.
You can persist data to user's local profile via java.util.prefs.Preferences. You should probably avoid saving sensitive data but 'username' is fair game.
As pointed out by #Hollis Waite, you can use the java.util.prefs library.
import java.util.prefs.*;
Make a Remember Me checkbox and put it on your login scene:
#FXML
private CheckBox rememberMeCheckBox;
Then you can use the action event from the checkbox to save the username. Again, as pointed out by Hellis, stick with saving the username and never handle naked passwords.
Example:
#FXML
void handleRememberUser(ActionEvent event) {
if(rememberMeCheckBox.isSelected()) {
// Let's validate the username field isn't empty (Optional)
if(!usernameField.getText().isEmpty()){
Preferences pref = Preferences.userRoot();
String userName = usernameField.getText();
pref.put("username", userName);
}
}
}
Then you will probably want the username field to automatically fill the username in memory, right?
In that case you have to make your LoginController implement the initializable class, to have access to the "initialize" method, which can run methods when the class is initialized.
Example:
public class LoginController implements Initializable{
/// Your whole code in here
}
Then all you have left to do is override the method initialize (Intellij = Alt + Insert/ Override and choose initialize().
#Override
public void initialize(URL location, ResourceBundle resources) {
usernameField.setText(Preferences.userRoot().get("username", "Username")); // gets the username form the preferences, if userRoot not set, returns "Username"
}
Complete code example would look like:
public class LoginController implements Initializable {
#FXML
private AnchorPane anchorRoot;
#FXML
private TextField usernameField;
#FXML
private PasswordField passwordField;
#FXML
private Button loginButton;
#FXML
private CheckBox rememberMeCheckbox;
#FXML
void handleRememberUser(ActionEvent event) {
if(rememberMeCheckBox.isSelected()) {
// Let's validate the username field isn't empty (Optional)
if(!usernameField.getText().isEmpty()){
Preferences pref = Preferences.userRoot();
String userName = usernameField.getText();
pref.put("email", userName);
}
}
}
#FXML
void handleLogin(ActionEvent actionEvent) throws IOException {
validateUser();
}
#FXML
void handleEnterPressed(ActionEvent event) {
validateUser();
}
private void validateUser() {
if (usernameField.getText().isEmpty() || passwordField.getText().isEmpty()) {
// Tell the user fields cannot be empty
} else {
// Connect to DB
DatabaseConnection connectNow = new DatabaseConnection();
Connection connectDB = connectNow.getConnection();
String query = "SELECT etc etc etc";
try {
Statement statement = connectDB.createStatement();
ResultSet rs = statement.executeQuery(query);
if (rs.next()) {
// Validate your user however you are doing it
} else {
// User not found, do something
}
} catch (Exception e) {
e.printStackTrace();
e.getCause();
}
}
}
#Override
public void initialize(URL location, ResourceBundle resources) {
// Will set usernameField to whatever was stored in userRoot.
usernameField.setText(Preferences.userRoot().get("email", "User email"));
}
}
Side note, if you are making a login and want to compare passwords, please start using encryption libraries. Never handle naked Strings for passwords.
springframeword.security.crypto is a good library.
Voila.
You could store the sensitive data in the keyring of the platform.
The NetBeans Platform (Swing based Rich Client Platform) for example provides a Java based Keyring API.
There seems to be also a port independent from the NetBeans Platform.
Ok so this is the first question I've asked on StackOverflow so apologies if its unclear.
Basically, I am making a program in JavaFx that is an ordering system for a fake Cafe. Its for an assignment and it really doesn't have to make conventional sense because my curriculum doesn't really care if it is actually useful or not, they just want to see you code some random stuff.
Anyways, the problem i am having atm is that I am trying to make it so when I open the Main page called MainPage.fxml, 4 things will be pre-disabled/enabled. These elements are PinPane Which contains the sign-in buttons and labels), PrimaryPane (which contains all buttons leading to different ordering pages), SettingsBtn (Sends user to settings), and LogoutBtn (Self expanatory).
This is important because when the program is first opened, MainPage is the first thing that is started. Once a user Signs in, and heads off to another page to select an item however, when they come back to the MainPage, where the current-order is displayed in PrimaryPage (I haven't actually done any code for that yet), I want to ensure that the disabled/enabled states of all 4 elements remains the same as when user left to go to another Page.
Currently, I am using a static class called DataContainer.java, which contains all data shared by the program, and I thought i could put 3 boolean variables which basically just tell the program on the opening of MainPage what is disabled and enabled.
However, my Primary problem is, I can't seem to be able to change the state of any of these elements on startup, and i have no idea how to do that other wise.
My code for the MainPageController.java is below:
'''
public class MainPageController {
#FXML private Label Price; //fx:if -> Price
#FXML public Pane PrimaryPage, PinPane; //fx:id -> PrimaryPage
#FXML public Label Pin; //fx:id -> Pin
#FXML public Button LogoutBtn, SettingsBtn;
public void Check(ActionEvent event) throws IOException{
// This is the method I use to check the entered pin against current
// saved pins.
DataContainer.DataContainer();
// This is just a method i use for testing, it adds a manager account that i can sign in with
// each time the program is opened because I haven't introduced account creation and saving
// yet
int pin = Integer.parseInt(Pin.getText());
int i = DataContainer.Users.size();
int x = 0;
while (x <= i-1){
if (DataContainer.Users.get(x).PinNumber == pin){
// In this, once the pin is verified, each element is enabled and disabled, and the
// boolean variables are set as well for future use
System.out.println("test");
DataContainer.UserIndex = x;
PrimaryPage.setDisable(false);
LogoutBtn.setDisable(false);
DataContainer.PrimaryPage = true;
Pin.setText("");
PinPane.setDisable(true);
DataContainer.PinPane = false;
break;
}
x = x + 1;
}
if (DataContainer.Users.get(DataContainer.UserIndex).Position.equals("Manager")){
SettingsBtn.setDisable(false);
DataContainer.SettingsBtn = true;
}
'''
This is the code for DataContainer.java
'''
public class DataContainer{
public static void main(String args[]){
}
public static void DataContainer(){
Users.add(owner);
System.out.println("test");
}
static boolean PinPane = true, PrimaryPage = false, SettingsBtn = false;
// These boolean values are relevant to the MainPage application
// Their purpose is to retain the information of the state in which the user
// left the main page, i.e, if the PinPage is disabled, the PrimaryPage is enabled, etc.
// this is important as if these variables don't exist the MainPage and its elements
// go back to their default state and the user has to re-sign in.
static String firstname, lastname, position;
static int PinNo, PhoneNo, UserIndex;
public static UserVariables user = new UserVariables(firstname, lastname, position, PinNo,
PhoneNo);
static UserVariables owner = new UserVariables("Test", "User", "Manager", 1234,
0434553);
public static ArrayList<UserVariables> Users = new ArrayList<UserVariables>();
}
'''
And finally this is the code for FInalIA.java (Main class):
'''
public class FInalIA extends Application implements Serializable {
public static void main(String args[]) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
// StackPane root = new StackPane();
Parent root = (Parent) FXMLLoader.load(getClass().getResource("MainPage.fxml"));
Scene scene = new Scene(root);
stage.setTitle("Main Page");
stage.setScene(scene);
stage.setResizable(false);
stage.show();
MainPageController.Open();
}
}
'''
And Finally, this is the code i was thinking of using, by making a public static method called 'Open()', and making all the panes static, and just just calling this method when ever MainPage is opened.
'''
public static void Open(){
if (DataContainer.PinPane == false){
PinPane.setDisable(true);
}
else{
PinPane.setDisable(false);
}
if(DataContainer.PrimaryPage == false){
PrimaryPage.setDisable(true);
LogoutBtn.setDisable(true);
}
else{
PrimaryPage.setDisable(false);
LogoutBtn.setDisable(false);
}
if(DataContainer.SettingsBtn == false){
SettingsBtn.setDisable(true);
}
else{
SettingsBtn.setDisable(false);
}
}
'''
Thanks to whoever helps me out with this (Also can you guys plz tell me if what i am writing is to non-concise and irrelevant or if its actually good)
Step one make Open non-static. You're going to create an instance of your controller and it will manage the associated items.
public class MainPageController implements Initializable{
#FXML private Label price; //fx:if -> Price
#FXML public pane primaryPage, pinPane; //fx:id -> PrimaryPage
#FXML public Label pin; //fx:id -> Pin
#FXML public button bogoutBtn, settingsBtn;
public void Check(ActionEvent event) throws IOException{
//why is this method included but not open?
}
#Override
public void initialize(URL url, ResourceBundle rb){
if (DataContainer.PinPane == false){
pinPane.setDisable(true);
} else{
pinPane.setDisable(false);
}
primaryPage.setDisable( ! DataContainer.PrimaryPage );
logoutBtn.setDisable(! DataContainer.PrimaryPage);
//etc etc
}
}
I've made your controller implement Initializable, that way it has a method initialize that gets called when you start. I've also improved the naming, eg Pin should be named pin. If this doesn't work for you, I can replace this with a small enclosed example.
You don't need to implement Initializable javafx will automatically call an appropriate initialize method.
I am trying to use this String called "username" from another method, but I can't seem to figure out what to do.
I have this bit of code right here, which assigns a text field's entry to a variable, but I can't seem to use this variable in another method
//Configuring content pane
JFormattedTextField formattedTextField = new JFormattedTextField();
formattedTextField.setBounds(129, 36, 120, 20);
UsernameFrame.getContentPane().add(formattedTextField);
UsernameFrame.setVisible(true);
//Assigning text field entry to variable
String username = formattedTextField.getText();
Now, I am trying to use this variable in the method pasted below, but I don't know what I am missing..
public void actionPerformed(ActionEvent e){
if(username.length() < 5){
}
//Execute when the button is pressed
System.out.println("The button has been pressed");
}
This is probably something really simple I am missing, thanks for your help guys.
(full code)
http://pastebin.com/RMszazd4
Declare username right after your class declaration like this:
public class App {
private String username;
public static void main(String[] args) {
...
}
...
}
If these are two separate methods you will need to reassign the username variable again or you can create a global variable outside of your methods.
You might want to pass in the string variable "username"as a parameter to another method since it would not recognize the scope of your string in another method unless its declared global.
You don't appear to have a way of reading the JFormattedTextField. If I understand what you're trying to do correctly, you could declare formattedTextField as an instance variable, and then declare username inside the listener:
public class Frame {
JFrame UsernameFrame = new JFrame("Welcome");
private JFormattedTextField formattedTextField;
....
btnSubmit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String username = formattedTextField.getText();
if (username.length() < 5) {
}
// Execute when the button is pressed
System.out.println("The button has been pressed");
}
});
Now you have a reference to the text of the JFormattedTextField to do what you will with each time the button is pressed.