> The StatusBar code contains the following in the initialisation code:
> statusTimer=new Timer();
Note that there are two standard timer implementations, java.util.Timer
and javax.swing.Timer. Whenever you use timers in Swing to update some
part of the GUI you almost always want the later one since it makes
callback from the event dispatcher thread.
If you really want to update a Swing component from the callback of a
java.util.TimerTask you must in general use something like
java.awt.EventQueue.invokeLater() to ensure Swing thread safety. See
javax.swing.Timer for documentation and links on all this.
Regards,

Signature
Filip Larsen
> Hi Im new to Swing (and a lot other Java things to be honest)....
<http://www.physci.org/codes/javafaq.jsp#cljh>
> s would be grateful for any assistance.
>
> Im writing an app that is MDI based Ive got an JFrame MDI into which I have
> a menu bar and menu items etc and a status bar (a JPanel attached to SOUTH)
ughh.. let the code do the talking..
<http://www.physci.org/codes/sscce.jsp>
..but having said that, you might *try*..
> mnuNewCase.addActionListener(new java.awt.event.ActionListener() {
> public void actionPerformed(java.awt.event.ActionEvent e) {
System.out.println("ActionEvvent " + e);
> Caseframe newCase=new Caseframe();
> desktopPane.add(newCase);
> }
> });
...
> private class MyStatusTask extends TimerTask {
> private SimpleDateFormat formatter; // Formats the date displayed
[quoted text clipped - 3 lines]
>
> public void run() {
System.out.println("Run..");
> currentDate = new Date();
> formatter = new SimpleDateFormat ("EEE MMM dd hh:mm:ss yyyy",
[quoted text clipped - 9 lines]
> }
> }
..
> any thoughts as to why the JInternalFrame jumps around ? Is it the timer
> getting in the way ?
'Getting in the way'? Why? How wide did you make it? [ ;-) ]

Signature
Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
Mr Bender's Wardrobe By ROBOTANY 500
Ed - 08 Aug 2005 22:30 GMT
Still cannot see whats going on , trying to debug timer related problems was
never my strongest attribute.
Have tried stepping though (just get lost in nested calls etc), Adding
system.out debug (does what I expect, but child windws also jumps around) ,
have gone back to basic MDI/child with javax timer but still cannot past
this problem. Its going to be something simple but at this point time what?
while I continue to read up on timers / swing thread safety etc can someone
look at a cut down version of my app that I knocked up in eclipse VE and
give some more comments. dont know if it matters but Im runnin JDK 1.5 ,
eclipse 3.1 on and XP machine (but get the same problems with jdl 1.4.2 ,
eclipse 3.0 on NT4)
cheers
code made up from 2 files MDI.java and ChildWindow.java
MDI.java
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.BorderLayout;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import javax.swing.JPanel;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class MDI extends JFrame implements ActionListener{
static final int ONE_SECOND=1000;
private JPanel jContentPane = null;
private JMenuBar jJMenuBar = null;
private JMenu fileMenu = null;
private JMenu launchMenu = null;
private JMenuItem exitMenuItem = null;
private JMenuItem childjMenuItem = null;
private JLabel lblTime = null;
private Timer statusTimer;
private JMenuItem getChildjMenuItem() {
if (childjMenuItem == null) {
childjMenuItem = new JMenuItem();
childjMenuItem.setText("launch Child");
childjMenuItem.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
System.out.println("ActionEvent " + e);
ChildWindow myChild=new ChildWindow();
getContentPane().add(myChild);
}
});
}
return childjMenuItem;
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.out.println("Running my MDI");
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
MDI myMDI = new MDI();
myMDI.setVisible(true);
}
public MDI() {
super();
initialize();
}
private void initialize() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setJMenuBar(getJJMenuBar());
this.setSize(400, 200);
this.setContentPane(getJContentPane());
this.setTitle("Application");
statusTimer=new Timer(ONE_SECOND * 3, this);
statusTimer.start();
}
private JPanel getJContentPane() {
if (jContentPane == null) {
lblTime = new JLabel();
lblTime.setText("Time");
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.add(lblTime, java.awt.BorderLayout.SOUTH);
}
return jContentPane;
}
private JMenuBar getJJMenuBar() {
if (jJMenuBar == null) {
jJMenuBar = new JMenuBar();
jJMenuBar.add(getFileMenu());
jJMenuBar.add(getEditMenu());
}
return jJMenuBar;
}
private JMenu getFileMenu() {
if (fileMenu == null) {
fileMenu = new JMenu();
fileMenu.setText("File");
fileMenu.add(getExitMenuItem());
}
return fileMenu;
}
private JMenu getEditMenu() {
if (launchMenu == null) {
launchMenu = new JMenu();
launchMenu.setText("Launch");
launchMenu.add(getChildjMenuItem());
}
return launchMenu;
}
private JMenuItem getExitMenuItem() {
if (exitMenuItem == null) {
exitMenuItem = new JMenuItem();
exitMenuItem.setText("Exit");
exitMenuItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
}
return exitMenuItem;
}
public void actionPerformed (ActionEvent e) {
System.out.println("actionPerformed for my clock:" + e);
Date currentDate = new Date();
final SimpleDateFormat formatter = new SimpleDateFormat ("EEE MMM dd
hh:mm:ss yyyy", Locale.getDefault());
formatter.applyPattern("HH:mm:ss");
String now = formatter.format(currentDate);
lblTime.setText(now);
}
}
Childwindow.java
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JInternalFrame;
import javax.swing.JButton;
public class ChildWindow extends JInternalFrame {
private JPanel jContentPane = null;
private JButton btnClose = null;
public ChildWindow() {
super();
initialize();
}
private void initialize() {
this.setSize(300, 100);
this.setResizable(true);
this.setMaximizable(true);
this.setTitle("Drag me around");
this.setVisible(true);
this.setContentPane(getJContentPane());
}
private JPanel getJContentPane() {
if (jContentPane == null) {
jContentPane = new JPanel();
jContentPane.setLayout(new BorderLayout());
jContentPane.add(getBtnClose(), java.awt.BorderLayout.CENTER);
}
return jContentPane;
}
private JButton getBtnClose() {
if (btnClose == null) {
btnClose = new JButton();
btnClose.setText("Close Me");
btnClose.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
dispose();
}
});
}
return btnClose;
}
}
==============================================================
>> Hi Im new to Swing (and a lot other Java things to be honest)....
>
[quoted text clipped - 52 lines]
>
> 'Getting in the way'? Why? How wide did you make it? [ ;-) ]
Filip Larsen - 13 Aug 2005 22:34 GMT
> Still cannot see whats going on , trying to debug timer related problems was
> never my strongest attribute.
I haven't tried to compile or run your code, but it looks like you add
the JInternalFrame instances to the content pane of the top JFrame,
which in your case is a JPanel and not a JDesktopPane. You probably want
to add a JDesktopPane as the center component on the panel, and then add
the JInternalFrame instances to that JDesktopPane instead.
After your initial post I got curious and made a small test example, but
I could not reproduce the problem you say you have (neither using
javax.swing.Timer or java.util.Timer calling from outside the EDT which
I at the time thought may cause the effect you observe). If your problem
persists perhaps you can use the example code below as a starting point
to figure out where you go wrong.
===== TimerDragTest.java =====
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TimerDragTest extends JFrame implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TimerDragTest());
}
private int windows = 0;
public TimerDragTest() {
setTitle("Timer Drag Test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container content = getContentPane();
final JDesktopPane dt = new JDesktopPane();
content.add(dt,BorderLayout.CENTER);
JPanel sb = new JPanel();
content.add(sb,BorderLayout.SOUTH);
JMenuBar mb = new JMenuBar();
content.add(mb,BorderLayout.NORTH);
JMenu fileMenu = new JMenu("File");
mb.add(fileMenu);
JMenuItem newWindowItem = new JMenuItem("New Window");
fileMenu.add(newWindowItem);
newWindowItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JInternalFrame frame = new JInternalFrame("Window " +
(++windows),true,true,true,true);
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.getContentPane().add(new JLabel(new Date().toString()));
frame.pack();
dt.add(frame);
frame.setVisible(true);
}
});
final JLabel date = new JLabel();
sb.add(date);
final Format dateFormat = new SimpleDateFormat("EEE MMM dd hh:mm:ss
yyyy");
new javax.swing.Timer(1000,new ActionListener() {
public void actionPerformed(ActionEvent e) {
date.setText(dateFormat.format(new Date()));
}
}).start();
// java.util.Timer tt = new java.util.Timer();
// tt.schedule(new TimerTask() {
// public void run() {
// date.setText(dateFormat.format(new Date()));
// }
// }, 0, 1000);
}
public void run() {
setSize(300,300);
setVisible(true);
}
}
=====
Regards,

Signature
Filip Larsen
Babu Kalakrishnan - 14 Aug 2005 06:19 GMT
> Still cannot see whats going on , trying to debug timer related problems was
> never my strongest attribute.
As Filip pointed out, your problem lies in the fact that you've added
the JInternalFrame to a plain JPanel instead of a JDesktopPane which is
the recommended practice. The JDesktopPane knows how to handle multiple
child internal frames that can be positioned arbitrarily in it, but a
JPanel doesn't.
Since you use a BorderLayout as the LayoutManager of the panel and add
the JInternalFrame without specifying a constraint, it ends up becoming
the CENTER component of that Layout. So everytime the panel does a
layout, it expands the child component to its own width (and height
equal to its own height minus that of the label placed as its SOUTH
component).
You see the "jumping" only when the timer fires because the timer
changes the text on the label causing a revalidation to occur. The
LayoutManager kicks in then, and forces the child frame to become a
proper "CENTER" component regardless of where you'd dragged it to.
Using a JDesktopPane whould solve your problem. Check out :
http://java.sun.com/docs/books/tutorial/uiswing/components/internalframe.html
BK
Ed - 24 Aug 2005 21:26 GMT
Thanks in advance to Filip and Babu
Havent tried what you said yet as Ive only just returned from Holiday
(Turkey - can recommend) but will do so in the next few days. Sounds like I
ned to be careful of GUI editors like the VE one in eclipse as the Im sure
it was VE that autogenerated the JPanel rather than a JDesktopPane. Oh well
will see whats what this weekend.
Thanks again
Ed
>> Still cannot see whats going on , trying to debug timer related problems
>> was never my strongest attribute.
[quoted text clipped - 21 lines]
>
> BK
Ed - 27 Aug 2005 00:12 GMT
Got it , instead of putting a JDesktopPane in the centre of the default
contentPane (getContentPane) I was creating my own pane and setting it using
setContentPane() and also giving it a Border Layout. still sounds like it
should have worked (to me anyway) but the combination seems to mess things
up.
Thanks to Filip for the sample code which helped a lot, now off for some
sleep before I re-read up on internal panes etc to understand things better
for the next times.
thanks again
Ed
> Thanks in advance to Filip and Babu
>
[quoted text clipped - 32 lines]
>>
>> BK
> which appears to open the window as expected. However whenever I grab the
> window by its title bar and drag it around the MDI space (using left mouse
[quoted text clipped - 6 lines]
> Ive coded on which I have a timer updating the clock on the the bottom right
> of the status bar.
Without debugging anything I would guess that you update (which should
be done on the AWT Event Dispatch Thread, btw) is causing an invalidate.
That is causing, probably, the DesktopManager to put the internal frame
back to the original position. When the cursor moves again
BasicInternalFrameUI.BorderListener continues to drag.
Get your debugger out and have a look.
Tom Hawtin

Signature
Unemployed English Java programmer
http://jroller.com/page/tackline/