public class DictionaryClient implements ActionListener {
JFrame frame = new JFrame("Amazing CW");
JPanel panel = new JPanel();
JButton button = new JButton("Send");
JTextField text = new JTextField("Field");
Book book;
DictionaryService port;
public DictionaryClient() {
panel.add(button);
panel.add(text);
frame.add(panel);
button.addActionListener(this);
frame.setSize(300,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args){
DictionaryClient client = new DictionaryClient();
DictionaryServiceService service = new DictionaryServiceService();
DictionaryService port = service.getDictionaryServicePort();
Book book = port.sendBook();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button){
System.out.print(book.getAuthor() + " " + book.getTitle());
}
}
}
I understand what a NullPointerException is but don't understand by my code is giving me this error, when I move the
System.out.print(book.getAuthor() + " " + book.getTitle());
out of the actionPerformed I get no issue at all.
Book book = port.sendBook();
Creates a local variable named book. It does not affect the field book in your DictionaryClient class, which keeps its default value of null. Change it to this:
client.book = port.sendBook();
That will assign the value to the correct field on your DictionaryClient object.
As it is now, that value is lost as soon as the main method ends and the local variable goes out of scope. When you moved the print into the main method, it was able to reference the local variable but, in your actionPerformed method the only book in scope was the field, which was never initialized.
Your Book object only has local scope in the main method. You need to change its scope to be local to the class (which you've already referenced).
Simply change this line
Book book = port.sendBook();
to
client.book = port.sendBook();
This will set the class level book variable correctly. Your actionPerformed method will then refer to that instance variable accordingly.
Check this out:
the following declaration/initialization
Book book = port.sendBook();
was made inside of the static main method, and since your class DictionaryClient has a member with the same name, then this object in the main method is shadowing the book of the DictionaryClient, when the actionPerformed is triggered, you are not in the static main anymore, so you book defined and well initialized there is back for good...
the only book available in that scope is the defined in the class...
but is was never initialized therefore a NPE.
Related
What I want to achieve is very simple.
I have 2 classes. "SpeedingTicket" & "SpeedingTicket GUI".
Inside my GUI I have 1 textbox name txtSpeedLimit & a button.
Inside my SpeedingTicket class I have a variable "int speedingTicket".
Inside my SpeedingTicket class I also have a get & set method for "speedingTicket".
I know how to get and set text using JTextFields, but I want to be able to:
receive input from the "txtSpeedLimit", and store that value into the "txtSpeedLimit" instance variable in the "SpeedTicket" class. I can then check for validation etc when I come to adding the vehicle speed.
Maybe this isn't the most efficient way of dealing with this program. Maybe I should scrap the instance variables in SpeedingTicket, and deal with it all in the GUI.
Any advice would be hugely appreciated.
Basically what I'm trying to do is this:
class confirmHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
String val = txtSpeedLimit.getText();
int realNum = speed.getSpeedLimit() = txtSpeedLimit; < but obviously that doesn't work, but I want the textbox link to the variable.
EDIT: If we take away the GUI, all I want my program to do is the following:
Speed Limit: 50 < enterd via textfield
Speed: 60 < entered via textfield
if the speed is blah blah (ive already coded this).. then output a result to one of my labels.
I achieved this without making a GUI and making it only console based, but instead of the user typing it via the console, I want it to be typed via textfields.
THe values that are entered into the textfields should be stored in the two variables (speed and speedlimit) that are in the SpeedingTicket class.
You can update a value in:
public class SpeedingTicket {
int speedingTicket;
public SpeedingTicket() {
speedingTicket = 500;
}
public int getSpeedingTicket() {
return speedingTicket;
}
}
by:
public class SpeedingTicketGUI extends JPanel{
SpeedingTicket st;
SpeedingTicketGUI() {
st = new SpeedingTicket();
setLayout(new FlowLayout(FlowLayout.LEFT));
JTextField txtField = new JTextField(10);
txtField.setText(""+st.getSpeedingTicket());
add(txtField);
JButton btn = new JButton("Update");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setSpeedingTicket(txtField.getText());
}
});
add(btn);
}
private void setSpeedingTicket(String text) {
try {
int speedTicket = Integer.parseInt(text);
st.setSpeedingTicket(speedTicket);
System.out.println("Speeding ticket set to " +st.getSpeedingTicket());
} catch (NumberFormatException ex) {
System.out.println("Invalid value " +text);
ex.printStackTrace();
}
}
public static void main(String[] args){
JFrame frame = new JFrame("Speeding Ticket");
frame.setSize(400,100);
frame.add(new SpeedingTicketGUI());
frame.setVisible(true);
}
}
You don't need to store values in JText or any GUI componenets...
Use global static variables. For example:
public static int speed_limit;
You can access this variable from ANY method,class, etc.
There are multiple ways to do it.
You can detect textfield changes by using a DocumentListener or if you want (not recommended) by a KeyListener.
The Listener could be implemented directly by your gui class or by your other class. If you want more abstraction you could implement the DocumentListener by your gui class and create a method
public void addSpeedChangeListener(SpeedChangeListener scl) {
this.speedChangeListeners.add(scl);
}
Your SpeedChangeListener could be very simple:
public interface SpeedChangeListener {
public void speedChanged(int value);
}
Then your second class implements the SpeedChangeListener and calls addSpeedChangeListener(this) on your gui class. Inside the gui class, your document listener calls speedChanged(val) for every listener registered.
EDIT
You can also use the Button and call the speedChanged on every listener inside the actionPerformed method of the ActionListener.
I think it would be easier to use a JOptionDialog which pop ups when the button is clicked. That way you can easily get input and also validate the input straight away.
Is there any way to retrieve the declaring class of an instance at runtime?
For example:
public class Caller {
private JFrame frame = new JFrame("Test");
private JButton button = new JButton("Test me");
private Callee callee = new Callee();
public Caller() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(button);
button.addActionListener(callee.getListener());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new Caller();
}
}
The callee:
public class Callee {
public ActionListener getListener() {
return new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
/* Get the class "Caller" here and invoke its methods */
/* Something along the lines of: */
Object button = e.getSource();
button.getOwnerClass(); //This would return the type Caller
}
};
}
}
"getOwnerClass()" is an imaginary method. Is there a way to get a result similar to that?
There is nothing in the standard API that allows you to get this information. It's a bit unclear what you mean with 'declaring class' or 'owner class' but for this sake of this answer I'll assume that it is the class whose code created the instance of the object (that you want the owner class from).
This information is not stored by the JVM by default.
But, using the heap profiler that is packaged along with the JDK distribution, you can record the stacktrace of the point at which objects are allocated, and this information can be written to a file on various points in time.
That still doesn't give you an API call to retrieve the information, but it shows that it is technically possible to record this type of information.
I search a bit on Google and found that someone did create an API that uses the same basic technique as the heap profiler (the java.lang.instrumentation package/JVMTI interface)
Open source project: java-allocation-instrumenter
With a bit of work you should be able to build something with it.
The site has a nice example:
AllocationRecorder.addSampler(new Sampler() {
public void sampleAllocation(int count, String desc, Object newObj, long size) {
System.out.println("I just allocated the object " + newObj +
" of type " + desc + " whose size is " + size);
if (count != -1) { System.out.println("It's an array of size " + count); }
}
});
Instead of printing, you should get the stacktrace using new Exception().getStackTrace(), remove the first few StackTraceElement objects that refer to the sampler and the API classes, and then call StackTraceElement.getClassName() to get the name of the class that created the object instance, in other words, your OwnerClass.
I have a problem with a variable in MyFrame class. I want to have in MyFrame class the value of a variable that is defined in a combobox listener.
This is my situation: I have a combobox with some friends' name. I have put a listener to the combobox which has to return the surname of the selected friend.
I want to insert the value of surname in a command in MyFrame class, but there are some problems: once setted surname as final (because it has to be used in the Listener), I have an error that say:
The final local variable surname cannot be assigned, since it is defined in an enclosing type.
What is (or are) the matter(s)? Here I post my code:
public class MyFrame extends {
public static void main (String[] args)
{
//other
String [] names = {"john","al","jack"};
final String surname=null;
JLabel nameLbl = new JLabel("surname: " + surname);
JComboBox box = new JComboBox(names);
JPanel centralPnl = new JPanel();
centralPnl.add(nameLbl);
centralPnl.add(box);
box.addItemListener(new ItemListener()
{
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
{
// Here operations from database
//that return friends' surname under the variable name of "result"
surname = result;
}
}
});
}
}
You are trying to reassign a final variable, and thats the problem.
Also your final variable needs to be initialised in the first place.
Beyond the issues with the code already pointed out, I guess the question is do you need to store surname or are you just using it to update the label?
If you need to store the data, move your surname variable to the class level.
If you are simply updating the label, then do something like
nameLbl.setText("surname: " + result);
There are two things first one is that final variable must be initialized when it is declared and that final variable cannot be reassigned a value.
Unfortunately you are doing both of the mistakes.
Another problem is that you should post a Valid code; it will make others finding problems easily.
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.
I am making a game, I have got several different classes as I dont like to put everything in one. I have a GameView class and a players class. The problem is that I am calling a method in players class from GameView. But its giving me an null pointer error. Below is my code:
GameVie class:
Panel p2 = new Panel();
p2.setLayout(new BorderLayout());
JLabel player1Lbl = new JLabel("Player 1");
p2.add(player1Lbl, BorderLayout.WEST);
player.enterNameP1(); //Having an error here.
player1Lbl.setText(player.enterNameP1());
Players Class:
public class Players
{
//storing the player 1 name
private String p1name;
//storing the player 2 name
private String p2name;
/**
* Constructor for objects of class Players
*/
public Players()
{
this.p1name = p1name;
this.p2name = p2name;
}
/**
*Enter the player 1 name in a dialog box
*/
public String enterNameP1() //It was public void before but it wasnt accepting a void method in the gameView so I changed it to String
{
this.p1name = JOptionPane.showInputDialog("Please enter player 1 name","Specify name");
return p1name;
}
you should initialized player first..... ?
Players player = new Players();
Your player isn't initialised at the moment you call:
player.enterNameP1(); //Having an error here.
To solve this, you have to make sure that the reference player actually points to a real instance of Player. This should be done by adding at a logic place in your code this:
player = new Players();
That is the reason why you got a NullPointerException. When you call a method from a specific object, the object must be initialised (which means that the pointer player points to an actual instance of the class Players).
You did not instantiated player
So it is null causing a NPE