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.
This might sound a bit complicated, I'll try to simplify what I am asking.
A program I am developing can read and write from/to files using a JTextArea. When files are rather large, it does take a cumbersome amount of time to read the data from that file into the text area. As an example, I have a file that currently has 40,000 lines of text, roughly 50 characters a line; also, some lines wrap. There is quite a lot of text and it takes a lot more time to read from that file then I would like.
Currently, I am using the standard read method utilizing a BufferedReader instance that the JTextArea component includes. What I would like to do is load the JTextArea with a certain amount of text loaded on screen. The rest of the text that is off-screen loaded in a separate thread in the background.
Would using a InputStream and write each character to an array then write characters to the JTextArea be sufficient? Or should there be a different approach at this? I'm trying to accomplish a fast and efficient read method.
There are two, immediate, issues at hand
First, the need to read a file in such away that it can progressively update the UI without causing unacceptable delays
Second, the ability for the JTextArea to actually deal with this amount of data...
The first issues is, relatively, simple to fix. What you need to make sure of is that you are not blocking the Event Dispatching Thread while you read the file and that you are only updating the JTextArea from within the context of the Event Dispatching Thread. To this end a SwingWorker is an excellent choice, for example...
public class FileReaderWorker extends SwingWorker<List<String>, String> {
private File file;
private JTextArea ta;
public FileReaderWorker(File file, JTextArea ta) {
this.file = file;
this.ta = ta;
}
public File getFile() {
return file;
}
public JTextArea getTextArea() {
return ta;
}
#Override
protected List<String> doInBackground() throws Exception {
List<String> contents = new ArrayList<>(256);
try (BufferedReader br = new BufferedReader(new FileReader(getFile()))) {
String text = null;
while ((text = br.readLine()) != null) {
// You will want to deal with adding back in the new line characters
// here if that is important to you...
contents.add(text);
publish(text);
}
}
return contents;
}
#Override
protected void done() {
try {
get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
// Handle exception here...
}
}
#Override
protected void process(List<String> chunks) {
JTextArea ta = getTextArea();
for (String text : chunks) {
ta.append(text);
}
}
}
Take a look at Concurrency in Swing and Worker Threads and SwingWorker for more details
ps- You don't need to use the List to store the contents, I just did it as an example...
The second problem is far more complicated and would need some additional testing to ensure that it is actually a problem, but generally speaking, contents of over about 1mb tends to lead to issues...
To this end, you would need to be able to manage the JScrollPane, be able to request chunks of text from the file both in backwards and forwards direction and try and effectively "fudge" the process (so that you only have the text you need loaded, but can still make it look like you have all the text loaded within the JTextArea)...
You could also take a look at FileChannel, which provides more functionality over the standard java.io classes, including memory mapping, for starters, have a look at Reading, Writing, and Creating Files.
You also might consider using a JList or JTable which are highly optimised for displaying large quantities of data. There are limitations to this, as there is an expectation of fixed row heights, which when changed (to dynamic row heights) can affect the performance, but might be a suitable alternative...
So I have this project,
the source code is here.
When you run the project and goto Processing, there is a jcombobox there that is suppose to have an addActionListener.
p_customer_list = new JComboBox<>(customers_name);
pp_customer_list.setPreferredSize(new Dimension(360, 35));
panel_processing_header.add(pp_customer_list);
//pp_customer_list.addActionListener(this);
pp_customer_list.addActionListener (new ActionListener () {
public void actionPerformed(ActionEvent e) {
JComboBox tmpBox = (JComboBox) e.getSource();
int selected = tmpBox.getSelectedIndex();
pp_refresh_data(selected);
}
});
This is what I have so far, its suppose to find the selected index when the value of the combobox changes and pass it to pp_refresh_data() but for some reason it does not run (I tried putting a JOptionPane to see when the code is executed, and its only executed once when the program runs.)
Hard to tell from just a partial code snippet, but do you have 2 combos, one named "p_customer_list" and another named "pp_customer_list"?
This could be your problem. You may be adding the listener to the wrong combo, or you may be adding the wrong combo to your panel, or maybe you don't need two, or maybe...
Again, it's hard to tell from just a snippet.
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
I have a JButton which launches a JFileChooser. However the JFileChooser often takes a few seconds to come up, during which time the user might think that nothing is happening. I tried to make the button become disabled until the JFileChooser is finished with, but the disabling of the button doesn't even happen until the JFileChooser is loaded. Is there something I can do?
My code:
public void actionPerformed(ActionEvent e) {
System.err.println("clicked");
((JButton) e.getSource()).setEnabled(false);
System.err.println("set");
JFileChooser b = new JFileChooser("C:\\");
b.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int res = b.showOpenDialog((Component) e.getSource());
if (res == JFileChooser.APPROVE_OPTION) {
try {
//Blah
}
catch (Exception err) {
JDialog j = new JDialog(window, "An error occured:\n" + err.getMessage());
}
}
((JButton) e.getSource()).setEnabled(true);
}
Move these lines..
JFileChooser b = new JFileChooser("C:\\");
b.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
..from the action performed method to the constructor of the action listener, change them to..
b = new JFileChooser("C:\\");
b.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
..then declare..
private JFileChooser b;
..as a class attribute (so it is visible to the action performed method).
You might also want to give it a better name.
The chooser will be constructed when the class is created, and be ready for use when needed. This has the added benefit that the chooser will remember the position, size, path & file display type, the subsequent times the user activates the button.
Yet another strategy is to declare the chooser as a class attribute, don't instantiate it in the constructor, but check in the action performed if it is null, and if so, create and configure it.
Continued..
I might want to do something a bit slower like this at some point, that doesn't quite deserve its own thread.
With the last strategy I outlined, I was considering adding something that I will add now.
..Continued
..Of course, that last method will give exactly the same problem you describe, but just once when the user 1st clicks the button. For that situation, you should probably be looking to pop a JOptionPane with an indeterminate JProgressBar from inside a SwingWorker.
Obviously, a SwingWorker creates a new Thread, but OTOH, Thread objects in Java are cheap. There are a number of them running for any app. with a GUI. A couple more will not hurt.