I am new to Java and have just tried out Java's swing, I tried making a log in form that would print the content of a JTextField to the console, but the console doesn't show anything when I tried it.
Here's my code:
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JButton;
public class JavaTextField {
private JFrame frame;
private JTextField text1;
private JTextField text2;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
JavaTextField window = new JavaTextField();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public JavaTextField() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
text1 = new JTextField();
text1.setBounds(114, 38, 122, 40);
frame.getContentPane().add(text1);
text1.setColumns(10);
String majorText = text1.getText();
text2 = new JTextField();
text2.setBounds(114, 117, 86, 20);
frame.getContentPane().add(text2);
text2.setColumns(10);
String minorText = text2.getText();
JButton btnButton = new JButton("Button");
btnButton.setBounds(132, 192, 159, 40);
frame.getContentPane().add(btnButton);
btnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(majorText);
System.out.println(minorText);
}
}
);
}
}
I'm glad if anyone could point me in the right direction, because I haven't seen the solution to this problem on the internet yet.
The issue here is, that you retrieve the content from the JTextFields at the wrong time. Currently you call getText() right when the components are being initialized. Of course, the content returned from getText() will be an empty String.
So to fix the issue in your logic, you should actually retrieve the majorText and minorText from the JTextFields only once your JButton has been pressed. Because at that point in time, when your button is pressed, the content of your text fields should be correct. To do that, move the retrieval of the text to the ActionListener.
The updated ActionListener should look as follows:
btnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String majorText = text1.getText();
String minorText = text2.getText();
System.out.println(majorText);
System.out.println(minorText);
}
}
or simply:
btnButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println(text1.getText());
System.out.println(text2.getText());
}
}
Sidenote (as also mentioned by the other answer):
Using null layout is highly discouraged, as it is a frequent source for unnecessary errors. Have a look at the different LayoutManagers available and how and when to use them.
There are some improvements to do in your code:
Avoid the use of null-layout and setBounds(...), see why should you avoid it and a graphic example along with a suggestion to fix it by using layout managers
Your majorText is getting the text BEFORE you click on the button, and by that time it's empty and never update it, you need to get the text on button click, so move this line:
String majorText = text1.getText();
Inside your actionListener, same thing for minorText
And if you tagged your question with Java 8, then you could rewrite your listener using Java 8 lambdas
btnButton.addActionListener(e -> {
String majorText = text1.getText();
String minorText = text1.getText();
System.out.println(majorText);
System.out.println(minorText);
}
Related
I am currently having trouble with a JTextPane not updating when a JButton ActionListener is telling it to update. In the code, I have a button that assigns a selected value from a JList to a global variable.
This process works because when I print out the variable when I press the button it prints the selected value in a list. However, when I push the button I also want that variable to populate the text pane so I know what value I am working with when using the UI. Does anyone know what might help with this?
I will try to get the relevant code from my large JavaSwing script as I'm using Eclipse WindowBuilder and it throws everything in the source in whatever order I created it.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class MainMappingGui extends JFrame {
private JPanel contentPane;
String attSelected = "Hello";
String attButSelect = "";
JTextPane textPaneEdits;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainMappingGui frame = new MainMappingGui();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MainMappingGui() {
setTitle("Data Mapping");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1105, 892);
contentPane = new JPanel();
contentPane.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
setContentPane(contentPane);
contentPane.setLayout(null);
JButton btnConfigMap = new JButton("Configure Mapping");
btnConfigMap.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
attButSelect = attSelected;
System.out.println(attButSelect);
textPaneEdits.repaint();
textPaneEdits.revalidate();
}
});
btnConfigMap.setFont(new Font("Tahoma", Font.PLAIN, 9));
btnConfigMap.setBounds(206, 406, 122, 23);
contentPane.add(btnConfigMap);
textPaneEdits = new JTextPane();
textPaneEdits.setBounds(634, 38, 314, 357);
textPaneEdits.setEditable(false);
textPaneEdits.setText("Current Output Column: " + attButSelect);
contentPane.add(textPaneEdits);
}
}
For this example, please assume that attSelected is a value that changes dynamically with a ListSelectionListener and works properly for selected values in a list. I have set it to "Hello" for simplicity sake.
As the one of the comments says, you have to manually change the text in the text pane.
btnConfigMap.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
attButSelect = attSelected;
textPaneEdits.setText(attButSelect);
}
});
Repaint and revalidate are not necessary.
okay, so I recently made a java console application that brute forced your password so now I was working on a similar app but with a gui.
So I have all the code and its running but for some reason, a scroll bar I added to a textArea is not appearing and when I run the program iI get neither the scroll bar nor the text area.
Please tell me where I am going wrong and help me solve this issue.
package swinggui;
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class BruteForce {
static JFrame frameObject;
static JPanel panelObject;
JLabel lblPassword;
JTextField txtPassword;
JTextArea txtStatus;
JScrollPane scrollbar;
JButton btn;
BruteForce() {
panelObject = new JPanel();
frameObject.getContentPane().add(panelObject);
panelObject.setLayout(null);
txtStatus = new JTextArea("Status: ");
txtStatus.setBounds(10,95,260,160);
panelObject.add(txtStatus);
lblPassword = new JLabel("Password: ");
txtPassword = new JTextField();
Font dialog = new Font("Dialog", Font.PLAIN, 14);
lblPassword.setBounds(10,10,100,30);
lblPassword.setFont(dialog);
panelObject.add(lblPassword);
txtPassword.setBounds(80,10,190,30);
panelObject.add(txtPassword);
scrollbar = new JScrollPane(txtStatus);
panelObject.add(scrollbar);
btn = new JButton("Test Password Strength");
btn.setBounds(10,50,260,30);
panelObject.add(btn);
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int password = Integer.parseInt(txtPassword.getText());
int guess_password = 0;
while(guess_password != password) {
txtStatus.append("\n [+] Password Attempt: " + guess_password);
guess_password = guess_password + 1;
}
if(guess_password == password) {
txtStatus.append("\n \n [-] Password Found: " + guess_password);
}
}
});
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
frameObject = new JFrame("Brute Force Tool");
frameObject.setVisible(true);
frameObject.setSize(300,300);
frameObject.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BruteForce gui = new BruteForce();
}
}
Please tell me where I am going wrong and correct my code.
Any help will be appreciated and thanks in advance.
First of all an important hint: Don't use null layout. Please learn all standard layout manager and use them to fill your UI. Also you can use some third-party layout manager like MigLayout or FormLayout (use Google to find them). These managers are often better then the standard.
Why is it better than null-layout? because Java-UI is cross-platform and some components can require different size on different OSs. The same can occur when the user uses some OS-features (like font scaling). Also layout manager defines the resize behavoir (what should happen when user changes the size of the window).
And here is the corrected version of your code (without layout manager change).
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;
public class BruteForce {
static JFrame frameObject;
JPanel panelObject;
JLabel lblPassword;
JTextField txtPassword;
JTextArea txtStatus;
JScrollPane scrollbar;
JButton btn;
BruteForce() {
panelObject = new JPanel();
frameObject.getContentPane().add(panelObject);
panelObject.setLayout(null);
txtStatus = new JTextArea("Status: ");
// set bounds not required here. it's required for scrollbar
// txtStatus.setBounds(10,95,260,160);
panelObject.add(txtStatus);
lblPassword = new JLabel("Password: ");
txtPassword = new JTextField();
Font dialog = new Font("Dialog", Font.PLAIN, 14);
lblPassword.setBounds(10, 10, 100, 30);
lblPassword.setFont(dialog);
panelObject.add(lblPassword);
txtPassword.setBounds(80, 10, 190, 30);
panelObject.add(txtPassword);
scrollbar = new JScrollPane(txtStatus);
// set the scroll bar bounds
scrollbar.setBounds(10, 95, 260, 160);
panelObject.add(scrollbar);
btn = new JButton("Test Password Strength");
btn.setBounds(10, 50, 260, 30);
panelObject.add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int password = Integer.parseInt(txtPassword.getText());
int guess_password = 0;
while (guess_password != password) {
txtStatus.append("\n [+] Password Attempt: " + guess_password);
guess_password = guess_password + 1;
}
if (guess_password == password) {
txtStatus.append("\n \n [-] Password Found: " + guess_password);
}
}
});
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
frameObject = new JFrame("Brute Force Tool");
BruteForce gui = new BruteForce();
frameObject.add(gui.panelObject); // don't forget to place your panel in the window
frameObject.setSize(300, 300);
frameObject.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frameObject.setLocationRelativeTo(null); // center location for window
frameObject.setVisible(true);
}
}
You do realize that you don't need an application to figure out that if you supply an integer password value (like 55673) and if you iterate through each value one at a time in a loop that it will take the password number of attempts (55673 iterations) to get to that password. We'll just chalk it up as an example. :/
In my opinion there are a number of issues with your particular project that needs some attention:
For a little easier coding, set the BruteForce Class so that it extends JFrame: public class BruteForce extends javax.swing.JFrame {. You won't need the static JFrame variable (frameObject) and it cleans things up somewhat.
Take out all that code related to the JFrame out of the main() method. Do your JFrame setup within a initialization method instead. In my opinion, I think your main() method would be better if you have:
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new BruteForce().setVisible(true);
}
});
}
And your initialization method might look like this:
private void initializeComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Brute Force Tool");
setResizable(false);
setAlwaysOnTop(true);
// Size the Form
// Slightly different from original size since
// form has been made non-resizable. Makes the
// form more uniformed.
setPreferredSize(new Dimension(285, 325));
setSize(getPreferredSize());
// Center Form to screen. Should always be after sizing
setLocationRelativeTo(null);
panelObject = new JPanel();
panelObject.setLayout(null);
// Password Box Label
Font dialog = new Font("Dialog", Font.PLAIN, 14);
lblPassword = new JLabel("Password: ");
lblPassword.setBounds(10, 10, 100, 30);
lblPassword.setFont(dialog);
panelObject.add(lblPassword);
// Password Entry Text Field
txtPassword = new JTextField();
txtPassword.setBounds(80, 10, 190, 30);
panelObject.add(txtPassword);
// Text Area with Scroll Pane to display
// Brute Force process.
txtStatus = new JTextArea("Status: ");
scrollbar = new JScrollPane(txtStatus);
scrollbar.setBounds(10, 125, 260, 160);
panelObject.add(scrollbar);
// Button to start Brute Force Process
btn = new JButton("Test Password Strength");
btn.setBounds(10, 50, 260, 30);
panelObject.add(btn);
// Display Progress CheckBox
chkUpdateStatus = new JCheckBox("Display Progress");
chkUpdateStatus.setBounds(10, 85, 150, 30);
panelObject.add(chkUpdateStatus);
// Scroll Progress CheckBox
chkScrollUpdate = new JCheckBox("Scroll Progress");
chkScrollUpdate.setBounds(160, 85, 150, 30);
panelObject.add(chkScrollUpdate);
// Add filled JPanel to JFrame
panelObject.setBounds(this.getBounds());
getContentPane().add(panelObject);
// Add Button Action Listener
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!workThreadIsRunning) {
// Clear the TextArea
txtStatus.setText(null);
new Thread(workThread).start();
}
if (btn.getText().equals("Cancel Test")) {
shutDownThread = true;
}
}
});
}
Which then means that your class constructor (BruteForce()) simply contains:
public BruteForce() {
initializeComponents();
}
If you are not going to use JFrame#pack() so that JFrame is automatically sized according to all its contents at or above their preferred sizes then the setSize() method to size the JFrame on its own won't help you much. You will also need to use the setPreferredSize() method as well in this case.
When creating your form, you want to add JTextArea into the JScrollPane, not the JPanel. It will then be the JScrollPane you add into the JPanel.
The setBounds() for JTextArea is not required since it will be filling the entire JScrollPane container. With the null layout you are using it will be the JScrollPane which will need the setBounds() supplied.
Since you are using the Null layout and your application window is
indeed small enough, and you've set boundries for all the components, you should also ensure that the JFrame window can not be resized (setResizable(false);) since the form would look ridiculous if it was. I'm sure you've been preached to enough to know why Null Layout is not necessarily a good choice. But if that isn't enough for you then Google this: Why is null layout in Swing frowned upon?. It does however have its place in the world especially when utilizing multiple layouts.
On a side note:
Understandably, when processing something like this it is usually nice to see the progress of that process while it is being carried out. The sad reality is that speed is seriously hampered when trying to do so.
To effectively update the JTextArea by appending a line to it indicating the brute force attempt (iteration) processed you need to use a new thread to carry out that updating. This of course means that the processing (attempts) are carried out in a separate Thread and not done within the Event Dispatch Thread (EDT) which will not update the JTextArea until all the processing is complete (which is what you are doing in your code). By placing the processing code within its own thread that updates the JTextArea immediatly is really the only viable option but it does takes time to write that update to the JTextArea...considerable time as a matter of fact.
As an example if you run the supplied runnable code (your code modified) below and supply a password of 222222, on my system it will take about 2147 milliseconds (around 2 seconds) to complete the task. If you were to comment out the textStatus.append(...) within the loop you would find that it only takes about 6 milliseconds (around 0.006 seconds) to complete the task. This is a very significant difference in processing time and if you're doing something like Brute Force you want every scrap of speed you can get. If you want the JTextArea to automatically scroll so as to display each update within the view port then speed is hampered much much more.
Progress display should be made optional with the use of Check Boxes which I did implement in the sample runnable code below and because the brute force processing is done within its own thread rather than the EDT, any changes to the Check Boxes takes immediate affect. The button also has a more toggle effect so that brute force processing can be canceled.
Here's the full code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class BruteForce extends javax.swing.JFrame {
JPanel panelObject;
JLabel lblPassword;
JTextField txtPassword;
JTextArea txtStatus;
JScrollPane scrollbar;
JButton btn;
JCheckBox chkUpdateStatus;
JCheckBox chkScrollUpdate;
Runnable workThread;
boolean workThreadIsRunning = false;
volatile boolean shutDownThread = false;
public BruteForce() {
initializeComponents();
workThread = new Runnable() {
#Override
public void run() {
long startTime = System.currentTimeMillis();
workThreadIsRunning = true;
int password = Integer.parseInt(txtPassword.getText());
btn.setText("Cancel Test");
int guess_password = 0;
while (guess_password != password & !shutDownThread) {
if (chkUpdateStatus.isSelected()) {
txtStatus.append("\n [+] Password Attempt: " + String.valueOf(guess_password + 1));
if (chkScrollUpdate.isSelected()) {
// Update The JTextArea to show immediate processing.
// (Slows down processing considerably)
txtStatus.setCaretPosition(txtStatus.getText().length() - 1);
}
}
guess_password++;
}
long duration = System.currentTimeMillis() - startTime;
if (guess_password == password) {
txtStatus.append("\n \n [-] Password Found: " + guess_password);
txtStatus.append("\n [-] It took " + duration + " milliseconds\n "
+ "(just over " + String.valueOf(duration / 1000) + " seconds) "
+ "to\n accomplish.");
txtStatus.setCaretPosition(txtStatus.getText().length() - 1);
}
workThreadIsRunning = false;
btn.setText("Test Password Strength");
shutDownThread = false;
}
};
}
private void initializeComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Brute Force Tool");
setResizable(false);
setAlwaysOnTop(true);
// Size the Form
// Slightly different from original size since
// form has been made non-resizable. Makes the
// form more uniformed.
setPreferredSize(new Dimension(285, 325));
setSize(getPreferredSize());
// Center Form to screen. Should always be after sizing
setLocationRelativeTo(null);
panelObject = new JPanel();
panelObject.setLayout(null);
// Password Box Label
Font dialog = new Font("Dialog", Font.PLAIN, 14);
lblPassword = new JLabel("Password: ");
lblPassword.setBounds(10, 10, 100, 30);
lblPassword.setFont(dialog);
panelObject.add(lblPassword);
// Password Entry Text Field
txtPassword = new JTextField();
txtPassword.setBounds(80, 10, 190, 30);
panelObject.add(txtPassword);
// Text Area with Scroll Pane to display
// Brute Force process.
txtStatus = new JTextArea("Status: ");
scrollbar = new JScrollPane(txtStatus);
scrollbar.setBounds(10, 125, 260, 160);
panelObject.add(scrollbar);
// Button to start Brute Force Process
btn = new JButton("Test Password Strength");
btn.setBounds(10, 50, 260, 30);
panelObject.add(btn);
// Display Progress CheckBox
chkUpdateStatus = new JCheckBox("Display Progress");
chkUpdateStatus.setBounds(10, 85, 150, 30);
panelObject.add(chkUpdateStatus);
// Scroll Progress CheckBox
chkScrollUpdate = new JCheckBox("Scroll Progress");
chkScrollUpdate.setBounds(160, 85, 150, 30);
panelObject.add(chkScrollUpdate);
// Add filled JPanel to JFrame
panelObject.setBounds(this.getBounds());
getContentPane().add(panelObject);
// Add Button Action Listener
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!workThreadIsRunning) {
// Clear the TextArea
txtStatus.setText(null);
new Thread(workThread).start();
}
if (btn.getText().equals("Cancel Test")) {
shutDownThread = true;
}
}
});
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new BruteForce().setVisible(true);
}
});
}
}
I am having problems clearing contents of TextField in AWT using setText() method. Apparently, setText("") does not clear the contents of the TextField on pressing the 'Reset' button. Here's my program:
import java.awt.*;
import java.awt.event.*;
public class form extends Frame
{
Label lbl = new Label("Name:");
TextField tf = new TextField();
Button btn = new Button("Reset");
public form()
{
tf.setColumns(20);
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
btn.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
tf.setText(""); //Problem occurs here. This does not clear the contents of the text field on pressing the 'Reset' button.
}
});
add(lbl);
add(tf);
add(btn);
setLayout(new FlowLayout());
setSize(400,100);
setVisible(true);
setTitle("Form");
}
public static void main(String[] args)
{
new form();
}
}
Can someone please tell me where I went wrong or suggest an alternative? Thanks.
I see the problem as well using Java 8u11. I seem to remember this being filed as a known bug, but I can't seem to find it now.
A solution that works for me is to add an intermediate step:
public void actionPerformed(ActionEvent e) {
tf.setText(" ");
tf.setText("");
}
I'm not sure why this is necessary, I think it's a bug with the setText() function specifically ignoring empty Strings. If somebody finds the filed bug there would be more information there.
Add space in setText(" ") in function and see if it works. But there after there will be one space.
I'm tying to make a program that acts similar to the Windows Command Prompt, or a terminal. It's basically just a JFrame with a JTextArea as output, and a JTextField as input. It looks like this:
I want to be able to get input from the JTextField whenever my program calls a method that returns a String, something like:
public static String getInput() {
//Wait for user to enter something, then press the enter key
}
I added an AbstractAction so I can do stuff when the enter key is pressed, but I still could figure out how to return the input as a String whenever I call the method.
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
//Clears the JTextField
input.setText("");
}
};
I could put something like userInput = input.getText() in public void actionPerformed(), so it would just set a variable to whatever has been entered every time, and use userInput whenever I want to, but I want the user to have time to read whats on the screen, then have the program wait for a response, instead of just using the last thing they entered right away.
I tried to use a userInput variable and a boolean variable like this:
private static String userInput = "";
private static boolean enterPressed = false;
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
userInput = input.getText()
enterPressed = true;
input.setText("");
}
};
...
public static String getInput() {
enterPressed = false;
while(!enterPressed){
//Do Nothing
}
enterPressed = false;
return userInput;
}
When I called output.setText(getInput());, it worked like I wanted to, except that the while(!enterPressed){} made my processor work a lot harder than it should need to. I'm pretty sure there's probably a lot better way of doing this.
Here's my whole code right now:
public class ConsoleFrame {
//Objects for Console Frame
JFrame frame = new JFrame();
JTextArea output = new JTextArea();
JTextField input = new JTextField();
BoxLayout boxLayout = new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
JScrollPane scrollPane = new JScrollPane(output);
DefaultCaret caret = (DefaultCaret)output.getCaret();
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
input.setText("");
}
};
ConsoleFrame(){
input.addActionListener(action);
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
frame.setLayout(boxLayout);
frame.add(scrollPane);
frame.add(input);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 250);
frame.setLocationRelativeTo(null);
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 10));
output.setEditable(false);
output.setAutoscrolls(true);
}
public static String getInput() {
return null;
}
}
So, how could I stop the program until the user presses enter, every time I call getInput();?
I want to be able to get input from the JTextField whenever my program
calls a method that returns a String, something like:
I added an AbstractAction so I can do stuff when the enter key is
pressed, but I still could figure out how to return the input as a
String whenever I call the method.
public String getInput() {
return input.getText();
}
So, how could I stop the program until the user presses enter, every time I call getInput();?
You don't. Swing, like most UI frame works is event driven, that is, something happens and your respond to it.
So, with that in mind you should consider using some kind Observer Pattern, where you use a call back to be notified of some kind of change which you are interested in, like your ActionListener for example.
Instead, you could provide some kind of listener, which interested parties would register with and when the field changes you would notify them, for example...
import java.util.EventListener;
import java.util.EventObject;
public class InputEvent extends EventObject {
private final String text;
public InputEvent(Object source, String text) {
super(source);
this.text = text;
}
public String getText() {
return text;
}
}
public interface InputObsever extends EventListener {
public void inputChanged(InputEvent evt);
}
So, we now have an observer who will be notified when ever the input is changed/updated.
Then we simply need a way to un/register and fire the event...
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.EventListenerList;
import javax.swing.text.DefaultCaret;
public class ConsoleFrame {
//Objects for Console Frame
JFrame frame = new JFrame();
JTextArea output = new JTextArea();
JTextField input = new JTextField();
BoxLayout boxLayout = new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS);
JScrollPane scrollPane = new JScrollPane(output);
DefaultCaret caret = (DefaultCaret) output.getCaret();
Action action = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
fireInputChanged(input.getText());
input.selectAll();
}
};
private EventListenerList listenerList = new EventListenerList();
ConsoleFrame() {
input.addActionListener(action);
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
frame.setLayout(boxLayout);
frame.add(scrollPane);
frame.add(input);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 250);
frame.setLocationRelativeTo(null);
input.setMaximumSize(new Dimension(Integer.MAX_VALUE, 10));
output.setEditable(false);
output.setAutoscrolls(true);
}
public String getInput() {
return input.getText();
}
public void addInputObsever(InputObsever obsever) {
listenerList.add(InputObsever.class, obsever);
}
public void removeInputObsever(InputObsever obsever) {
listenerList.remove(InputObsever.class, obsever);
}
protected void fireInputChanged(String text) {
InputObsever[] listeners = listenerList.getListeners(InputObsever.class);
if (listeners.length > 0) {
InputEvent evt = new InputEvent(this, text);
for (InputObsever obsever : listeners) {
obsever.inputChanged(evt);
}
}
}
}
Now, the point here is, when you want to know when the text has been input/changed, you register an observer to the instance of the ConsoleFrame
console.addInputObsever(new InputObsever() {
#Override
public void inputChanged(InputEvent evt) {
// Do what ever you need to do...
}
});
EDIT: First half removed. It was brought to my attention that it was erroneous.
The best option is to enclose a call to whatever you need your computer to execute after the user inputs text inside your actionPerformed method. So when the user inputs text and presses enter, the program automatically continues from there.
Action action = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
userInput = input.getText()
enterPressed = true;
input.setText("");
//call next method;
}
};
This requires some more formatting work on your behalf, but it could be helpful depending on your project. This link has more information on this strategy.
Hope this helped.
jTextField1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
yourFunction(jTextField1.getText());
jTextField1.setText("");
}
});
Btw just a tip, you may append the JTextArea to get the feel of a console window
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
For some reason getText is not working for a text field.
Perhaps I am doing something wrong with this.
private JTextField txtTemp;
txtTemp = new JTextField();
txtTemp.setBounds(350, 57, 86, 20);
mainPanel.add(txtTemp);
txtTemp.setColumns(10);
String filePath = txtTemp.getText();
System.out.println("File path is" +filePath);
Nothing is being printed when something is typed in the text box.
I also did it with using an action listener. Load the program, and have the user add some text.
btnTest = new JButton("TEST");
btnTest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String filePath = txtTemp.getText();
System.out.println("File path is" +filePath);
}
});
Still returns blank.
Any ideas?
"Nothing is being printed when something is typed in the text box."... "Still returns blank."
Sounds like you want something to happen whenever the text field is being type into. For that we would use a DocumentListener, which listener for changes in the underlying Document of the text field.
final JTextField field = new JTextField(20);
field.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) { printText(); }
#Override
public void removeUpdate(DocumentEvent e) { printText(); }
#Override
public void changedUpdate(DocumentEvent e) { printText(); }
private void printText() {
System.out.println(field.getText());
}
});
See more explanation at How to Write a Document Listener
Aside, if you want something to happen when the use type enter, then add an ActionListener to the text field.
Your JTextField seems empty, as long as you dont give any input, however common mistakes may be:
is it editable?
txtTemp.setEditable(true);
any text added?
public void changeTxtField(String text)
{
txtTemp.setText(text);
System.out.println(text);
}
your code looks fine so
Don't also do it 'also in the Action Listener' , DO it only in the ActionListener ?
I have no idea where you are going wrong , are you expecting the output on the GUI screen ?if so you are mistaken , look into the terminal...
Here I just tried and it perfectly works , it prints the user input text after clicking the button onto the terminal ,
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class TestText{
public static void main(String[] args)
{
JFrame frame=new JFrame("TextFieldTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainPanel=new JPanel();
JTextField txtTemp;
txtTemp = new JTextField();
txtTemp.setBounds(350, 57, 86, 20);
mainPanel.add(txtTemp);
txtTemp.setColumns(10);
JButton btnTest = new JButton("TEST");
btnTest.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String filePath = txtTemp.getText();
System.out.println("File path is" +filePath);
}
});
frame.add(BorderLayout.SOUTH,btnTest);
frame.add(mainPanel);
frame.setSize(600,600);
frame.pack();
frame.setVisible(true);
}//main ends
}//class ends
I ended up figuring out this issue.
At the top if i declare and Instantiate the object it works.
private JTextField txtTemp = new JTextField();