Java 当使用非水色外观时,隐藏在OS X上JOGL GLCANCAS后面的工具提示
在以下程序中(取决于JOGL),当工具提示“适合”在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
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外观时才会发生。我可以用光环和金属的外观来复制它,但不能用水绿色的外观
- 当使用常规的
时不会发生这种情况,只使用JOGLjava.awt.Canvas
(它是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)
编辑:我将此记录在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报告现在可以在