Skip to main content

LockableUI - children components still receiving mouse events

4 replies [Last post]
depryf
Offline
Joined: 2008-10-03
Points: 0

Hello,

I am trying to use the LockableUI to lock a panel containing many children. I noticed that while the panel is locked, the buttons don't answer to mouse events, but those events are only delayed and happen once the panel is unlocked.

I am sure I am doing something wrong since this can't be the expected behavior.

Here is a very simple program that reproduces what I explained: click the TEST button and you will see "TEST" in the console. Click the START button, that will lock the main panel; while it is locked, click TEST again. Nothing will happen but as soon as the main panel is unlocked, "TEST" will be printed in the console again.

Thank you!

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.ext.LockableUI;

public class LockableTest {

public static void main(String[] args) {

// the panel to lock with only a button in it; the button just prints "TEST"
JPanel toLock = new JPanel(new GridBagLayout());
JButton btn = new JButton("TEST");
toLock.add(btn);
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("TEST");
}
});

// the lockable UI wrapping the panel to lock
final LockableUI lockableUI = new LockableUI();
JXLayer lockablePnl = new JXLayer(toLock, lockableUI);

// and finally a button to trigger the test: lock the panel, do some demanding work and unlock the panel
JButton startBtn = new JButton("START");
startBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
lockableUI.setLocked(true);

// busy loop, represents some random work
long i = 0;
while (i < 3000000000L)
i++;

lockableUI.setLocked(false);
}

});

// now create the testing frame and show it
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(300, 300));
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(lockablePnl, BorderLayout.CENTER);
frame.getContentPane().add(startBtn, BorderLayout.SOUTH);

frame.pack();
frame.setVisible(true);
}
}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
alexfromsun
Offline
Joined: 2005-09-05
Points: 0

Hello Depryf

There are two problems in the LockableTest,
you create Swing components on the main thread,
when they must be created and used on the Event Dispatch Thread only

The fix is easy - wrap all your code in the main method
with SwingUtilites.invokeLater(Runnable)

http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html

The second problem, as correctly pointed by Piet
is blocking the Event Dispatch Thread

it is incorrect to do any time-consuming tasks on this thread,
because it blocks the processing of the input events
you should use SwingWorker in this case

http://java.sun.com/docs/books/tutorial/uiswing/concurrency/simple.html

alexp

depryf
Offline
Joined: 2008-10-03
Points: 0

Thank you very much for you answers, it makes perfect sense; I knew it had to be something wrong on my side!

depryf
Offline
Joined: 2008-10-03
Points: 0

My code was cut-off, here is the rest of the example.

// now create the testing frame and show it
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(300, 300));
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(lockablePnl, BorderLayout.CENTER);
frame.getContentPane().add(startBtn, BorderLayout.SOUTH);

frame.pack();
frame.setVisible(true);
}
}

pietblok
Offline
Joined: 2003-07-17
Points: 0

Hi,

Your problem is that you execute your long running task on the EDT. The press action on TEST can only be detected after the task has ended. Change your long running task as follows:

[code]
startBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
lockableUI.setLocked(true);
new Thread(new Runnable() {

@Override
public void run() {
// busy loop, represents some random work
long i = 0;
while (i < 3000000000L)
i++;
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
lockableUI.setLocked(false);
}
});
}
}).start();
}

});
[/code]

(Use code formatting tags for your code: [ CODE ] and [ / CODE ], but without the spaces)

Piet