I'm re doing a specific application, just a basic text editor and I remember I had tabs and a JMenu so if you went File --> New it would add or 'Open' another tab on the JTabbedPane. But this time it's not doing it for me, could someone help? Here is how im doing it:
newFile.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
tabs.addTab("new file", text);
}
}
);
So when it's clicked it should add another tab but it's not for some reason...
If it matters there is a default tab open at the beginning and when you click new it wipes out the old one.
Thanks for any help! (Please ask if you need anymore explanation)
Here I uploaded my code here since the editor here kept saying I the way I was putting it in wasnt formatted correctly:
http://nardcake.com/java
There is 2 files there, one initializes it and the other is everything else
thanks!
try:
tabs.revalidate();
tabs.repaint();
I have removed these two lines (those two are anyhow called in the end by addTab() method), and rewritten your init.java like this:
public static void main(String[] args) {
System.out.println(SwingUtilities.isEventDispatchThread()); // 1
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
System.out.println(SwingUtilities.isEventDispatchThread()); //2
EBLFWE window = new EBLFWE();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setExtendedState( window.getExtendedState()|JFrame.MAXIMIZED_BOTH );
window.setSize(1024, 728);
window.setVisible(true);
}
});
It works now. To quote myself:
Every usage of Swing components must be done thorugh the Event Dispatch Thread (abbreviated EDT) or you will probably get unwanted visual effects. See here for explanation.
EDIT:
All the GUI related code must be executed on the EDT. You can test if some part of your code is run by EDT like this:
System.out.println(SwingUtilities.isEventDispatchThread());
If it prints true you are safe to do a GUI update (e.g. call methods on Swing components instances) - like in 1 or anywhere in EBLFWE class. However 2 will print false - it is because the thread that runs your program is not EDT.
When calling SwingUtilities.invokeLater() you are actually placing that code to be executed (at some appropriate time the EDT sees fit) in the Event dispatch thread.
EDT does the actual painting, and a lot of other tasks, so when you call GUI update code from another thread you can mess up the order and get unwanted visual apperance.
Related
I know many people have asked this question before but I couldn't find any answer that solved my problem. My code is like this:
public void mouseClicked(MouseEvent arg0) {
TEXT.setText("ON");
myfunction(); //runs for a very long time
}
The original text of JLabel is "OFF". Now I want to change the text to "ON" when the mouse is clicked but the text doesn't set until myfunction() is complete (which may take several minutes).
I have tried the invalidate function, making a separate function for setting the text but nothing is working.
Please help me with this problem!
The problem is that mouseClicked(...) is executed on the UI Thread. That is the Thread that is responsible for handling all sorts of user actions (like a mouse click) and also the drawing of components (like updating the text of the label on screen). If you execute your long running method call on the UI thread, it will be blocked and can't draw anything until execution is complete. You'll have to use multi threading to get around this problem.
The following might not be the most elegant solution, but if you are new to multi threading it will get the job done:
public void mouseClicked(MouseEvent arg0) {
TEXT.setText("ON");
(new Thread() {
public void run() {
myfunction();
}
}).start();
}
It will spawn a new Thread that handles your method, which will let the UI Thread continue doing its thing. consider deactivating the button that has just been clicked, so the user can't start the execution while it is already in progress (which usually is what you want..)
I have created a JFrame with a textArea called 'outputTextArea' and I want to print the results from a database query in the textArea. However, the variable outputTextarea is not static and therefore I can't call the method setText() in the main method to print the db resultset in the textArea.
I would like to know how I can make this variable (private javax.swing.JTextArea outputTextArea;) static, because NetBeans won't let me edit this variable because it was generated by NetBeans when I dragged and dropped the textArea.
I had the same problem.
In Netbeans IDE 8.0.2:
1) In the design tab
2) Click on the textarea
3) go to properties -> code
4) Variable Modifiers -> add static.
It worked for me.
Just add an accessor method to your class that adjusts the field. For instance:
public void setTextAreaText(String newText) {
outputTextArea.setText(newText);
}
Then anyone with a reference to your class can adjust the text in the text area. Just be sure to call that method from the Event Dispatch Thread. This is usually achieved with SwingUtilities.invokeLater
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myClassReference.setTextAreaText("Hello, World");
}
});
See the documentation on Event Dispatch Thread if this sort of thing is new to you. It's important to get threading correct when using Swing.
If you just want to edit codes. Open code with another editor just like notepad or something. And if you remove GEN-BEGIN:initComponents just before the auto generated code you can edit code through netbeans also.
I have a java class called GameUpdater which extends JInternalFrame.
It used to extend JFrame when I ran the class as a program by itself, but I changed it to JInternalFrame to become part of a larger application - now accessible from a menu button.
The function being called when I press this menu button is as follows:
private void update(){
GameUpdater gu = new GameUpdater();
desktop.add(gu); //add to JDesktopPane
gu.setSize(400, 300);
gu.setVisible(true);
gu.readMatches();//this function takes ages
gu.setMatch("Updating database...");//this is some output to the user, displays info in the internal frame
//try and insert into database
for(Match m : gu.getMatches()){
db.insertMatch(m);
}
gu.setMatch("DONE"); //now it shows the frame, way too late
}
The method gu.readMatches() takes a long time to execute, so it periodically updates content in the JInternalFrame to display its progress. However the frame is not being shown until this update function is complete!
It's like setVisible(true) is waiting until the end of the function...
It worked absolutely fine when it was a JFrame. Is there any weird property of a JInternalFrame that would cause this?
Cheers
It sounds like you're executing a time consuming process inside the Event Dispatching Thread (EDT), this will prevent the event queue from process (amongst other things) repaint requests.
This will cause you program to appear as if it has "hung".
You need to off load this task to a background thread.
Have a read through Concurrency in Swing, especially the section on Worker Threads and SwingWorker
The problem is that you are blocking your EDT this can be taken care of by simply creating a new Thread/Runnable thar calls gu.readMatches(); the method:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
gu.readMatches(); //gu will have to be declared `final`
gu.setMatch("Updating database...");//this is some output to the user, displays info in the internal frame
//try and insert into database
for(Match m : gu.getMatches()){
db.insertMatch(m);
}
}
});
ofcourse though you might want to implement a JProgressBar so the user can keep track of of how far the reading is.
I'm working on a simple Java swing project. This is the code of the main class (name changed):
public class MainProg
{
private static MainProg program;
//mainWin is a JFrame
private MainWindow mainWin;
//Event handler class which extends MouseAdapter
private TrayManager trayMgr;
public static void main(String[] args)
{
program = new MainProg();
}
public MainProg()
{
mainWin = new MainWindow();
trayMgr = new TrayManager();
mainWin.startBtn.addMouseListener(trayMgr);
mainWin.setVisible(true);
}
}
As is clear, when the program starts, in main() it creates a new instance of the MainProg class, which then calls the constructor. In the constructor, it creates a new instance of the JFrame mainWin. It then attaches an event handler to a button on mainWin.
In the event handler class trayMgr, the only method is mouseClicked() which does nothing
except a System.out.println('Clicked');
The issue is, when I run this program in Netbeans, the JFrame is shown right away, but I seem to have to click the button 2-3 times before the message is printed in the console.
Is this just something specific to Netbeans, or do I have to change something to make the event handler be set before the window is made visible?
Your threading issue is not likely one that is causing your current problem, but there's the theoretic potential for problems, and I've seen some real problems associated with some of the more touchy look and feels. Quite simply you should queue your code that starts your GUI onto the Swing event thread. You do this by doing:
public void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(
public void run() {
program = new MainProg();
}
));
}
Someone else recommended using invokeAndWait(...) instead of invokeLater(...) but this can be risky especially if you inadvertently make this call from within the Swing event thread itself. For your situation you're better off using invokeLater(...).
But again, I think the main problem with the code you have shown was inappropriate use of MouseListener where an ActionListener should have been used. Learning to code any GUI library can be quite tricky, and for that reason, you can't assume anything. Check out the tutorials and learn from the experts. Also if you are considering coding Swing for the long haul, consider ditching the NetBean's code-generation utilities and learn first to code Swing by hand. You won't regret doing this.
Since you asked, the code I posted here is a Java SSCCE on a different topic. invokeLater is a way of running computations on the EDT. (There is also invokeAndWait, which would work fine here, but under some other conditions can cause a deadlock.)
In fact this example is perhaps a bit over-conservative. Some references say you can run Swing from the main thread the call to show() or setVisible(). However I have a program that misbehaves under Java 7 when I try that.
I want to write a program, which search some HTML addresses. I assume that one search will be going more than 1 minute. When I print the results to console everything is OK, but when I make a frame the results don't appear in textpane. Now I have two classes one to search and one for frame. I write the simply function in the frame class to check if adding text working:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String Txt=(String)jComboBox1.getSelectedItem();
jTextPane1.setText("");
addText(Txt);
SecondClass.find(Txt);
}
public void addText(String text){
StyledDocument doc = jTextPane1.getStyledDocument();
try{
doc.insertString(doc.getLength(), text, null);
}catch(Exception e) { System.out.println(e); }
}
And in SecondClass I write the same line to addText, but it is working only from frame class. The second problem is that if the search is going I cannot do anything in program and the text from frame class is see after search is finished. I want see text immediately after finding it like in console which is working and I want to have possibility to click this link before search is ended ( I don't implement clickable links yet and don't know how to do this). I think that I must synchronize the processes, but I don't know how to do this.
It sounds like you are doing the main downloading task on the special Swing event thread, which handles all the work for Swing components. This will prevent the GUI from responding properly.
This will happen 'by accident' if you do long-running actions within event handlers (e.g. when you press a JButton).
You need to do long-running tasks in a separate thread, then 'hand over' the data to the Swing thread to update the GUI, using SwingUtilities.invokeLater(runnable); Edited: or see Max's answer about SwingWorker.
For example, your worker thread would do something like this when it has some data ready, using an anonymous Runnable:
final String text = getText();
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
appendText(text);
}
});
where getText() just indicates some means of acquiring the downloaded text, and appendtext() is a method you will need to write to update your textpane.
Check out SwingWorker. It should help you with handling lengthy operation and managing intermediate results as well. There is a sample in this manual that illustrates use of publish() and process() methods to append intermediate text results to JTextArea.