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
Related
I'm trying to create a small program, where you have to guess words while you are shown a matching anagram. My code is like:
JFrame frame = generateJFrame(BACKGROUND, FOREGROUND);
JLabel display = generateDisplay(BACKGROUND, FOREGROUND);
Pair now = woerter.shuffle();
display.setText(now.getAnagram());
JTextField input = generateInputBox(BACKGROUND, FOREGROUND);
ActionListener action = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
nextWord(now, woerter, display, input);
}
};
input.addActionListener(action);
[...]
private static void nextWord(Pair now, Woerter woerter, JLabel display, JTextField input) {
if (now.getRealWord().equalsIgnoreCase(input.getText())) {
now = woerter.shuffle();
display.setText(now.getAnagram());
input.setText("");
}
}
Now when I execute it, it works the first time (when you type in the correct word and press enter a new anagram is displayed and the inputfield clears), but afterwards it breaks and enter doesn't do anything anymore.
What am I doing wrong? Any help would be appreciated.
Pair now = woerter.shuffle();
You are defining "now" as a local variable.
now = woerter.shuffle();
But you also reference it in your nextWord(…) method, which indicates you have also defined it as a static variable.
Don't define the variable twice. Get rid of the local variable:
//Pair now = woerter.shuffle();
now = woerter.shuffle();
Also, defining methods and variables as static indicates a poor design. Your nextWor() method should not be static and therefore the "now" variable will not need to be static.
Read the section from the Swing tutorial on How to Use Text Fields. The TextDemo code will show you how to better structure your code so that the ActionListener of the text field can access the text field and the rest of the data in your class.
So download the working demo code and modify it to meet your requirements.
I am struggling to fix this for like 2 hours and still nothing really happened. I've tried updating the JLabel with multiple methods like revalidate, paintImmediately, etc, although it didn't change the final result.
public void notificationtos( ) {
jLabel2.setText( "Read our ToS first, please." );
jLabel2.revalidate();
jLabel2.paintImmediately(jLabel2.getVisibleRect());
System.out.println("debug" );
System.out.println( jLabel2.getText() );
}
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
if( prihvaceniuslovi == false ) {
new notification().notificationtos();
new notification().setVisible(true);
}
}
Also on debugging, here's the output from the code above:
run:
debug
Read our ToS first, please.
BUILD SUCCESSFUL (total time: 3 seconds)
GUI shows up normally, but the string isn't being changed from the one that's been set on initialization of the JLabel.
Instead of this string below that's been shown in photo...
GUI Photo here
this one should've been shown
"Read our ToS first, please."
I would be very grateful if someone could actually help me. Thanks!
EDIT, Here's the solution code, thanks alot #camickr
private void jButton1MouseClicked(java.awt.event.MouseEvent evt) {
if( prihvaceniuslovi == false ) {
notification objekt = new notification();
objekt.setVisible(true);
objekt.notificationtos();
}
}
There is no need for repaint() or revalidate() or paintImmediately(). All that is needed is to invoke the setText() method.
If the text doesn't change on the frame then you have two labels:
One that you added to the frame and
another one that is just sitting in memory.
The problem would be the code below:
new notification().notificationtos();
new notification().setVisible(true);
You should NOT keep creating new instances of a component. A component should be created once and then you save a refrence to the variable in your class that that you can make changes to the component in the future.
Read the section from the Swing tutorial on How to Use Text Areas. It shows how you can keep adding text to the same text area. You need to restructure your code to be similar to the demo example.
my goal is to be able to draw graphs and then save its values if required.
In the image above, I choose from the comboBox a specific type of graph to draw, except for Clear, which just clears the graph that is shown. This is already working correctly.
I have an arrayList of UserPattern(I created) objects that contains a string, a double and a double array.
I want to store the values from the graph in some variable (i'm currently using a double array) to use it later on.
With the double array I've had problems with the passing of values, since when I press "Save Pattern" it keeps the latest values of the graph (the last graph shown) and inputs it on every element of the UserPattern List that I have previously saved. So, even if I save multiple patterns, they all keep the value of the last save.
This is the code I use to store the values in the ArrayList:
private void readAndInsertPatternValues(List<UserPattern> patternLi, double[] graphValue) {
UserPattern tempUserPattern = new UserPattern(typePattern);
//extra code
tempUserPattern.setMonthlyConsump(consTemp);
tempUserPattern.setNameID(patternName);
tempUserPattern.setPatternValues(graphValue);
patternLi.add(tempUserPattern);
System.out.println("Inserted: ");
System.out.println(tempUserPattern);
}
}
I call this method within a mouse event on the button "Save Pattern":
JButton btnSaveUserPattern = new JButton("Save Pattern");
btnSaveUserPattern.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(!((comboBoxPattern.getSelectedItem()).equals(UserPattern.PatternType.CLEAR)))
readAndInsertPatternValues(patternList, patternValue);
for(UserPattern upTemp : patternList) {
System.out.println("Inside the Pattern List:");
System.out.println(upTemp.toString());
}
}
});
btnSaveUserPattern.setFont(new Font("Tahoma", Font.PLAIN, 13));
btnSaveUserPattern.setEnabled(false);
Also, I get the values that create the graph in the event from selecting an option of the combobox:
comboBoxPattern = new JComboBox<UserPattern.PatternType>();
comboBoxPattern.setFont(new Font("Tahoma", Font.PLAIN, 13));
comboBoxPattern.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//this method creates the graphs, so I send the array "patternValue" to "get" the values.
printPatternGraph(comboBoxPattern, chartPanel, "User Pattern for Energy Consumption", "Hours", "Energy Consumption(Wh)", true, patternValue);
btnSaveUserPattern.setEnabled(true);
}
});
I initialized the patternValue array as a local variable in the method that calls and uses the above mentioned methods as such:
double[] patternValue = new double[1440];
With all this, happened the problem in transporting values. At the "insertion time", the console showed the correct values, however, when I clicked on the "Save Pattern" button, which shows all the objects in the UserPattern list, the graph values from the previously saved graphs were equal to the one I saved last. (The last one I saved corrupted all the others).
I tried to change the way of passing values and changed the method "printPatternGraph" to return a double[] array, and made like this:
patternValue=printPatternGraph(comboBoxPattern, chartPanel, "User Pattern for Energy Consumption", "Hours", "Energy Consumption(Wh)", true);
This, however, brought me the error,
Local variable patternValue defined in an enclosing scope must be final or effectively final.
Therefore, I tried making "patternValue" a global variable . This actually solved the problem, but I don't think that this is the best solution (I've read multiple times that global variables are "bad coding".
This way, which way do you think I should implement this?
Thanks for your attention and sorry for the long post,
nhekas
SOLUTION:
I understood what was wrong! Sorry to bother you guys.
My problem, was, that when I added the double array to the ArrayList, I did it like this:
patternLi.add(graphValues);
This, instead of storing the values inside the graphValue array, was storing the reference to it. Therefore, when I wanted to create a different graph, the reference to the graph was the same, but changed the values.
I had to do the following:
new double[] arrayTemp= new double[1440];
for ( int i=0; i<1440;i++) {
arrayTemp[i]=graphValues[i];
}
patternLi.add(arrayTemp);
This way, it worked! Because, since arrayTemp is local, is created everytime I call the method and passes the correct values.
Thanks for all your input guys !
nhekas
New to asking questions here on stack overflow. I have a program that has me stumped. I have been able to get it to work but just not in the manner I would prefer and I was wondering if some of you could take a look at it and help me figure out what I am doing wrong. Please see below:
For the beginning, the program doesnt compile in class Output at
String ageStr = Input.getAge().toString();
int ageInt = Integer.parseInt(ageStr);
because getAge() returns the address, not the Text of JTextField. Integer can't parse that, as it inhabits not only integers.
And so does all your static getters only return not intended data.
Try to change those in class Input after this sample:
public static String getAge() {
return age.getText();
}
and don't forget to add the outputPanel in class Output
add(outputPanel, BorderLayout.CENTER);
Additionally,
make those methods non-static as stated by others
separate / encapsulate code into fitting methods and improve your API
keep an overall persistent code appearance.
One option is to define an object variable and change your Output-Constructor:
Input input; // keeps a ref to input
public Output(Input input) {
super("Output", 300, 300);
this.input = input;
String ageStr = input.getAge();
...
And the call to:
public void actionPerformed(ActionEvent e){
output = new Output(Input.this);
output.display();
...
Hope it helps you.
Ok here is what I changed, like I said I'm still getting an error. So far all I have tried to fix is the code associated with the age. I will work the rest when i figure out how to make this work. See new code below. I can get it to work if I leave everything static but I know that's not the appropriate method. Tried to fix the formatting as well.
I am learning Java with Swing and I have some problems with using JTextField. In my program I want to dynamically add a few JTextFields with some text:
while( (ln = bufFile.readLine()) != null ) {
// inIdPanel is JPanel
inIdPanel.add(new JTextField(ln));
}
And it works good. However, the content of these JTextFields can be modified by users, and later I want to call getText() from all of them. Is this possible? How can I do this?
I saw this question: Java Swing: JButton creates new JTextField(s) but this isn't enough to solve my problem (I think using arrays in my case is not a good idea but maybe I'm wrong).
The reason why you cannot call getText() is that you have not stored a reference to the JTextField when you created it. You will need to use an array or collection to store the JtextFields as you create them so you can call the method on them later. A collection will be easier than an array because you do not know how many lines you will read in so you want it to be able to grow.
List<JTextField> fields = new ArrayList<JTTextField>();
while( (ln = bufFile.readLine()) != null ) {
JTextField field = new JTextField(ln);
inIdPanel.add(field);
fields.add(field);
}
Then you can call the .getText() from all of them
for(JTextField field: fields){
System.out.println(field.getText());
}
For an easy solution, just add an ArrayList<JTextField> textFieldList and add to the code you posted:
while((ln = bufFile.readLine()) != null) {
textFieldList.add(new JTextField(ln));
inIdPanel.add(textFieldList.get(textFieldList.size()-1));
}
Then, when you want to access the text fields, you simply iterate through them, e.g.
for (JTextField jtf : textFieldList) {
/* Operate on jtf, call methods, etc */
}
You could replace the ArrayList with an array if there is a defined limit on how many text fields you could add, but the list is nice if that quantity is unknown.