1

As a follow-up to the question "JavaFX FileChooser in swing", which I have answered, I wonder if there's any possibility to simulate modal blocking call in Swing in a more elegant way. Here's the relevant code:

// a trick to emulate modality:
final JDialog modalBlocker = new JDialog();
modalBlocker.setModal(true);
modalBlocker.setUndecorated(true);
modalBlocker.setOpacity(0.0f);
final CountDownLatch modalityLatch = new CountDownLatch(1);
final FutureTask<T> task = new FutureTask<T>(() -> {
    // <-- some code checking whether the task is cancelled
    // and notifying that it is started
    try {
        return callable.call();
    } finally {
        // Wait until the Swing thread is blocked in setVisible():
        modalityLatch.await();
        // and unblock it:
        SwingUtilities.invokeLater(()
                -> modalBlocker.setVisible(false));
    }
});
// run the task in the JavaFX thread:
Platform.runLater(task);
// <-- some code waiting until the task is started,
// canceling it if it's not
// A trick to notify the task AFTER we have been blocked
// in setVisible():
SwingUtilities.invokeLater(() -> {
    // notify that we are ready to get the result:
    modalityLatch.countDown();
});
modalBlocker.setVisible(true); // blocks
modalBlocker.dispose(); // release resources
try {
    return task.get();
} catch (ExecutionException ex) {
    // exception handling
}

The idea here is to keep Swing updating, repainting, moving progress bars and doing other visual tasks while blocking the user input, until the blocking call returns. If I did a simple return task.get() without all this modality mess, then Swing would freeze while the task is working, which is not catastrophic, but still undesirable.

The whole thing seems to be working perfectly, at least under Windows 7, but "seems to be working perfectly" is not exactly in line with "Write once, run everywhere", is it?

I have tried to look in to JDialog/Dialog source code to figure out how modality blocks without totally freezing the GUI, but alas the code is very complicated, and worse, uses too many private features that would prevent me from doing it in my code even if I figured out how it's working.

The question is: maybe there's a more elegant way to do it that I have missed? I just need to perform a blocking call that keeps the GUI updating, but blocks all user input until the call returns.

Community
  • 1
  • 1
Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73
  • 2
    Take a look at [Foxtrot](http://foxtrot.sourceforge.net/) – MadProgrammer May 08 '15 at 06:38
  • 1
    Foxtrot together with [glass pane](https://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html) will provide the required functionality – Sergiy Medvynskyy May 08 '15 at 06:51
  • 1
    Personally, I prefer `JXLayer` (AKA `JLayer`) to provide a "blocking" layer, it allows you to do some fancy paint effects, for [example](http://stackoverflow.com/questions/19324918/how-to-disable-all-components-in-a-jpanel/19328368#19328368) and [example](https://stackoverflow.com/questions/19799451/java-blocking-focus-from-jcomponent/19801009#19801009) ... but that's me ;) – MadProgrammer May 08 '15 at 06:58
  • @MadProgrammer looks good, but it's one third paty lib more... I'm currently on customizing of application for new L&F, so I hate all Swing third party libs :). But JXLayer can be tolerated :) – Sergiy Medvynskyy May 08 '15 at 07:42
  • @MadProgrammer, Foxtrot looks nice, but it doesn't block user input. It's more like a synchronous SwingWorker, which is not exactly what I need. – Sergei Tachenov May 08 '15 at 14:39
  • @Sergiy, what does the glass pane have to do with this? Also, Foxtrot is third party too, isn't it? – Sergei Tachenov May 08 '15 at 14:40
  • @SergeyTachenov Glass pane can be used to block user input (mouse and key events) during the foxtrot task is executed. You also can use it to show a progress message to the user. – Sergiy Medvynskyy May 08 '15 at 15:37
  • @Sergiy, I see. After looking at some Glass Pane examples, I figured it's even more messy than what I currently have. It only works for a single JFrame, it seems to require some sort of Black Magic to block the keyboard input, and it doesn't give the right modality "feel" - for example, the JFrame can still have focus. – Sergei Tachenov May 08 '15 at 16:55

0 Answers0