JFormDesigner / FlatLaf

FlatLaf - Swing Look and Feel (with Darcula/IntelliJ themes support)
https://www.formdev.com/flatlaf/
Apache License 2.0
3.35k stars 266 forks source link

JFileChooser occasionally slow to instantiate #849

Open charphi opened 4 months ago

charphi commented 4 months ago

JFileChooser is occasionally slow to instantiate. This problem is difficult to replicate since it seems to appear on Windows when shortcuts target unavailable network drives. There are also multiple layers of cache that interfere.

After some digging, I think that the source of the problem is the class javax.swing.filechooser.FileSystemView. Expecially:

My current solution is to call these methods in a background thread at startup in order to warmup Windows internal caches. See https://github.com/jdemetra/jdplus-main/blob/ddf9ce62f5f89bdd957cac10f03017e01db141f8/jdplus-main-desktop/jdplus-toolkit-desktop-plugin/src/main/java/jdplus/toolkit/desktop/plugin/util/Installer.java#L284

A better solution would be to handle each call to FileSystemView in FlatLaf asynchronously but that might be difficult to program. What do you think ?

charphi commented 3 months ago

Here is a screenshot to visualize the different components

Screenshot 2024-06-11 143323_2

DevCharly commented 3 months ago

Sounds actually like a Java issue, which should be fixed in Java for all L&Fs...

JFileChooser is occasionally slow to instantiate

What does "slow" mean? One second? Two seconds? Five seconds? Or more?

Could you measure the time that FileSystemView#getChooserComboBoxFiles() needs? (call System.currentTimeMillis() or System.nanoTime() before and after invoking the above method and calculate the difference)

My current solution is to call these methods in a background thread at startup in order to warmup Windows internal caches.

Does this mean that, without that warmup code, opening file chooser is slow when opened the first time and "normal" on subsequent openings?

A better solution would be to handle each call to FileSystemView in FlatLaf asynchronously but that might be difficult to program.

Unfortunately, that is not possible without rewriting the whole file chooser UI... FlatLaf file chooser is based on MetalFileChooserUI.

Files for chooser combo box are filled in MetalFileChooserUI.DirectoryComboBoxModel in private method addItem(): https://github.com/openjdk/jdk/blob/7e55ed3b106ed08956d2d38b7c99fb81704667c9/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java#L1031

Private method addItem() is also invoked from another private method: https://github.com/openjdk/jdk/blob/7e55ed3b106ed08956d2d38b7c99fb81704667c9/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java#L719

So even if we implement a subclass of MetalFileChooserUI.DirectoryComboBoxModel and re-implement addItem() functionality asynchronously, we still have the problem that the original addItem() method is invoked from elsewhere...

Re-implementing addItem() is also difficult (or impossible?) because it uses some Java internal classes/methods (e.g. FilePane.usesShellFolder() or ShellFolder.getNormalizedFile()).

charphi commented 3 months ago

What does "slow" mean? One second? Two seconds? Five seconds? Or more?

Unfortunately, I can't replicate the problem when I want to. It seems to be a combination of a slow network and broken links.

On one occasion it took 3 to 5 seconds to open the JFileChooser dialogue box each time I tried.

I've since upgraded to Windows 11. Now it only takes almost 1 second to open JFileChooser the first time and a few hundred milliseconds the second time. Obviously there are some caches at play somewhere ...

charphi commented 3 months ago

Unfortunately, that is not possible without rewriting the whole file chooser UI... FlatLaf file chooser is based on MetalFileChooserUI.

Indeed. The MetalFileChooserUI is a bit odd to override. What I've found so far:

charphi commented 3 months ago

Here is a proof-of-concept to play with : https://gist.github.com/charphi/cf386bcbf4cd562801c8dd5da95b8b6c