gpt4 book ai didi

java - 使用非 Aqua 外观时,OS X 上的工具提示隐藏在 JOGL GLCanvas 后面

转载 作者:行者123 更新时间:2023-11-30 07:24:25 25 4
gpt4 key购买 nike

在以下程序(取决于 JOGL)中,当工具提示“适合”在 内时,JLabel 的工具提示隐藏在重量级 GLCanvas 后面。 GLCanvas.

import java.awt.*;

import javax.swing.*;
import javax.swing.plaf.nimbus.NimbusLookAndFeel;

import com.jogamp.opengl.awt.GLCanvas;

public class HeavyWeightTooltipTest {

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false);
try {
UIManager.setLookAndFeel(NimbusLookAndFeel.class.getName());
} catch (Exception aE) {
aE.printStackTrace();
}
showUI();
}
});
}

private static void showUI(){
JFrame frame = new JFrame("TestFrame");

JLabel label = new JLabel("Label with tooltip");
label.setToolTipText("A very long tooltip to ensure it overlaps with the heavyweight component");
frame.add(label, BorderLayout.WEST);

GLCanvas glCanvas = new GLCanvas();
frame.add(glCanvas, BorderLayout.CENTER);

frame.setVisible(true);
frame.setSize(300,300);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}

观察

  • 只有在不使用 Aqua 外观和感觉时才会发生这种情况。我可以用 Nimbus 和 Metal 的外观和感觉来重现它,但不能用 Aqua 的外观和感觉来重现它。
  • 使用常规 java.awt.Canvas 时不会发生这种情况,仅使用 JOGL GLCanvas (它是 java.awt.Canvas 的扩展)时不会发生这种情况)
  • 当工具提示比 GLCanvas 宽时,工具提示会正确呈现。一旦工具提示适合 GLCanvas,问题就开始了(请参阅帖子末尾的屏幕截图)
  • 是否调用 ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false) 并不重要。问题总是可重现的
  • 它适用于 Linux 和 Windows
  • 如果相关的话,我使用的是 JOGL 版本 2.3.2 和 Java 版本 1.8.0_65

    java version "1.8.0_65"
    Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
    Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)

正确显示工具提示 Tooltip correctly shown隐藏在 GLCanvas 后面的工具提示 Tooltip hidden behind GLCanvas

编辑:我在 JOGL 的错误跟踪器中将其记录为 bug 1306 .

最佳答案

似乎强制 PopupFactory 使用重量级工具提示(而不是中等重量工具提示)可以解决该问题。这并不简单,需要您编写自己的 PopupFactory 或使用反射来调用 PopupFactory#setPopupType

由于我不太热衷于编写自己的 PopupFactory,因此我使用了反射:

final class HeavyWeightTooltipEnforcerMac {

private static final Object LOCK = new Object();
private static PropertyChangeListener sUIManagerListener;

private HeavyWeightTooltipEnforcerMac() {
}

/**
* <p>
* Tooltips which overlap with the GLCanvas
* will be painted behind the heavyweight component when the bounds of the tooltip are contained
* in the bounds of the application.
* </p>
*
* <p>
* In that case, {@code javax.swing.PopupFactory#MEDIUM_WEIGHT_POPUP} instances are used, and
* they suffer from this bug.
* Always using {@code javax.swing.PopupFactory#HEAVY_WEIGHT_POPUP} instances fixes the issue.
* </p>
*
* <p>
* Note that the bug is only present when not using the Aqua look-and-feel.
* Aqua uses its own {@code PopupFactory} which does not suffer from this.
* </p>
*
*/
static void install() {
synchronized (LOCK) {
if (sUIManagerListener == null && isMacOS()) {
installCustomPopupFactoryIfNeeded();
sUIManagerListener = new LookAndFeelChangeListener();
UIManager.addPropertyChangeListener(sUIManagerListener);
}
}
}

private static void installCustomPopupFactoryIfNeeded() {
if (!isAquaLookAndFeel()) {
PopupFactory.setSharedInstance(new AlwaysUseHeavyWeightPopupsFactory());
}
}

private static final class LookAndFeelChangeListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if ("lookAndFeel".equals(propertyName)) {
installCustomPopupFactoryIfNeeded();
}
}
}

private static class AlwaysUseHeavyWeightPopupsFactory extends PopupFactory {
private boolean couldEnforceHeavyWeightComponents = true;

@Override
public Popup getPopup(Component owner, Component contents, int x, int y) throws IllegalArgumentException {
enforceHeavyWeightComponents();
return super.getPopup(owner, contents, x, y);
}

private void enforceHeavyWeightComponents() {
if (!couldEnforceHeavyWeightComponents) {
return;
}
try {
Method setPopupTypeMethod = PopupFactory.class.getDeclaredMethod("setPopupType", int.class);
setPopupTypeMethod.setAccessible(true);
setPopupTypeMethod.invoke(this, 2);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException aE) {
//If it fails once, it will fail every time. Do not try again
//Consequence is that tooltips which overlap with a heavyweight component will be painted behind that component iso
//on top of it
couldEnforceHeavyWeightComponents = false;
}
}
}
}

类似的修复可以在 IntelliJ 社区版中找到:LafManagerImpl类在 fixPopupWeight 方法中设置自己的工厂,该方法强制执行重量级弹出窗口。

关于java - 使用非 Aqua 外观时,OS X 上的工具提示隐藏在 JOGL GLCanvas 后面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37001959/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com