This question already has answers here:
Value Change Listener to JTextField
(14 answers)
Closed 2 years ago.
I want to know if there is a way to notice if a listener is changing the text of a JTextField or if it is done by .setText(); I need to seperate between both cases, beacause it need to do different things when accesed by a user or by the programm.
I assume you use a DocumentListener to hook into user's input. You can remove this document listener while you call the setText from your program.
Take a look at the following example. When the button is pressed, the text is changed without the printing message.
public class DocumentListenerExample extends JFrame {
private JTextField textField;
private DocumentListener textFieldDocumentListener;
public DocumentListenerExample() {
super("");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
textField = new JTextField(20);
textFieldDocumentListener = new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
System.out.println("Text changed by user");
}
#Override
public void insertUpdate(DocumentEvent e) {
System.out.println("Text changed by user");
}
#Override
public void changedUpdate(DocumentEvent e) {
System.out.println("Text changed by user");
}
};
textField.getDocument().addDocumentListener(textFieldDocumentListener);
add(textField);
JButton button = new JButton("Change text");
button.addActionListener(e -> {
textField.getDocument().removeDocumentListener(textFieldDocumentListener);
textField.setText(String.valueOf(Math.random()));
textField.getDocument().addDocumentListener(textFieldDocumentListener);
});
add(button);
pack();
setLocationByPlatform(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new DocumentListenerExample().setVisible(true);
});
}
}
Related
This question already has answers here:
Access GUI components from another class
(5 answers)
Java/Swing: reference a component from another class
(2 answers)
Closed 4 years ago.
I'm trying populate a JComboBox, whenever a button is clicked in a different frame. In the other frame, there is a text field where a person enters a name for example and a submit button, that is all. Every time the submit button is clicked, I want to populate the JComboBox. Here is the code to demonstrate what I mean. The code works, with static variables, something I'm wanting to avoid if possible.
public class Frame1Panel extends JPanel{
private static MyComboBox comboBox;
private JButton addItemsButton, exitButton;
public Frame1Panel() {
comboBox = new MyComboBox();
exitButton = new JButton("exit");
addItemsButton = new JButton("Add Items");
Dimension dim = addItemsButton.getPreferredSize();
addItemsButton.setPreferredSize(dim);
setupLayout();
exitButton.setPreferredSize(dim);
addItemsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == addItemsButton) {
Frame2 frame2 = Frame2.getInstance();
frame2.setVisible(true);
}
}
});
//This is what I'm trying to avoid. This works of course
public static MyComboBox getComboBox() {
return comboBox;
}
}
}
If you notice, I just use Frame1Panel and call the getComboBox method and of course the addItem method and it works as expected. Again is there way where I can avoid using static?
public class Frame2Panel extends JPanel {
private JTextField nameTextField;
private JLabel nameLabel;
private JButton submitButton;
public Frame2Panel() {
setLayout(new GridBagLayout());
nameTextField = new JTextField(10);
nameLabel = new JLabel("Name: ");
submitButton = new JButton("Submit");
setupLayout();
submitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
String name = nameTextField.getText();
Frame1Panel.getComboBox().addItem(name);
}
});
}
}
If anyone is wondering as to why I have a separate MyComboBox class, that is because I incorporate the DefaultComboBoxModel so Eclipse doesn't yell at me, when I use the window design editor, it isn't necessary to the question to include it, You can assume MyComboBox doesn't exist and just think it is JComboBox instead.
I'm writing an application where I need to get two String objects from the GUI to the nullObject class.
I'm relatively new to programming, and am trying my best to learn. If you have any tips on how to make this better, I'd be really thankful!
My GUI class:
package com.giuly.jsoncreate;
public class GUI {
private JFrame startFrame;
private JFrame chkFrame;
private JFrame osFrame;
private JFrame appVFrame;
private JPanel controlPanel;
private JButton nextPage;
private JButton cancel;
private JButton save;
public GUI() {
generateGUI();
}
public static void main(String[]args) {
GUI gui = new GUI();
}
public void generateGUI() {
//Creation of the First Frame
startFrame = new JFrame("JSCON Creator");
startFrame.setSize(1000, 700);
startFrame.setLayout(new FlowLayout());
startFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
//Panel Creation
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
//Button Creation
cancel = new JButton("Cancel");
cancel.setSize(100, 100);
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
nextPage = new JButton("Next");
nextPage.setSize(100, 100);
nextPage.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
startFrame.setVisible(false);
showText();
}
});
startFrame.add(controlPanel);
startFrame.add(cancel);
startFrame.add(nextPage);
startFrame.setVisible(true);
startFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
public void showText() {
JFrame textFrame = new JFrame();
textFrame.setSize(1000, 700);
textFrame.setTitle("Text");
textFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JPanel textPanel = new JPanel();
JLabel titleLabel = new JLabel("Title");
textPanel.add(titleLabel);
JLabel descrLabel = new JLabel("Description");
JTextField tfTitle = new JTextField("",15);
tfTitle.setForeground(Color.BLACK);
tfTitle.setBackground(Color.WHITE);
JTextField tfDescr = new JTextField("",30);
tfDescr.setForeground(Color.BLACK);
tfDescr.setBackground(Color.WHITE);
textPanel.add(tfTitle);
textPanel.add(descrLabel);
textPanel.add(tfDescr);
JButton buttonOK = new JButton("OK");
textPanel.add(buttonOK);
buttonOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String jsonTitle = tfTitle.getText();
String jsonDescr = tfDescr.getText();
System.exit(0);
}
});
textFrame.add(textPanel);
textFrame.setVisible(true);
}
I want to get the Strings jsonTitle and jsonDescr into another class, so I can store them. In the end I will have some Strings and I need to save them in a JSON file. I need a way to get those two Strings, what advice do you guys have?
Erick is correct with his answer. Just thought I should add additional info. If you declare jstonTitle and jsonDescr like your other fields using private you still will not be able to access these fields from another class. Coding up a getter for the fields along with declaring them at the top of GUI should solve your problem. Then just create an instance of GUI in your other class and call the method.
public String getJsonTitle(){
return this.jsonTitle;
}
You're declaring jstonTitle and jsonDescr inside the actionPerformed() method. That means that as soon as actionPerformed() exits you'll lose those variables. You need to declare them in an enclosing context. For example, you could make them fields on the GUI class. Still assign them in actionPerformed(), but declare them up at the top of GUI where you're declaring startFrame, chkFrame, etc.
That will give you the ability to access those values from anywhere within GUI.
Oh, BTW, get rid of System.exit(0);. (Have you actually tried to run your program?)
I have main JFrame in my project. And one main JPanel with Y-AXIS BoxLayout which is used to contain another panels in it. This is the way i use my JFrame to show this JPanel by default (I'm not quite convinced if this is the right way):
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
mainPanel = new MainScreenPanel();
MainFrame mainFrame = new MainFrame();
mainFrame.setContentPane(mainPanel);
mainFrame.invalidate();
mainFrame.validate();
mainFrame.setVisible(true);
}
});
}
Next I add two JPanels into mainPanel like this:
public class MainScreenPanel extends javax.swing.JPanel {
public MainScreenPanel() {
StatusPanel sPanel = new StatusPanel();
LogPanel lPanel = new LogPanel();
add(sPanel);
add(lPanel);
}
}
lPanel has different gui elements on it. One of them is a button which opens another panel (addConnectionPanel), and replaces mainPanel in the jFrame Here is the way i do it:
private void addCnctButtonActionPerformed(java.awt.event.ActionEvent evt) {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
topFrame.setContentPane(new AddConnectionPanel());
topFrame.invalidate();
topFrame.validate();
}
AddConectionPanel has some labels and input text boxes. It has two buttons ok and cancel. Here is the code of cancel button:
private void cancelCnctBtnActionPerformed(java.awt.event.ActionEvent evt) {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
topFrame.setContentPane(new MainScreenPanel());
topFrame.invalidate();
topFrame.validate();
}
sPanel is empty. It must be empty until input boxes on AddConnectionPanel are not filled and 'ok' button is not pressed. When these actions are performed, I want to dynamically create JLabels which take parameters from inputs on sPanel. Labels should be grouped, so when the actions performed second time new group must be created. Can some one give me advice on how to do this? And show me my mistakes? Keep in mind I'm using NetBeans.
This would be my approach:
public interface ConnectionPanelListener{
void onOkButtonClicked(String... options);
void onCancelButtonClicked();
}
public class AddConnectionPanel extends JPanel {
private static final long serialVersionUID = 1L;
private ConnectionPanelListener listener;
public AddConnectionPanel(){
final Map<ConnectionOptions, JTextField> components = new HashMap<>(ConnectionOptions.values().length);
for(ConnectionOptions option:ConnectionOptions.values()){
this.add(new JLabel(option.labelCaption));
JTextField textField = new JTextField();
//setup textField;
this.add(textField);
components.put(option, textField);
}
JButton button = new JButton("OK");
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent pE) {
super.mouseClicked(pE);
//TODO validate TextFields
Collection<String> inputs = new Stack<>();
for(Entry<?,JTextField> e : components.entrySet()){
String text = e.getValue().getText();
if(text==null || text.trim().isEmpty()){
//TODO improve input validation
System.out.println("Input text is empty for: "+e.getKey());
} else {
inputs.add(e.getKey() + ": " + text);
}
}
listener.onOkButtonClicked(inputs.toArray(new String[inputs.size()]));
}
});
this.add(button);
button = new JButton("cancel");
button.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent pE) {
super.mouseClicked(pE);
listener.onCancelButtonClicked();
}
});
this.add(button);
}
public void setConnectionPanelListener(final ConnectionPanelListener l){
listener = l;
}
private enum ConnectionOptions{
IP_ADDRESS("IP-Address:"), PORT("Port:"), WHATEVER_ATTRIBUTE_YOU_NEED("Extras:");
private String labelCaption;
private ConnectionOptions(final String caption) {
labelCaption = caption;
}
}
}
As you can see, AddConnectionPanel expects a Listener to register for the case, that "OK" or "CANCEL" are clicked. So your adjusted implementation could be like:
private void addCnctButtonActionPerformed(java.awt.event.ActionEvent evt) {
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
AddConnectionPanel panel = new AddConnectionPanel();
panel.setConnectionPanelListener(new ConnectionPanelListener(){
#Override
void onOkButtonClicked(String... options){ TODO: fill sPanel using the given Strings }
#Override
void onCancelButtonClicked(){ TODO }
});
topFrame.setContentPane(panel);
topFrame.invalidate();
topFrame.validate();
}
This question already has answers here:
Cannot refer to a non-final variable inside an inner class defined in a different method
(20 answers)
Closed 8 years ago.
How can I change the Value of a JTextfield inside an ActionLIstener?
cmdAnzeigen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
/* Cannot refer to a non-final variable TextOutput inside an
inner class defined in a different method*/
TextOutput.setText("Hello");
}
});
Here,You can write another method and put your TextField value change code in this method. like,
public class Demo {
static JTextField txtName;
static JButton jbSubmit;
public Demo()
{
txtName = new JTextField(10);
jbSubmit = new JButton("Submit");
jbSubmit.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
change("XYZ");
}
});
}
public static void change(String name)
{
txtName.setText(name);
}
public static void main(String[] args) {
Demo d = new Demo();
JFrame jf=new JFrame();
jf.add(txtName);
jf.add(jbSubmit);
jf.setLayout(new FlowLayout());
jf.setVisible(true);
jf.setSize(500,200);
}
}
I have a problem with Java Textfield that is when I cover all text in the JTextField and input new text immediately(do not pass backspace) into the JTextField, then I use function getText() I get the previous string not current string. Please help for some solutions. Thanks in advance.
I just tested the problem you described by adding a keyListener to a JTextField and printing the getText() method's return value to the console.
What I found out is that it is always one character behind if you want to use the getText() method right in the keyTyped or keyPressed event (I didn't know this because I usually just use a button to confirm I'm done entering the text and bind a KeyEvent to the Return key to trigger the button if a user wants to confirm by hitting enter)
I think this is due to the textField updating its text value AFTER the event is shot.
I assume this is what you did since you didn't provide sample code, so I'll delete this answer if it's not.
The work around to this is to implement what you want to do in the keyReleased method instead.
public void keyReleased(Event e)
{
System.out.println(myTextField.getText());
}
Don't use a KeyListener. The character has NOT been added to the Document when the keyPressed() event is fired.
Add an ActionListener to a JButton. This way the user clicks on the button when text is finised being entered.
Also, in the future post a SSCCE with you question so we can better understand what you are trying to do.
for example :
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class TextLabelMirror {
private JPanel mainPanel = new JPanel();
private JTextField field = new JTextField(20);
private JTextField field1 = new JTextField(20);
public TextLabelMirror() {
field.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void changedUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void insertUpdate(DocumentEvent e) {
updateLabel(e);
}
#Override
public void removeUpdate(DocumentEvent e) {
updateLabel(e);
}
private void updateLabel(DocumentEvent e) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
field1.setText(field.getText());
}
});
}
});
mainPanel.setLayout(new GridLayout(1, 0, 10, 0));
mainPanel.add(field);
mainPanel.add(field1);
}
public JComponent getComponent() {
return mainPanel;
}
private static void createAndShowUI() {
JFrame frame = new JFrame("TextLabelMirror");
frame.getContentPane().add(new TextLabelMirror().getComponent());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowUI();
}
});
}
}