Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid FlatLaf crashing the GUI #135

Merged
merged 12 commits into from
Nov 18, 2022
Merged

Avoid FlatLaf crashing the GUI #135

merged 12 commits into from
Nov 18, 2022

Conversation

ctrueden
Copy link
Member

  • Always queue ui.show/showUI calls on the EDT
  • Fix usage of private and now-removed PyImageJ API
  • Use existing imagej.gateway if already running
  • Add a hack to avoid FlatLaf in problem situations
  • Include imagej-legacy by default

This avoids threading issues which cause deadlocks on macOS.
In a future PyImageJ release, when running in GUI mode (and
*only* when running in GUI mode), the created ImageJ2 gateway will
be cached in the global variable imagej.gateway, so that it is
accessible from other threads, since the imagej.init function
never returns in that case. We can utilize this in napari-imagej
to hook into that ImageJ2 gateway, rather than creating a new one.

By doing this, napari-imagej becomes usable interactively while
PyImageJ is in GUI mode, which means it can now work with a GUI on
macOS! But you need to start napari + PyImageJ in a special way:

  import imagej, napari
  napari.Viewer()
  imagej.init(mode='gui')

As an aside: this construction does *not* work on non-macOS
platforms, because imagej.init(mode='gui') manually blocks the
thread with a polling sleep loop, which means that napari.run()
does not get invoked to start up napari's event loop, which
results in napari hanging. However, on Linux (and likely Windows)
you can instead do:

  import imagej, napari
  imagej.gateway = imagej.init(mode='interactive')
  imagej.gateway.ui().showUI()
  napari.Viewer()
  napari.run()

To utilize the pathway enabled by this commit.
Specifically, if the UI is swing rather than legacy, then FlatLaf
doesn't work with napari-imagej for some reason. We need to figure out
why, but for the moment, this HACK avoids the issue by switching to the
system default Look+Feel proactively before the Java UI can crash.

Unfortunately, it has the side effect of changing the user's preferred
Look+Feel preference globally for all their ImageJ2 instances, not just
within napari-imagej. So we'll eventually need something better.
And in any case, we should make FlatLaf work, since FlatLaf is great.
This avoids the issue with FlatLaf not working with the Swing UI.

But we'll need to figure out what to do about imagej/imagej-legacy#280.
@ctrueden ctrueden added this to the 0.1.0 milestone Nov 17, 2022
@ctrueden ctrueden added the bug Something isn't working label Nov 17, 2022
@ctrueden ctrueden requested a review from gselzer November 17, 2022 16:15
Copy link
Collaborator

@gselzer gselzer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks so much @ctrueden!

I had a couple ideas, please let me know what you think.

Also, looks like there are a couple of places where I'm still using old PyImageJ API, causing the tests to fail 😨 We should probably:

  • Update those to make the tests pass
  • Probably bump up the minimum pyimagej version, because those functions are new, right?

Comment on lines 19 to 22
# This can be used to include original ImageJ functionality.
# Iff true, original ImageJ functionality (ij.* packages) will be available.
# Defaults to false.
include_imagej_legacy: false
include_imagej_legacy: true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reasoning for this change?

Assuming we do this, we also need to change the documentation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote the reasoning into the commit message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"This avoids the issue with FlatLaf not working with the Swing UI."

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because whenever the FlatLaf avoidance hack is triggered, it changes the user's preferred Look+Feel globally to the system one, meaning the next time they run Fiji (outside napari-imagej), it won't be FlatLaf for them anymore. 😢

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't the point of the hack napari_imagej/java to get around that issue? Or am I missing something?

Copy link
Member Author

@ctrueden ctrueden Nov 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We made add_legacy=False the default before we added the GUI buttons, right? Now that we have the GUI buttons, bringing up the unfinished Swing UI by default strikes me as rather rude; people are very used to the legacy UI, and it is much better tested, and the FlatLaf bug doesn't happen with that UI.

I agree that there are challenges to solve if we change this, particularly imagej/imagej-legacy#280.

Copy link
Collaborator

@gselzer gselzer Nov 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that there are challenges to solve if we change this, particularly imagej/imagej-legacy#280.

I thought this was the main reason that we chose to use pure IJ2. See #58

The other reason that we chose to use pure IJ2 is that closing the legacy UI disables napari-imagej, as described in #93.

Tbh, I don't really like either option here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if we do decide to make legacy the default, we should rewrite the conda job testing legacy to test pure IJ2.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if you close the IJ2 UI on this branch, you terminate napari. So that stinks, and we have to get to the bottom of that...

Copy link
Collaborator

@gselzer gselzer Nov 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if you close the IJ2 UI on this branch, you terminate napari. So that stinks, and we have to get to the bottom of that...

Okay, this seems to be fixed with 008daec.

src/napari_imagej/java.py Outdated Show resolved Hide resolved
src/napari_imagej/java.py Outdated Show resolved Hide resolved
src/napari_imagej/java.py Outdated Show resolved Hide resolved
src/napari_imagej/java.py Outdated Show resolved Hide resolved
src/napari_imagej/widgets/menu.py Outdated Show resolved Hide resolved
src/napari_imagej/widgets/menu.py Outdated Show resolved Hide resolved
@ctrueden
Copy link
Member Author

@gselzer Do you have time to fix up this PR along the lines of your suggestions? I have a dozen other things I'm supposed to get done today.

@gselzer
Copy link
Collaborator

gselzer commented Nov 17, 2022

@gselzer Do you have time to fix up this PR along the lines of your suggestions? I have a dozen other things I'm supposed to get done today.

Yeah, I think I can fix it up.

We have to bump the minimum pyimagej version to use it
@codecov-commenter
Copy link

codecov-commenter commented Nov 17, 2022

Codecov Report

Base: 91.34% // Head: 89.89% // Decreases project coverage by -1.44% ⚠️

Coverage data is based on head (251977f) compared to base (9ce9650).
Patch coverage: 27.77% of modified lines in pull request are covered.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #135      +/-   ##
==========================================
- Coverage   91.34%   89.89%   -1.45%     
==========================================
  Files          41       41              
  Lines        3917     3949      +32     
==========================================
- Hits         3578     3550      -28     
- Misses        339      399      +60     
Impacted Files Coverage Δ
src/napari_imagej/java.py 81.88% <8.10%> (-5.92%) ⬇️
src/napari_imagej/widgets/menu.py 74.04% <54.54%> (-11.68%) ⬇️
src/napari_imagej/types/converters/images.py 100.00% <100.00%> (ø)
src/napari_imagej/types/converters/labels.py 100.00% <100.00%> (ø)
src/napari_imagej/utilities/_module_utils.py 87.50% <100.00%> (+0.04%) ⬆️
tests/widgets/test_menu.py 72.16% <0.00%> (-3.31%) ⬇️
src/napari_imagej/widgets/result_tree.py 89.62% <0.00%> (-1.89%) ⬇️
tests/widgets/test_result_runner.py 83.67% <0.00%> (+8.16%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

☔ View full report at Codecov.
📢 Do you have feedback about the report comment? Let us know in this issue.

@gselzer
Copy link
Collaborator

gselzer commented Nov 17, 2022

Looking at the CodeCov results:

  • We're losing a significant amount of coverage in napari_imagej/widgets/menu.py, but I'm alright with that since the code that lost coverage is now being run on a different thread thanks to ij().thread().queue().
  • We're also losing coverage in napari_imagej/java.py, since we are no longer running IJ2 by default. Thus the new HACK fixing L+F isn't getting tested. I'm okay with skipping the coverage here as long as we rewrite the legacy CI test to be a IJ2 UI test.
  • We're skipping a test in tests/widgets/test_menu.py, because it gets skipped on CI. The reason for skipping, NPE from Napari/ImageJ2 Data Transfer on CI with ImageJ Legacy #124, feels relevant to this PR @ctrueden

Steps to merge:

@gselzer gselzer merged commit 5498c0d into main Nov 18, 2022
@gselzer gselzer deleted the fix-gui branch November 18, 2022 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants