How do I make variables accessible everywhere? - java

I am using java swing and I have tried using new text as a parameter but I am not sure how, there is also the fact that I have "});" which is completely messed up but it works, and i tried fixing it and it doesn't work
this code is inside my main
public String newText = "";
a.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JFrame popup = new JFrame("Choose...");
popup.setSize(250,250);
popup.setLayout(null);
popup.setVisible(true);
JButton o=new JButton("o");
o.setBounds(25,75,100,100);
popup.add(o);
o.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae, String newText){
newText = "O";
}
});
JButton x=new JButton("x");
x.setBounds(125,75,100,100);
popup.add(x);
if (!newText.equals(""))
a.setText(newText);
}
});

I have tried using newText as a parameter
Here?
public void actionPerformed(ActionEvent ae, String newText){
This is not valid code. ActionListener is an interface; an interface is a contract that must be followed. You cannot simply add variables to existing method signatures.
Assuming you wanted to modify the button text, you could do this
public class Main {
public String newText;
public static void main(String[] args) {
new Main().run();
}
public void run() {
System.out.printf("before: newText = %s%n", newText);
final JButton o = new JButton("o");
// ...
o.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae){
Main.this.newText = "O"; // Sets the field
System.out.printf("action: newText = %s%n", Main.this.newText);
o.setText(Main.this.newText);
}
});
System.out.printf("actionListener set : newText = %s%n", newText);
}
}
However, trying to use newText.equals outside of the action listener happens on a different thread, meaning the code does not run "top to bottom". E.g. the variable isn't "set" in the execution order that the code reads as. Added print statements to show this

Related

Action Listener is not working when I press a Button

I got this code but when I run it the actionListener is not working.
Code
public class MenuPrincipal extends javax.swing.JFrame implements ActionListener {
public MenuPrincipal() {
initComponents();
this.setVisible(true);
this.setLocationRelativeTo(null);
this.addListener();
this.jButton1 = new JButton();
this.jButton2 = new JButton();
}
public static void main(String args[]) {
new MenuPrincipal();
}
private void addListener() {
this.jButton1.addActionListener(this);
this.jButton2.addActionListener(this);
JOptionPane.showMessageDialog(null, "Activado");
}
#Override
public void actionPerformed(ActionEvent event) {
if(event.getSource().equals(this.JButton1){
// do something
}
if(event.getSource().equals(this.JButton2){
// do something
}
}
}
I'm using Netbeans to make the interface, thus I'm not pasting here the generated code.
You should write something in the method of the handler:
#Override
public void actionPerformed(ActionEvent event) {
System.out.println("button pressed!");
}
and your class should implement the ActionListener interface
Alternatively you can use the java8 lambdas:
btn.addActionListener(e -> {System.out.println("button pressed!)});
remove this 2 lines from the constructor
this.jButton1 = new JButton();
this.jButton2 = new JButton();
Since addLsiteners method didnt throw any exception, that means you have already instantiated those JButtons. if you re instantiated then those fields will have the reference to different instances than the instance you added the action listener .

Disable buttons on GUI in Swing

I have buttons on a GUI that execute tests when clicked on in Selenium. They can only be run serially and are currently added to EventQueue. I would like it so that if a button is clicked on and a test is executed, then it will disable the other buttons so that other tests cannot be added to a queue.
Currently a button looks like:
Test1 = new JButton("Test1 ");
Test1.setLocation(290, 30);
Test1.setSize(120, 30);
Test1.addActionListener(this);
Test1.addMouseListener(new MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent e) {
if (Test1.isEnabled()) {
Test1.setEnabled(false);
errorLabel.setText("");
service.submit(()->{
Result result = JUnitCore.runClasses(Test1.class);
EventQueue.invokeLater(()->{
errorMessageDisplay(result);
Test1.setEnabled(true);
});
});
}
}
});
buttonPanel.add(Test1);
I have used the EventQueue as it allows me to reset update Pass/Fail error messages on the GUI.
How can I best achieve this?
You should add ActionListener to your button. What's even more important, you should use naming conventions what also means that your objects' names should start with a small letter. Capital letters are reserved for Classes and static fields (all upper case). The following code adds an ActionListener to your JButton and disables it after clicked. If it's not what you're looking for, I'll add another version in a moment.
test1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
test1.setEnabled(false);
}
});
In case, you want to keep the state of your button, but don't disable it, the following code might be a solution:
private final static String ENABLED = "ENABLED";
private final static String DISABLED = "DISABLED";
public static void main(String[] args) {
Map<JButton, String> map = new HashMap<>();
JButton test1 = new JButton();
map.put(test1, ENABLED);
test1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (map.get(test1).equals(ENABLED)) {
//do something
} else {
//do something else. I'll enable.
map.remove(test1);
map.put(test1, ENABLED);
}
}
});
}

java enable the second textfield if the first textfield is not empty

I have 2 textfields in my project. The first textfield is txtNumA and the second is txtNumB. I disabled txtNumB. When txtNumA is not empty, txtNumB will be enabled.
Well, this is part of code I've tried:
private void txtNumKeyTyped(java.awt.event.KeyEvent evt) {
if(!(txtNumA.getText().trim().equals(""))){
txtNumB.setEnabled(true);
}
else {
txtNumB.setText(null);
txtNumB.setEnabled(false);
}
}
Actually it works, but not perfect. It works only if I typed 2 or more characters in txtNumA. What I need is when I typed one character and more, txtNumB will be enabled.
What's wrong with my code?
What is happening here is,
In case of KeyTyped and KeyPressed events the input is not still given to the TextField.That's why it is not working and works after you type the second character and by that time first character must have reached the TextField.So use KeyReleased method to handle this case.
t is the first TextField and t1 is second.
t.addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
JTextField bt = (JTextField)e.getSource();
if(bt.getText().trim().length()>0){
t1.setEnabled(true);
}
else
t1.setEnabled(false);
}
});
The correct way is to add a DocumentListener to the Document of your JTextField:
public final class TextFieldListener implements DocumentListener {
public static void main(final String... args) {
SwingUtilities.invokeLater(() -> new TextFieldListener().go());
}
private final JFrame frame = new JFrame();
private final JTextField field = new JTextField();
private final JTextField field2 = new JTextField();
private TextFieldListener() {
field.getDocument().addDocumentListener(this);
frame.setLayout(new GridLayout(2, 0));
frame.add(field);
frame.add(field2);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
onFieldUpdated();
}
private void go() {
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void onFieldUpdated() {
setField2Enabled(!field.getText().isEmpty());
}
private void setField2Enabled(final boolean enabled) {
field2.setEnabled(enabled);
}
#Override
public void insertUpdate(final DocumentEvent e) {
onFieldUpdated();
}
#Override
public void removeUpdate(final DocumentEvent e) {
onFieldUpdated();
}
#Override
public void changedUpdate(final DocumentEvent e) {}
}
It is not correct to add a KeyListener to your text field if you are interested in changes to its content.
Further reading:
JTextComponent
Document
Text Component Features
How to Use Text Fields
How to Write a Document Listener
I think the problem with this working for 2 characters is because getText() method returns not updated value, i.e. it returns the value BEFORE the change. What you need to do is somehow update that value before you compare it to empty string.
You may need to investigate KeyEvent to see if user adds another character or is it e.g. backspace...

return from Jframe by jbutton

I have Jframe that has a JTextField and a JButton. It should return text of Jtextfield to anotherClass (MainPage).
but when program starts, It returns null to the class.
public class JframeFoo extends JFrame {
private String username = new String();
public JframeFoo() {
// --------------------------------------------------------------
// Making Frame for login
final JTextField usernameFiled = new JTextField();
this.add(usernameFiled);
JButton signinButton = new JButton();
// ------------------------------------------------------------
signinButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
Main.mainpage.setVisible(true);
}
});
// ----------------------------------------------------------------------
username = usernameFiled.getText();
}
public String getuserName() {
return this.username;
}
}
(this Jframe should run at the start of program and when it gets text, it should go to invisible and another class should become visible.)
You need to move the call to username = usernameField.getText() into the actionPerformed method. It only gets set to null the way you currently have it.
The constructor JFrameFoo() is called when that frame is created. Therefore, this line:
username = usernameFiled.getText();
is also called at that moment. What you want to do instead is:
signinButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
username = usernameFiled.getText();
setVisible(false);
Main.mainpage.setVisible(true);
}
});
EDIT
What I expect is also going wrong is that you use userName in your main class before it is initialized. I would recommend two things:
Learn about event-driving programming and callbacks. The simple fact that a line is below another in the source does not mean that it is executed later.
Instead of calling mainPage.setVisible, do something like
signinButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
setVisible(false);
Main.mainpage.open(usernameFiled.getText());
}
});
and add that method in your mainpage, doing something like
public void open(String username) {
this.setVisible(true);
// do whatever you want to do with username
}
In addition to calling the getText() method from within the actionPerformed overridden method, you can also use this.dispose(); rather than setVisible(false);
so your code would look something like:
signinButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
username = usernameFiled.getText();
if ((username != null) || !(username.length() == 0)) {
this.dispose();
Main.mainpage.setVisible(true);
} else {
// Appropriate error here...
}
}
});
Calling getText() from within actionPerformed will also allow you to do some checks on the username variable before you dispose of the frame and proceed (again, see above snippet).
Good luck!

Make text in JButton not visible

I made a button and did a .setText() on it because I have to compare the value of the .setText() with something else.
I applied the .setText() to a JButton, but I don't want the text to be visible in my button.
If I do setVisible(false) then it hides the whole button, but I only want it to hide the text.
Is there an option for this? I've considered making a custom font and apply it on the text in the .setText() but I'm wondering if there's a more efficient option to my problem.
Thanks in advance guys.
EDIT: I can't use .setText(" ") because I have to compare the value within it.
You state:
EDIT: I can't use .setText(" ") because I have to compare the value within it.
Nonsense. As I've mentioned in a comment, set the JButton's text to " ", and don't use the JButton's text for comparison. Instead use its actionCommand easily obtained via getActionCommand(). Or use a HashMap<JButton, SomethingElse>.
You may consider changing the JButton's Action when you need to change its behavior and state which is easily done by calling setAction(...)
For example,
import java.awt.event.ActionEvent;
import javax.swing.*;
public class ButtonActions {
private static void createAndShowGui() {
JPanel mainPanel = new JPanel();
JButton myButton = new JButton();
StartAction startAction = new StartAction();
PauseAction pauseAction = new PauseAction();
BlankAction blankAction = new BlankAction();
startAction.setNextAction(pauseAction);
pauseAction.setNextAction(blankAction);
blankAction.setNextAction(startAction);
myButton.setAction(startAction);
mainPanel.add(myButton);
JFrame frame = new JFrame("ButtonActions");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class SwappingAction extends AbstractAction {
private Action nextAction;
public SwappingAction(String text) {
super(text);
}
public void setNextAction(Action nextAction) {
this.nextAction = nextAction;
}
public Action getNextAction() {
return nextAction;
}
#Override
/**
* super method needs to be called in child for swap to work
*/
public void actionPerformed(ActionEvent e) {
System.out.println("ActionCommand: " + e.getActionCommand());
((AbstractButton)e.getSource()).setAction(nextAction);
}
}
class StartAction extends SwappingAction {
public static final String START = "Start";
public StartAction() {
super(START);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
// start-specific code goes here
}
}
class PauseAction extends SwappingAction {
public static final String PAUSE = "Pause";
public PauseAction() {
super(PAUSE);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
// pause-specific code goes here
}
}
class BlankAction extends SwappingAction {
public static final String BLANK = " ";
public BlankAction() {
super(BLANK);
}
#Override
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
}
}
Write buttonName.setText(" ") this will not display any name to the button. And whenever you feel like displaying the name (on any event) then set it again buttonName.setText("some text")
If you insist not to use setText(""), try setting same colour as a background colour and text colour. Check the below links
setBackground(java.awt.Color)
setForeground(java.awt.Color)
Why don't you name the first button " " (1 space).
the second: " " (2 spaces)
the third: " "(3 spaces) and so on ..
Now, compare:
if((event.getActionCommand()).equals(" "))
{ //1st button }
if((event.getActionCommand()).equals(" "))
{ //2nd button }
..and so on
where event is an object of ActionEvent
This way the buttons will have a unique names and be invisible.
Horrible coding, I know. But it does the trick ;)
Instead of .setText(), use .setTag() and .getTag() to attach some value to a View - including a Button - for later retrieval.
These methods are there directly for that kind of purpose.

Categories

Resources