Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当使用非水色外观时,隐藏在OS X上JOGL GLCANCAS后面的工具提示_Java_Macos_Swing_Tooltip_Jogl - Fatal编程技术网

Java 当使用非水色外观时,隐藏在OS X上JOGL GLCANCAS后面的工具提示

Java 当使用非水色外观时,隐藏在OS X上JOGL GLCANCAS后面的工具提示,java,macos,swing,tooltip,jogl,Java,Macos,Swing,Tooltip,Jogl,在以下程序中(取决于JOGL),当工具提示“适合”在GLCanvas中时,JLabel的工具提示隐藏在重量级GLCanvas后面 import java.awt.*; import javax.swing.*; import javax.swing.plaf.nimbus.NimbusLookAndFeel; import com.jogamp.opengl.awt.GLCanvas; public class HeavyWeightTooltipTest { public stat

在以下程序中(取决于JOGL),当工具提示“适合”在
GLCanvas
中时,
JLabel
的工具提示隐藏在重量级
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外观时才会发生。我可以用光环和金属的外观来复制它,但不能用水绿色的外观
  • 当使用常规的
    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)
    
工具提示正确显示 隐藏在GLCanvas后面的工具提示


编辑:我将此记录在JOGL as的bug跟踪器中。

似乎强制
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;
      }
    }
  }
}
最后一类重量级选手ToolTipenforformac{
私有静态最终对象锁=新对象();
私有静态属性ChangeListener sUIManagerListener;
私人重量级拳手OLTIPENFORCEMAC(){
}
/**
*
*与画布重叠的工具提示
*当包含工具提示的边界时,将在重量级组件后面绘制
*在应用程序的范围内。
*

* * *在这种情况下,将使用{@code javax.swing.PopupFactory#MEDIUM_WEIGHT_POPUP}实例,并且 *他们受这种虫子的折磨。 *始终使用{@code javax.swing.PopupFactory#HEAVY _WEIGHT _POPUP}实例可以解决这个问题。 *

* * *请注意,该错误仅在不使用Aqua外观时出现。 *Aqua使用自己的{@code PopupFactory},它不会受到这种影响。 *

* */ 静态void安装(){ 已同步(锁定){ if(sUIManagerListener==null&&isMacOS()){ InstallCustomPopupFactoryyFneed(); sUIManagerListener=newlookandfeelchangellistener(); UIManager.addPropertyChangeListener(sUIManagerListener); } } } 私有静态void installCustomPopupFactoryyFneedd(){ 如果(!isAquaLookAndFeel()){ setShareInstance(新的AlwaysUsehavyWeightPopupFactory()); } } 私有静态最终类LookAndFeelChangeListener实现PropertyChangeListener{ @凌驾 公共作废属性更改(属性更改事件evt){ 字符串propertyName=evt.getPropertyName(); if(“lookAndFeel”.equals(propertyName)){ InstallCustomPopupFactoryyFneed(); } } } 私有静态类始终使用HeavyWeightPopupFactory扩展PopupFactory{ 私有布尔值couldenforceHeavweightComponents=true; @凌驾 公共弹出窗口getPopup(组件所有者、组件内容、int x、int y)抛出IllegalArgumentException{ 强制执行重量级组件(); 返回super.getPopup(所有者、内容、x、y); } private void强制执行重量级组件(){ 如果(!couldenforceweightComponents){ 返回; } 试一试{ 方法setPopupTypeMethod=PopupFactory.class.getDeclaredMethod(“setPopupType”,int.class); setPopupTypeMethod.setAccessible(true); 调用(这个,2); }捕获(NoSuchMethodException | IllegalacessException | InvocationTargetException aE){ //如果失败一次,每次都会失败。不要再试一次 //结果是,与重量级组件重叠的工具提示将绘制在该组件的后面 //最重要的是 couldenforceHeavweightComponents=false; } } } }

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

您在中尝试过这些技巧吗?啊。。我只是注意到他们说这是“自动的”。在你的机器上试用他们的一些代码,看看是否有效。@AndrewThompson从那篇文章中我主要得出结论,它应该只适用于现代JDK。那篇文章中提到的一些bug已经被修复了,而其他的技巧是不相关的(比如滚动窗格或者非矩形组件)。这是一个JOGL bug,请填写bug报告。使用OS X维护AWT重量级GLCanvas是件痛苦的事情:s@gouessej有趣的是,我也碰到了这个bug。昨天附加的评论/截图/片段是我的。斯文开始修复另一个bug,你应该试试他的补丁。有趣的是,你能在维基上写一个关于它的页面吗?你有没有按照建议填写过bug报告?据我所知,StackOverflow不是一个bug追踪器。谢谢你分享你的发现。@gouessej它确实不是一个bug追踪器,但是这里的人可能知道一个解决方法。如果Sven真的恢复修复问题,我会提交一些bug报告(就像我碰到其他一些一样)@gouessej bug报告现在可以在