I am working on a project where I have a bunch of buttons, mostly split into two groups and I would like to work with these groups through an array. Each button is an instance of class Button extends JButton and each instance has its own value (this.value = "..")
The problem is that it seems like array is being filled with previously mentioned instances, but when I try to reach them, it acts like array is filled with nulls.
Button but1, but2, but3;
Button[] buttonNumbers = {but1, but2, but3};
System.out.println(buttonNumbers.length); // returns 3, so it acts like array IS filled
System.out.println(but1.value); // prints whatever the value is
System.out.println(buttonNumbers[0].value); // throws error, element acts like null
Could someone help me out, where is the problem or what am I missing ?
Thank you for every tip or answer!
It doesn't seem like you're initializing each Button! You need to call its constructor for each Button with whatever parameters you defined:
Button but1 = new Button(), but2 = new Button(), but3 = new Button();
Button[] buttonNumbers = {but1, but2, but3};
System.out.println(buttonNumbers.length); // returns 3, so it acts like array IS filled
System.out.println(but1.value); // prints whatever the value is
System.out.println(buttonNumbers[0].value);
I'm using GWT primarily in code. I currently have a column with a TextInputCell:
public class EditPanel extends Composite{
#UiField
protected DataGrid<MyObject> dataGrid;
public EditPanel(final ActionHandler actionHandler){
...
Column<MyObject, String> inputColumn = new Column<MyObject, String>(new TextInputCell()){
... // Override of the getValue
};
inputColumn.setFieldUpdater(...);
this.dataGrid.addColumn(inputColumn, "Column title");
...
}
...
}
Based on this SO answer I know I can add a placeholder-text (or any other property) to a regular TextField in GWT like this:
TextField myInputField = new TextField();
myInputField.getElement().setPropertyString("placeholder", "some placeholder text");
However, on the TextInputCell there isn't really a getElement() method to retrieve the input-field.
When looking through the TextInputCell-class code I came across the protected getInputElement(parent) method, so I did managed to get a placeholder with the following work-around:
final TextInputCell myInputCell = new TextInputCell(){
#Override
protected InputElement getInputElement(final Element parent){
final InputElement inputElement = super.getInputElement(parent);
inputElement.setPropertyString("placeholder", "my placeholder text");
return inputElement;
}
};
Column<MyObject, String> inputColumn = new Column<MyObject, String>(myInputCell){
...
};
It works, but I have two concerns:
Obviously it is very ugly to set it like this..
The getInputElement(parent)-method isn't called initially. I do get the placeholder when I focus one of the input-field, but the property is not always added by default..
Does anyone have an actual solution of how to add a Property to the (TextInput)Cell of a Column, instead of this ugly maybe-working work-around?
EDIT: Some things I've tried:
1) Trying to retrieve the element with the getRowElement method, like in this SO question & answer:
this.dataGrid.addColumn(inputColumn, "Column title");
if (this.dataGrid.getRowCount() > 0){
final Element element = this.dataGrid.getRowElement(0);
element.setProperty("placeholder", "some placeholder text");
}
This doesn't work because getRowCount() always returns 0. I also tried a this.dataGrid.redraw(); right before it, but it still returns 0.
2) Overriding the TextInputCell as geert3 suggested:
public class MyTextInputCell extends TextInputCell{
#Override
public InputElement getInputElement(Element parent){
return super.getInputElement(parent);
}
}
The problem? I don't know what to put in for the parent-parameter. I did try this.getElement():
MyTextInputCell textInputCell = new MyTextInputCell();
Column<MyObject, String> inputColumn = new Column<MyObject, String>(textInputCell){
... // Override of the getValue
};
inputColumn.setFieldUpdater(...);
this.dataGrid.addColumn(inputColumn, "Column title");
textInputCell.getInputElement(this.getElement()).setPropertyString("placeholder", "some placeholder text");
but that doesn't seem to work. And when I try this, this.dataGrid or inputColumn it gives an error because they aren't considered as Elements (and I also can't cast them).
3) Using my initial work-around.
Problem: I can't really find a way to enforce the getInputElement(parent) method call when the page loads, instead of when an input-field is focused.
Pretty annoying that there is no way to directly access the InputFields of a TextInputCell in GWT...
I've been reading up a bit on Cells. These are in fact reused, a single Cell can render multiple DOM instances of itself, and it can handle events from multiple rendered instances. This means that a Cell doesn't have a one-to-one associated Element, but receives the "current" element as it is being reused, passed as the "parent" argument to several methods.
So in conclusion I think this means that the original solution you've described in your question appears to be a valid solution, not "ugly" at all.
ImgSet[0] = new ImageIcon("bandeira-portugal.png",
"Portugal");
ImgSet[1] = new ImageIcon("south_korea-32.png",
"South_Korea");
ImgSet[2] = new ImageIcon("China-icon.png",
"China");
ImgSet[3] = new ImageIcon("Japan.png",
"Japan");
This is my code for the image icons. I am getting the error message "java.lang.NullPointerException"!
Can you please tell me how to fix it?
My picture files are in the program folder!
Yes I did set the variable ImgSet if that's got anything to do with it.
private Icon[] ImgSet;
Initialize your array first. Thats all:)
private Icon[] ImgSet = new Icon[4];
Remember that you cannot change arrays length, after you initialize it, so select a good size, in this example it is 4.
If your collection is dynamic (you will add more elements, depending on runtime), change it to list, or set. Remember that arrays are fast, but their size is not editable.
You're just declaring ImgSet variable by doing:
private Icon[] ImgSet;
To initialize you should do something like:
private Icon[] ImgSet = new Icon[n];
Where n should be an initialized int or Integer.
You may way to use something like ArrayList or LinkedList instances from the java.util package.
Maybe you forget to initialize your array before.
Try this
ImageIcon[] ImgSet =
{
new ImageIcon("bandeira-portugal.png", "Portugal"),
new ImageIcon("south_korea-32.png", "South_Korea"),
new ImageIcon("China-icon.png", "China"),
new ImageIcon("Japan.png","Japan")
};
Doubts: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html
Well, I have another doubt. Every row of my list have those components
Label - Button(-) - Button(+) - Label(0) when I clicked on Button(+) I need to get Label(0) value and increase one unit. So I need to get Label(0) reference to set new values. I am trying to find this component with:
Label l = (Label)findByName("lblVal", c.getParent());
Label l = findLblVal();
Label l = findLblVal(c);
Label l = findLblVal(c.getPrent());
My code in List Action Listener is:
List list = (List)c;
Button b = ((GenericListCellRenderer)list.getRenderer()).extractLastClickedComponent();
if(b != null)
{
//lblVal is the name of my component in the renderer
//MY PROBLEM IS HERE, I GET NULL REFERENCE
Label l = findLblVal(c);
}
but I always get a null reference. How can I get reference to this component?
Renderer's are stateless. I suggest reading the developer guide or following the How Do I? videos.
You need to edit your model so that it includes a field matching the name of the label with the proper string that you want.
I've been looking all over, and i cant find anyone who can solve this problem. I'm making a game, and in that game, i have editable controls. the controls window is a seperate JFrame, and when i click the confirm button, it is supposed to write the items in the JTextFields (holding the controls) to a file. but that wasnt working, so instead i have it print the arraylist that holds the values. here is the code:
public void writeControls() {
ArrayList<String> al = new ArrayList<String>();
al.add(up.getText());
al.add(down.getText());
al.add(left.getText());
al.add(right.getText());
al.add(jump.getText());
al.add(duck.getText());
al.add(attack.getText());
for (int i = 0; i < al.size(); i++) {
System.out.println(al.get(i));
}
System.exit(0);
}
the problem is this: if i change the final JTextField attack or any other one for that matter, and click submit, the system prints out the default controls. for example, if the JTextFields have the values w,a,s,d,r,t,q and i change the value q to i, it prints out q. what am i doing wrong? thanks in advance!
EDIT 1:
code for the textfields, and the FILES.... is simply a string stored in a different class. the class setText() is below the textfields.
up = new JTextField(setText(FILES.controlsFileFinalDir, 1));
down = new JTextField(setText(FILES.controlsFileFinalDir, 2));
left = new JTextField(setText(FILES.controlsFileFinalDir, 3));
right = new JTextField(setText(FILES.controlsFileFinalDir, 4));
jump = new JTextField(setText(FILES.controlsFileFinalDir, 5));
duck = new JTextField(setText(FILES.controlsFileFinalDir, 6));
attack = new JTextField(setText(FILES.controlsFileFinalDir, 7));
public String setText(String fileDir, int lineNum) {
String txt = "";
txt = io.readSpecificLine(fileDir, lineNum);
txt = switchCase(txt);
return txt;
}
switchcase() is only taking what you have written in the text file that these are getting the values from, and translating them. so if the value is 0, it is turned into Space, etc. io.readSpecificLine(); is only to get the line of text from the file. does this help?
EDIT 2:
i just was dinking around and found out that if i set the JTextField text by using setText(""); then use getText(); it works. so the problem is that when i change it manually, and use getText(); it wont work. Why?
To update the text to a currently existing JTextField, I would establish the JTextField as a class variable, and create a setter/getter method to adjust it (which I'm assuming you're doing).
According to your methods, you would use something like:
up.setText(setText(FILES.controlsFileFinalDir, 7));
Edit: **The first setText is the JTextField.setText, the second setText is your public method you posted. I'm assuming your second getText() isn't working because you're probably not setting the text correctly.
Without seeing more code, I can't really give a better guess.
The main possibilities:
(1) The text fields have their editable property set to false.
(2) You are creating multiple copies of the JTextFields, then editing a new one on the screen, but referring to the old one when you get the value.
(3) You have a ValueChanged or LostFocus event handler that is resetting the text fields to their defaults
(4) It is actually JFormattedTextField not a JTextField
If I was you, I would try to debug the programm. You will probably do some Mistake in your code, you won't be able to see, by just checking the code.
For example in which order do you call the functions and so on, maybe you have a fault here, or maybe you have several threads, so you try to read the Textfields without even set them and so on ... It's hard to say without reviewing the whole Code.
So if you use eclipse you can follow this link for an explanation on how to debug: http://www.vogella.com/articles/EclipseDebugging/article.html
Netbeans or any other IDE should support debugging as well.
This may seem like a strange thing to suggest, but I think this is an issue with pointers. If you create a new string before passing it in, JTextField will be able to change it internally and return what you expect when asked for the modified value.
down = new JTextField("" + setText(FILES.controlsFileFinalDir, 2));
// or
down = new JTextField(new String(setText(FILES.controlsFileFinalDir, 2)));
You might want to try the following:
create a class Test.java
import java.util.ArrayList;
import javax.swing.JTextField;
public class Test implements Runnable {
private ArrayList<JTextField> textFields = null;
private ArrayList<String> stringList = null;
public Test(ArrayList<JTextField> textFields, ArrayList<String> stringList) {
this.textFields = textFields;
this.stringList = stringList;
}
#Override
public void run() {
for ( JTextField textField : this.textFields )
this.stringList.add( textField.getText() );
}
}
and then, at the place where you use the "getText() method .. "
do the following...
ArrayList<JTextField> textFields = new ArrayList<JTextField>();
// add all the JTextField to textFields
ArrayList<String> stringList = new ArrayList<String>();
Test test = new Test( textFields, stringList );
SwingUtilities.invokeLater( test );
// check if the stringList is populated.
If this work, then what I believe is that, for some reason, the JTextField hasn't finished
"setting" the text, and before it finishes your getText() was called. I've had similar problems before, and this solved my problem that time, but still, this might not be the perfect solution.
First, you should change your "setText()" method name to something like "getTextFromFile()" it would be more readable
Then, if you are setting and reading the new text in different threads, my bet is that the setText() is taking long to return, because it is accessing the file system, while the method that read the values run instantly
I would try to do run a little test:
public void test(){ // must be run after the JTextFields be initialized
up.setText("TEST")
System.out.println(up.getText());
up.setText(setText(FILES.controlsFileFinalDir, 1));
System.out.println(up.getText());
}
If the test() prints the correct values, then we can assume that if you set and read the new value in the same thread it works fine
The other test I would do is:
public void testThread(){
new Thread(){
public void run(){
while(true){
if(up!=null){
System.out.println(up.getText());
}
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
It will print the value of up each 1 second, so that you can see if after some time you get the new value. If it does, then the answer is: Your setText() is taking long to run and you are reading the value before the new value is set
SOLUTION
none of the above answers were working for me, so i finally decided to just start over with that class. the few things i changed were the way i made the JTextFields. I made them as an array instead of individual objects. Second is the way i put what they say. When i initialized them, i was unable to get them to create WITH the text in the parameters. so i had to do that seperately. i changed some of the method names so as to reduce future confusion, and it worked! so im not sure what was up with that, maybe it was the way i did it, maybe just a fluke. it happens sometimes, so im sorry for the delay and waste of your time! thanks for all the answers anyway!
Try this:
textbox.setText(setFile(args)); // your function for set file