Hi noticed some code in our application when I first started Java programming. I had noticed it created a dialog from a separate thread, but never batted an eye lid as it 'seemed to work'. I then wrapped this method up through my code to display dialogs.
This is as follows:
public class DialogModalVisibleThread
extends Thread {
private JDialog jDialog;
public DialogModalVisibleThread(JDialog dialog, String dialogName) {
this.setName("Set " + dialogName + " Visable");
jDialog = dialog;
}
#Override
public void run() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
}
Usage:
WarnUserDifferenceDialog dialog = new WarnUserDifferenceDialog( _tableDifferenceCache.size() );
DialogModalVisibleThread dmvt = new DialogModalVisibleThread( dialog, "Warn User About Report Diffs");
dmvt.start();
Now, as far as I am now aware, you should never create or modify swing components from a separate thread. All updates must be carried out on the Event Dispatch Thread. Surely this applies to the above code?
EDT on WikiPedia
However, the above code has worked.
But lately, there have been countless repaint issues. For example, click on a JButton which then calls DialogModalVisibleThread to display a dialog. It caused buttons alongside the clicked button not to redraw properly.
The repaint problem is more frequent on my machine and not the other developers machine. The other developer has a laptop with his desktop extended onto a 21" monitor - the monitor being his main display. He is running Windows 7 with Java version 1.6.0_27.
I am running on a laptop with Windows 7 and Java version 1.6.0_24. I have 2 additional monitors with my desktop extended onto both.
In the meantime I am going to upgrade to Java 1.6 update 27.
I wondered if the above code could cause repaint problems or are there any other people out there with related paint issues?
Are there any easy ways to diagnose these problems?
Thanks
So, you're breaking a rule, having problems, and wondering if these problems could be cause by the fact that you broke the rule. The answer is Yes. Respect the rules!
To detect the violations, you might be interested by the following page: http://weblogs.java.net/blog/2006/02/16/debugging-swing-final-summary
The easiest way to check if your problems are being caused by breaking the rules is to fix them (You should fix them anyway :-)
Just use SwingWorker.invokeLater() from the thread you want to update to UI from to easily adhere to Swing's contract. Something like this should do the trick:
#Override
public void run() {
SwingUtilities.invokeLater(new Runnable() {
jDialog.setVisible(true);
jDialog.requestFocus();
}
});
}
EDIT: You should make the 'jDialog' variable final for this to work.
Related
I have eclipse 3.7 indigo; I installed gwt plugin and its designer; The problem is (time after time) when I add new widget X to composite the
palette (keeps widget selected)
components (doesn't show the new widget in the tree)
properties (doesn't show the new widget properties)
...so I cannot select another widget unless I resize the whole eclipse application to force its GUI repaint :(
It seems like palette and other managers don't get report "widget was added from windowbuilder" or similar :(
Moreover, I cannot edit widget's text if I have input method as "System" which is the default on btw so the only one input method which works is "X Input Method" but anyways it doesn't solve the mentioned focus regain problem;
That makes eclipse indigo really hard to use; So my question is... how to fix that?
p.s.
eclipse 3.7 (indigo)
gwt plugin - https://dl.google.com/eclipse/plugin/archive/3.6.0/3.7
gwt designer - http://dl.google.com/eclipse/inst/d2gwt/latest/3.7
gwt sdk 2.2
jdk 1.7
jre 1.7
OS Linux x64
Thanks
I had to do my own research concerning the issue; I noticed there is some kind of "jobs order conflict" or similar with the default constructor based code style as :
public class MyTestUI extends Composite {
private FlowPanel flowPanel;
public MyTestUI() {
flowPanel = new FlowPanel();
initWidget(flowPanel);
}
}
...so, as a workaround, I had to play with code generator as;
window -> preferences -> windowbuilder -> gwt
(combobox) method name for new statements : initComponents
variable generation : field
statement generation : flat
just to avoid having in-constructor init as a result I have code generated as :
public class MyTestUI extends Composite {
private FlowPanel flowPanel;
public MyTestUI() {
initComponents();
}
private void initComponents() {
flowPanel = new FlowPanel();
initWidget(flowPanel);
}
}
...btw there is a problem with focus regain if input method is "System" and initComponents() method generated first time; so before starting adding widgets I had to select "X input method" to avoid synch-ed jobs; So "X input method" needs to be the default one, as I can get it :)
EDIT :
The effect I faced very looks like bug 388170; So I tried to modify eclipse.ini argument as
-Djava.awt.headless=true
It seems like the headless helps a bit but anyways eclipse sometimes does hang when using windowbuilder especially DnD :P
Anyways I want to point I faced the mentioned issue first time cause similar windows x32 eclipse indigo version works pretty fine with gwt;
p.s.
The solution is not final (the hang problem still occurs on DnD evens) and I am still looking for a more optimal one; So do comment if you have some helpful tips or ideas;
So I'm writing a boid simulation program as a project for school. My program supports multiple different groups of these boids that don't flock with other groups, they all have different settings which I do by adding a BoxPanel to the main GUI of the program when a new tribe is made, and those BoxPanels have a settings button that opens a new frame with the groups settings.
This works perfectly when I start the program up and add all the pre defined tribes that are in the code. Now I made a new part of the GUI that let's you make new groups of these boids and adds them while the simulation is running, and here is when the problems start for me.
For some weird reason it adds the group just fine, with the right settings in to the simulation but it wont add the BoxPanels to the main GUI. It makes the whole settings bar that I have in the side of my simulation disappear completely. I tested this out and if I add the tribes in the beginning of my calculation thread it does the same thing, so this seems to be a problem with multiple threads and swing. Any ideas what is causing this or how to fix this? I am completely perplexed by this.
tl;dr: The code below for adding tribes works fine when I haven't started the thread but if I try to use it after starting the thread the optionPanel appears empty.
Here's the code that adds the BoxPanels to the main gui:
def addTribe(tribe: Tribe) = {
tribeFrames += new TribeSettingFrame(tribe)
tribeBoxPanels += new TribeBoxPanel(tribe)
this.refcontents
}
private def refcontents = {
top.optionPanel.contents.clear()
top.optionPanel.contents += new BoxPanel(Orientation.Vertical) {
tribeBoxPanels.foreach(contents += _.tribeBoxPanel)
}
top.optionPanel.contents += new BoxPanel(Orientation.Horizontal) {
contents += top.addTribeButton
}
top.optionPanel.contents += new BoxPanel(Orientation.Horizontal) {
contents += top.vectorDebugButton
}
}
new Thread(BoidSimulation).start()
Oh and I tested if it really adds the contents that it should by printing out the sizes of the contents, and everything matches fine, it just won't draw them.
EDIT: After some digging around it really seems to be a thing with updating swing from a Thread. A lot of places suggest to use SwingWorker but from the info I gathered about it I don't think it would fit in my program since it is a continuous simulation and and I would have to keep making new SwingWorkers every frame.
EDIT2: Tried calling the method from the thread like this:
SwingUtilities.invokeLater(new Runnable() {
override def run() {
GUI2D.addTribe(tribe)
}
});
Didn't make any difference. I am starting to think that this is a problem with how I use TribeBoxPanel and TribeSettingFrame. These are objects that both contain only one method that returns the wanted BoxPanel or Frame. Is this implementation bad? If so what is the better way of creating dynamic BoxPanels and Frames?
Swing is not thread-safe.
Repeat after me.
Swing is not thread-safe.
Hear the chorus? Swing is not thread safe There is official documentation.
There is a very simple workaround given as well.
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
// your stuff
}
});
In Scala, this is supported as:
Swing.invokeLater(/* your stuff */)
First you should let the UI thread handle all UI manipulation.
The simple way should be following Scala-Code:
Swing.onEDT { GUI2D.addTribe(tribe) }
But as you already noted, this won't solve your problem. I had a very similar problem where I only changed the text content of a Swing.Label and it sometimes simply disappeared.
It turned out that it only disappeared, when the text was too long to display it inside the Area which the Label initially reserved for itself. So one way around your Problem could be to give the optionPanel a bigger initial size when you create it.
Swing.onEDT { top.optionPanel.preferredSize = new Dimension(width,height) }
I'm not quite sure whether this has to be set before the component is first drawn (before Frame.open() is called).
Nowadays, I am working on a java swing application using DJ NativeSwing as my embed browser to do something automatic work. The scenario of my application is that a user click start button and the embed browser auto click some position of the current page and then redirect to another one and then execute some other operations like click or something other. Now here is my solution. First, I will define a webbrowser class (extends JWebBrowser) and webbrowser listener class (implements WebBrowserListener), which represents a webbrowser and contains loadingProgressChanged, windowOpening and so on separately. Second, I define a thread class to do some logic computing and execute my browser operations as mentioned above by webbrowser.executeJavascript. At last, I add mouseListener for start and stop button to start or stop the task. When I open my application, the JFrame add the browser and its listener class. I click the start button, the browser works and will click the target position as I expected and then the page will redirect to another one. As we all know, js code can’t be executed until the page was loaded completely. So I set a global flag to check whether the page has loaded completely or not in loadingProgressChanged (code:if(e.getWebBrowser().getLoadingProgress() == 100)globalflag = true;) within webbrowser listener class. And in the thread class, I use code( while(globalflag == false){Thread.sleep(500);}) after first click to detect if the current page was loaded completely. However, when browser first click the target position and the page redirects successfully, I find that the current page has changed but blocked. After some debugging, I find it. In my thread class, browser will execute js code by webbrowser.executeJavascript("document.getElementById(‘target’).click();") to click the target position and then java code (while(globalflag == false){Thread.sleep(500);}) to detect if the current page was loaded completely and then execute some other java code. I find that the globalflag will never change and the current page’s loadingProgressChanged listener will never work because the java code (while(globalflag == false)). Because after I remove all java code after the first webbrowser.executeJavascript("document.getElementById(‘target’).click();"), the current page’s loadingProgressChanged listener works and the page was not blocked. With the DJ NativeSwing demo, I could execute my js in the loadingProgressChanged. However, I want to do a series of operations with my browser and also want to stop the task whenever need. So, I prefer to my solution for my demand rather than the provided one by demo. So, I wonder that after webbrowser.executeJavascript the DJ NativeSwing thread will wait my thread? And, in my software architecture, does anyone could have any suggestions? Thanks a lot. Any suggestion is appreciated!
PS.my application works fine with jdic-0.9.5, but it supports IE7 only.
I paste my code here to demonstrate my problem:
After I click the start button in JFrame, I will new a thread as follow
public class MyVisit implements Runnable{
private void doClick1(){
webbrowser.executeJavascript("document.getElementById('n').value='test'");
webbrowser.executeJavascript("document.getElementById('f').submit()");
}
public void run() {
globalFlag=false;
webbrowser.executeJavascript("document.getElementById(‘t’).click();") ;
while(!globalFlag){
Thread.sleep(500);
}
this.doClick1();
}
}
listener:
public class MyListener implements WebBrowserListener {
…
public void loadingProgressChanged(WebBrowserEvent e) {
if (e.getWebBrowser().getLoadingProgress() == 100) {
globalFlag=true;
}
}
}
DJ Native Swing enforces the Swing approach to threading: manipulate the components in the AWT Event Dispatch thread (a.k.a. UI thread). But also, do not block that thread, because listeners are triggered in that thread too.
So, you should not have a "while" loop in the UI thread, but should instead spawn a new thread. I hope your global variable is volatile, or AtomicBoolean or all accesses to it protected by synchronized block, otherwise you might have interesting threading side effects.
I am using a Thread in Spring mvc project to do some background working.
What I have done is
I write a class which extends Thread. and I added init() method to start this class.
Whole ThreadTest.java is Below.
package org.owls.thread.vo;
public class ThreadTest extends Thread {
public void init(){
this.start();
}
public void pause(){
this.interrupt();
}
#Override
public void run() {
for(int i = 0; i < 100; i++){
try{
Thread.sleep(3000);
System.out.println("Thread is running : " + i);
} catch(Exception e){e.printStackTrace();}
}
}
};
edit root-context.xml intent to start this Thread as soon as possible when the server started.
<bean id="threadTest" class="org.owls.thread.vo.ThreadTest" init-method="init"/>
Now is the problem. I want to make a toggle button(pause/resume) in my home.jsp and When I click the button it works. But I do not know how can I access to the Thread, which already registered and run.
please, show me the way~>0<
P.S
additional question about java Thread.
What method exactly means pause and resume. I thought stop is the one similar to pause, but it is deprecated.
And start() is somehow feels like 'new()' not resume.
Thanks
I figured out how to control a thread.
if I want to pause(not stop), code should be like below.
thread.suspend();
And want to resume this from where it paused, like below.
thread.resume();
even though those methods are both deprecated.
(if somebody knows some replacement of these, reply please)
If you do not want to yellow warning in your spring project,
you can remove warning by simply add an annotation on that method.
annotation is #SuppressWarnings("deprecated").
=========================================================
From here, additional solutions based on my experience.
To make automatic executing Spring mvc Thread,
I did following steps.
make a simple Class which extends Thread class.
inside that class, make a method. this will be calles by
config files. in this method. I wrote code like "this.start();".
Let Spring knows we have a Thread class that should run independently
with Web activities. To do this, we have to edit root-context.xml.
Add a bean like this.
<bean id="threadTest" class="org.owls.thread.vo.ThreadTest" init-method="init"/>
init is the method name which generated by user in step 2.
Now we run this project Automatically Thread runs.
Controlling Thread is not relavent with Spring, I guess.
It is basically belongs to java rules.
I hope this TIP(?) will be helpful to people who just entered world of programming :-)
I have read in many places that network connection in a j2me app should be done in a separate thread. Is this a necessity or a good to have?
I am asking this because I could not find anywhere written that this must be done in a separate thread. Also, when I wrote a simple app to fetch an image over a network and display it on screen (without using a thread) it did not work. When I changed the same to use a separate thread it worked. I am not sure whether it worked just because I changed it to a separate thread, as I had done many other changes to the code also.
Can someone please confirm?
Edit:
If running in a separate thread is not a necessity, can someone please tell me why the below simple piece of code does not work?
It comes to a stage where the emulator asks "Is it ok to connect to net". Irrespective of whether I press an "yes" or a "no" the screen does not change.
public class Moo extends MIDlet {
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
Display display = Display.getDisplay(this);
MyCanvas myCanvas = new MyCanvas();
display.setCurrent(myCanvas);
myCanvas.repaint();
}
class MyCanvas extends Canvas {
protected void paint(Graphics graphics) {
try {
Image bgImage = Image.createImage(getWidth(), getHeight());
HttpConnection httpConnection = (HttpConnection) Connector
.open("https://stackoverflow.com/content/img/so/logo.png");
Image image = Image.createImage(httpConnection
.openInputStream());
bgImage.getGraphics().drawImage(image, 0, 0, 0);
httpConnection.close();
graphics.drawImage(bgImage, 0, 0, 0);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Edit: I got my answer for the code here.
Edit: I spawned off a separate question of this here.
The problem is that you are trying to do work within the thread that is responsible for running the UI. If you do not use a separate thread, then that UI thread is waiting while you do your work and can't process any of your other UI updates! so yes you really should not do any significant work in event handlers since you need to return control quickly there.
I agree with Sean, but it is not required to have your network connection in a separate thread, just best practice. I think that it's probably coincidental that the connection worked properly after moving it to a separate thread. Either way though, if you want to provide any visual feedback to the user while the connection is happening (which you probably do considering the disparity of lag that users can experience on a mobile network), you should have the networked processing in a separate thread.
It is not mandatory that you do network connections in a new thread,however practically you'll find that it almost always a good idea to do so since network activities could block and leave your app in an unresponsive state.
This is an old article but it speaks about some of the issues involved in networking and user experience.