I'm working on getting the value of a textfield from another class using Vaadin.
my solution is something like this.
public class MyTextField{
String str;
public MyTextField(){
TextField text = new TextField();
str = text.getValue().toString();
}
public String getStr(){
return str;
}
}
public class MyButton{
public MyButton(){
Button button = new Button("UPDATE");
button.addListener(new Button.ClickListener(){
#Override
public void buttonClick(ClickEvent event) {
MyTextField text = new MyTextField();
System.out.println(text.getStr());
}
});
}
}
the problem is, I always get null result. any help is highly appreciated. Thank you.
In all likelihood the MyTextField object inside of your buttonClick method is not the same MyTextField that is being displayed to the user. A solution is to get a reference to the class that holds the displayed MyTextField, and then call a public method on that reference to extract the text.
Edit 1
Note that I'm not familiar with Vaadin, but your MyTextField class looks suspicious in that you're declaring the TextField inside of the constructor making it visible only in the constructor. I'm also not sure what calling getValue() on it immediately and before any event, before the user's had a chance to interact with the component, will do. This looks very suspicious to me.
Edit 2
For instance, if this were Swing, I'd do something like:
public class MyTextField{
TextField textField = new TextField();
public MyTextField(){
}
// so it can be added to the gui
public TextField getTextField() {
return textField;
}
public String getStr(){
return textField.getValue().toString(); // not sure if this is correct
}
}
public class MyButton{
private MyTextField textField;
private Button button = new Button("UPDATE");
public MyButton(final MyTextField textField){
this.textField = textField;
button.addListener(new Button.ClickListener(){
#Override
public void buttonClick(ClickEvent event) {
System.out.println(textField.getStr());
}
});
}
}
Edit 3
You ask:
you have declared "private MyTextField textfield" as a field and add a parameter (MyTextField textfield) from the MyButton constructor. does it mean that I have to pass the class MyTextField to the MyButton class as a reference?
Again, note that I am not familiar with Vaadin, but I am familiar with general use of Java objects, and this I know. If you want to have one class (here MyButton) get the state of another object (here MyTextField), then the first object needs a valid reference to the second. One way to get this reference is by passing it in as a constructor parameter. Another is via a setter method, say by giving MyButton a setMyTextField(TextField textField) method, and then assigning the reference to your field. Another option is via "dependency injection", but I think that this may be a little too advanced for now, but do consider it in the future.
If you try to do it as you're doing it in your original post, things will likely fail, since sure, you're giving MyButton a MyTextField object, but what MyTextField object is this? It's one that has been created in the MyButton class and is present no where else.
I would rather do some thing like this, to achieve what you are doing. This is based on the assumption that you are trying to read the user entered value on click of a button.
There are two option to achieve this.
Option 1
public class MyTextField extends TextField{
public MyTextField(){
}
public String getStr(){
return this.getValue();
}
}
public class MyButton extends Button{
public MyButton(){
setCaption("UPDATE");
}
}
//Add in your presentation logic
final MyTextField text = new MyTextField();
MyButton button = new MyButton();
mainLayout.addComponent(text);
mainLayout.addComponent(button);
button.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
System.out.println(text.getStr());
}
});
Option 2
public class MyTextField extends TextField{
public MyTextField(){
}
public String getStr(){
return this.getValue();
}
}
public class MyButton extends Button{
public MyButton(final MyTextField text){
setCaption("UPDATE");
addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
System.out.println(text.getStr());
}
});
}
}
//And in your presentation logic
final MyTextField text = new MyTextField();
MyButton button = new MyButton(text);
mainLayout.addComponent(text);
mainLayout.addComponent(button);
Please let me know if in case if this is not what you are expecting.
And Kudos to Hovercraft Full Of Eels for trying to help him out
Thanks.
Related
How to place Action Listener directly in definition of class that extends Button ?
If object of class Button is created then we could simply use anonumous inner class :
b = new Button("Click me");
b.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("stringToPrint");
}
}
);
how to do the same in below :
class CustomizedButton extends Button{
String customClass;
Button(String stringToPrint){
super(customClass); //customClass is also button name
this customString = stringToPrint;
}
/*this.addActionListener( //don't work this way
new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println(customClass);//use outer(?) field
}
}
);*/
}
I need to create 20 almost identical but slightly different buttons, so anonymous inner is too long
You could declare a private nested class, like so:
public class CustomizedButton extends Button{
String customClass;
CustomizedButton(String stringToPrint){
super(customClass); //customClass is also button name
this.customString = stringToPrint;
addActionListener(new MyListener());
}
private class MyListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO: listener code here
}
}
}
But it's not much different from using an anonymous inner class or lambda:
public class CustomizedButton extends Button{
String customClass;
CustomizedButton(String stringToPrint){
super(customClass); //customClass is also button name
this.customString = stringToPrint;
addActionListener(e -> myListenerCode(e));
}
private void myListenerCode(ActionEvent e) {
// TODO: listener code here
}
}
Having said this, other issues come to mind:
Usually it's best to favor composition over inheritance. I would bet that what you really want is some sort of factory method that creates your button complete with listener
Why use AWT components such as the java.awt.Button class when it is 20+ yrs out of date? Why not Swing JButtons instead?
If you were using Swing JButtons, best would be to create a custom Action rather than extend JButton. Actions can hold and change many button properties, including a listener, the displayed text, icons, the tool tip text (displayed on hover)....
For that matter, you should favor JavaFX if this is a new project, since this is the current best-supported Java GUI library.
For example an AbstractAction class could look something like:
public class CustomizedAction extends AbstractAction{
String text;
CustomizedAction(String text, int mnemonic){
super(text); //text is also button name
this.text = text;
putValue(MNEMONIC_KEY, mnemonic); // for alt-key short cut if desired
}
#Override
public void actionPerformed(ActionEvent e) {
String currentName = getValue(NAME); // same value as the text field
System.out.println(currentName);
// TODO: more listener code here
}
}
and could be used like so:
JButton button = new JButton(new CustomizedAction("Foo", KeyEvent.VK_F));
I'm very new to coding(2 months) and i attempted to make Tic-Tac-Toe in java. I'm in a little over my head but i managed to create it using swing. My main problem is in the button1 class. I was going to use the getText() method but ended up not needing it or so i thought. I tried deleting it but as it turns out my tictactoe buttons don't switch letters without it. The compiler told me it overrides AbstractButton's getText() method but i don't see why that should matter since i never actually used it i thought. I'm thinking it's maybe a scope issue handled by it being overwritten somehow but i'm not sure. I was trying to use the text variable to update the button with setText() and that doesn't seem to work like i thought it should. I also don't understand why the 3 by 3 gridlayout seems to work properly most of the time but sometimes the number of buttons added is wrong.
So in summation the program works(mostly) but i'm not fully understanding how the button1 class is working.
TicTacToe.java
import java.awt.*;
import java.util.*;
import javax.swing.*;
public class TicTacToe extends JFrame {
public static void main(String[] args) {
JFrame window = new JFrame("Tic-Tac-Toe");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.setSize(600, 600);
window.setLayout(new GridLayout(3, 3));
ArrayList<button1> buttonArrayList = new ArrayList<>(9);
for (int i = 0; i < 9; i++) {
button1 newbutton = new button1();
buttonArrayList.add(newbutton);
window.add(buttonArrayList.get(i));
}
}
}
button1.java
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
public class button1 extends JButton {
int value = 0;
String text = "";
public button1() {
class ButtonAction extends AbstractAction {
public ButtonAction() {}
#Override
public void actionPerformed(ActionEvent Switcher) {
System.out.println(text + " " + value);
value++;//value is a relic from earlier attempts that i just felt like keeping.
if (text.equals("O")) {
text = "X";
} else if (text.equals("X")) {
text = "";
} else if (text.equals("")) {
text = "O";
}
}
}
this.setAction(new ButtonAction());
this.setText(text);
this.setFont(new Font("Arial",Font.PLAIN,120));
}
public String getText()// <----culprit
{
return text;
}
}
A JButton class has a methods defined for it, including setText() (which will set the displayed text on the button) and getText() (which will return the current text that is displayed on the button).
You created a class button1 (note: classes should start with Capital Letters).
You added an Action to the button1 class, which means that when the action is activated, something happens. Note that in that actionPerformed method, you should call setText(text) to update the displayed value.
You have also defined a getText() method that overrides the getText() method defined in JButton. This approach is fine if it is a conscious design decision. As it is, I think you should remove the getText() method from the button1 class, and allow the standard JButton class to handle the update. Right now, you are attempting to keep an instance variable text with the value, but it is possible for that instance variable to not be in alignment with the actual displayed value of the button (consider another class calling .setText() on the button).
EDIT: It is true that this referring to the JButton in the ButtonAction is not available. However, the Action itself contains the button that was pressed.
#Override
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
// if desired, String cur = btn.getText() may be called to find the
// current setting; get and process if needed
btn.setText(WHAT_EVER_TEXT);
}
Unless it is a specific requirement to process the current text, however (allowing selecting an O to an X to a blank), I would implement something to keep track of the current turn. This code is something I was experimenting with, and has good and bad points to it (as it is illustrative):
static class TurnController
{
// whose turn it is; start with X
private Player whoseTurn = Player.X;
// the instance variable
private static final TurnController instance = new TurnController();
private TurnController()
{
}
public static Player currentTurn()
{
return instance.whoseTurn;
}
public static Player nextTurn()
{
switch (instance.whoseTurn) {
case X:
instance.whoseTurn = Player.O;
break;
case O:
instance.whoseTurn = Player.X;
break;
}
return instance.whoseTurn;
}
public static String getMarkerAndAdvance()
{
String marker = currentTurn().toString();
nextTurn();
return marker;
}
enum Player
{
X,
O,
;
}
}
Using this TurnController, the actionPerformed becomes:
#Override
public void actionPerformed(ActionEvent e)
{
JButton btn = (JButton)e.getSource();
btn.setText(TurnController.getMarkerAndAdvance());
}
and the Button1 class may have the String text instance variable removed.
What you have tried is Try to make a Custom Button Class and its EventHandler just by extending AbstractAction namee button1 as we See in Your Question.
You have Override the method actionPerformed(ActionEvent Switcher) which actually belongs to Class AbstractAction by your own definition (What should Performed on Action Event of Every Button).
class ButtonAction extends AbstractAction {
public ButtonAction() {}
#Override
public void actionPerformed(ActionEvent Switcher) { // Your Definition For actionPerformed..
System.out.println(text + " " + value);
value++;//value is a relic from earlier attempts that i just felt like keeping.
if (text.equals("O")) {
text = "X";
} else if (text.equals("X")) {
text = "";
} else if (text.equals("")) {
text = "O";
}
}
}
this.setAction(new ButtonAction()); // add ActionListener to each Button.
this.setText(text); // Setting Text to each Button
this.setFont(new Font("Arial",Font.PLAIN,120)); //add Font to each Button.
}
Now In this Code.
ArrayList buttonArrayList = new ArrayList<>();
for (int i = 0; i < 9; i++) {
button1 newbutton = new button1(); // Creating 9 new buttons.
buttonArrayList.add(newbutton); // add each button into the ArrayList.
window.add(buttonArrayList.get(i)); // each Button to the the AWT Window.
}
Above Code will generate 9 Button and add it to Your AWT Window. each button have actionPerformed() method which contains the overrided Definition.
Now Each button will performed action as per the definition you give to actionPerformed() Method.
Thank You.
I want to have several JavaFX Buttons that update one Label in my Application with text. For testing purposes it's just Button Text.
What I did at first worked fine and looked like this:
String Text = "...";
public void kons() {
System.out.println("Works...");
System.out.println(Text);
Tekst.setText(Text);
Button G4 = new Button("Spadantes");
G4.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Text = G4.getText();
kons();
}
});
Then I decided to stylize my buttons with CSS and because I wanted to have several groups of buttons stylized in different way I subclassed JavaFX Button class in this way:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
Which still worked. But now I want my event handler to be moved to Button subclass (to avoid copy-pasting exactly same code into each and every button of mine). What I did looks like this:
public class Buttons extends Button {
public Buttons(String text) {
super(text);
getStylesheets().clear();
getStylesheets().add("./Buttons.css");
setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Main.Text = getText();
Main.kons();
}
});
}
}
Main is my extend Application class
Tekst is my label.
And sadly it throws me exception about calling non-stathic method and variable from static context. From what I understand instances are static and definitions are non-static. I tried to change everything "in the way" to static but it gives me red wall of errors after clicking button (nothing in compilation process). I also tried to call instance of my Application somehow but I have no idea how (from what I understand extend Application class intantiates itself on it's own while starting program so there's no "name" by which I can call it's Label.
What I'm looking for is "quick and dirty solution" to be able to use subclassed buttons (or other sliders, text-fields, etc.) that can call a method that updates something "on screen".
[EDIT] I'm using newest Java there is of course. In case it matters.
Instead of subclassing, why not just write a utility method that creates the buttons for you? I would also not recommend making the text variable an instance variable: just reference the Label directly.
public class SomeClass {
private Label tekst ;
// ...
private Button createButton(String buttonText) {
Button button = new Button(buttonText);
button.getStylesheets().add("Buttons.css") ;
button.setOnAction(e -> tekst.setText(buttonText));
return button ;
}
}
Then, from within the same class, when you need one of those buttons you just do
Button button = createButton("Text");
If you really want to subclass (which just seems unnecessary to me), you need to pass a reference to the label to the subclass:
public class LabelUpdatingButton extends Button {
public LabelUpdatingButton(String text, Label labelToUpdate) {
super(text);
getStylesheets().add("Buttons.css");
setOnAction(e -> labelToUpdate.setText(getText()) );
}
}
Then from your class that assembles the UI you can do
public class Main extends Application {
#Override
public void start(Stage primaryStage) {
Label tekst = new Label();
Button someButton = new LabelUpdatingButton("Button text", tekst);
// etc...
}
}
But again, creating a subclass that does nothing other than define a constructor that calls public API methods is redundant, imo.
Also, it's a bit unusual to create an entire stylesheet just for your buttons. Typically you would set a style class on the Button:
button.getStyleClass().add("my-button-class");
and then in the stylesheet you add to the Scene do
.my-button-class {
/* styles for this type of button */
}
I hope this question is not really a repetition of an existing one! I searched and found no good answer to my question. Here it is:
I have a class MyGame that contains a Button member object. Whenever that button is clicked, MyGame should do something.
class MyGame extends Application {
MyBoard board = new MyBoard();
MyButton btn = new MyButton();
public MyGame() {
board.add(btn);
}
// this method should be called whenever the button is clicked!
public void doSomething() {
doingSomething();
}
}
class MyButton extends Button {
int someData;
// some code here
public MyButton() {
this.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
MyGame.doSomething(); // ==> NOT POSSIBLE!!!
}
});
}
}
Would an interface be the best way to make the communication between the MyButton and MyGame go? If so, how would you do it?
I don't want to hand over a reference of MyGame object to the MyButton object! I think this is not a good way to resolve this problem.
I appreciate any suggestions and help!
Cheers
In the constructor of MyGame you can add an ActionListener to btn that will be called when an action is performed on the button.
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Insert thing to do within MyGame here
}
});
One way is to do it the other way around (game should be a member of button). I know that you think "it is not a good way to resolve this problem", but you think wrong, there is really nothing wrong with it.
Alternatively, move the registering of the listener out of the button's constructor into the game itself:
public MyGame() {
btn.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent arg0) { doSomething(); }
});
}
Make the "button action" an interface that can be passed to the constructor when creating MyButton. Example:
public MyButton(final Runnable action) {
this.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
action.run(); // POSSIBLE!!!
}
});
}
or save the action in a MyButton instance field:
public MyButton(Runnable action) {
buttonAction = action; // make buttonAction an instance field
this.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
buttonAction.run();
}
});
}
Then when MyGame creates a new MyButton, the MyGame gets to tell the button what to do when the button is clicked:
MyButton btn = new MyButton(new Runnable() {
#Override
public void run() {
MyGame.this.doSomething();
}
}
or in Java 8:
MyButton btn = new MyButton(this::doSomething);
NOTE: I haven't yet tested this. I think I got the syntax right, but I may have made a mistake. You may need to assign btn in the MyGame constructor rather than in an initializer expression.
This is a generalized approach (dependency injection?) that works in lots of situations. There may be other solutions specific to Button (or other Swing components for which a listener mechanism is already defined). But this mechanism reduces coupling, because the MyButton doesn't really need to know anything about who created it, and the MyGame doesn't need to know what the MyButton plans to do with the Runnable action. Some other possible solutions involve having MyGame doing some of MyButton's work, which increases coupling.
Is it possible to pass a String to an ActionListener? I'm creating a number guessing game, and I need to pass the difficulty selected to the the ActionListener, because it's passed from the first GUI opened. How would I do this as it's passed directly to the Game() constructor?
Have your ActionListener access a variable that contains the result of the guess.
I would do something like:
final JTextArea textArea = new JTextArea();
JButton button =new JButton("press");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
String text = textArea.getText();
if (text.equals("something")) {
doSomething();
} else {
doSomethingElse();
}
}
});
Where does the string come from? You can pass that component to the ActionListener when constructed. For example, your string comes from a JLabel object. Then
class GuessNumberActionListener implements ActionListener {
private JLabel difficulty;
public GuessNumberActionListener(JLabel difficulty) {
this.difficulty = difficulty;
}
// implement other methods
}
Then inside your action listener, you can access/update what you want.
ActionListener is an interface. try extending the functionality of the interface using inheritance. this will do the trick
Sure you can. There are lots of ways but one of them is to pass it in to the the ActionListener's constructor:
public class MyClass implements ActionListener {
private int difficultyLevel;
public MyClass(int difficultyLevel) {
this.difficultyLevel = difficultyLevel;
}
public void actionPerformed(ActionEvent e) {
...//code that reacts to action and does something based on difficultyLevel
}
}
UPDATE:
Looks like the design patterns police are out in full force today. You may want to quickly rewrite your app in MVC before you get shot in the foot :)
http://java.sun.com/products/jfc/tsc/articles/architecture/