可以在重量级模式下停止闪烁的java工具提示吗?

可以在重量级模式下停止闪烁的java工具提示吗?,java,tooltip,flicker,Java,Tooltip,Flicker,类似于 不断更新的轻量级工具提示工作正常,但一旦它移出窗口边界或变为重量级(通过禁用轻量级弹出窗口),它就是闪烁城市 尝试了“-Dsun.awt.noerasebackground=true”提示,该提示在窗口内工作,但代价是在其他组件上绘制一些人工制品(此示例只是一个空白面板)。在一扇窗户外,它没有帮助,仍然有可怕的闪烁量 有人知道怎么解决这个问题吗?还是目前还不可能 示例如下代码--> 不知何故,javax.swing.repaitmanager类可以帮助解决工具提示重绘问题。下面扩展重新绘

类似于

不断更新的轻量级工具提示工作正常,但一旦它移出窗口边界或变为重量级(通过禁用轻量级弹出窗口),它就是闪烁城市

尝试了“-Dsun.awt.noerasebackground=true”提示,该提示在窗口内工作,但代价是在其他组件上绘制一些人工制品(此示例只是一个空白面板)。在一扇窗户外,它没有帮助,仍然有可怕的闪烁量

有人知道怎么解决这个问题吗?还是目前还不可能

示例如下代码-->


不知何故,
javax.swing.repaitmanager
类可以帮助解决工具提示重绘问题。下面扩展
重新绘制管理器的类取自第11章“重新绘制管理器”中的示例:

它被修改为重新绘制
JTooltipFlickerTest
的内容窗格

尝试注释掉构造函数中的
installRepaitManager()
调用,您将看到不同之处

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;

public class JTooltipFlickerTest extends JFrame {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    JPanel panel;

    static public void main (final String[] args) {
        new JTooltipFlickerTest ();
    }


    public JTooltipFlickerTest () {
        super ();
        panel = new JPanel ();          

        setTitle (this.getClass().toString());
        setSize (1024, 768);

        this.getContentPane().setLayout (new BorderLayout());

        SwingUtilities.invokeLater (
                new Runnable () {

                    @Override
                    public void run() {

                        final MouseAdapter ma = new MouseAdapter () {

                            public void mouseMoved (final MouseEvent e) { 
                                panel.setToolTipText ("x: "+e.getX()+", y: "+e.getY());
                            }
                        };  
                        panel.addMouseMotionListener(ma);

                        panel.setDoubleBuffered(true);
                        panel.createToolTip().setDoubleBuffered(true);

                        JTooltipFlickerTest.this.getContentPane().add (panel, "Center");                
                        JTooltipFlickerTest.this.setVisible (true);
                    }
                }
        );

        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        installRepaintManager();

    }

    private void installRepaintManager() {
        ReflectionRepaintManager manager = new ReflectionRepaintManager();
        RepaintManager.setCurrentManager(manager);
    }

    private class ReflectionRepaintManager extends RepaintManager {
        public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {

            int lastDeltaX = c.getX();
            int lastDeltaY = c.getY();

            Container parent = c.getParent();
            while (parent instanceof JComponent) {
                if (!parent.isVisible()) {
                    return;
                }

                if (parent instanceof JTooltipFlickerTest) {
                    x += lastDeltaX;
                    y += lastDeltaY;

                    int gap = getContentPane().getHeight() - h - y;
                    h += 2 * gap + h;

                    lastDeltaX = lastDeltaY = 0;

                    c = (JComponent) parent;
                }

                lastDeltaX += parent.getX();
                lastDeltaY += parent.getY();

                parent = parent.getParent();
            }

            super.addDirtyRegion(c, x, y, w, h);
        }
    }
}
已编辑

禁用
installRepaitManager()
时,整个工具提示在边缘边界的两侧闪烁(其效果和OP的原始代码中的效果相同)

启用
installRepaitManager()
时,工具提示区域的一部分不会在边缘边界内闪烁。相反,它的另一部分在边缘边界外闪烁。但是,与禁用
installrepaitmanager()
时相比,闪烁情况并不严重

我知道,这是一个微妙的区别,我想它没有留下什么不想要的。至少,启用
installrepaitmanager()
时,工具提示区域中的文字有点清晰

即使禁用了双缓冲代码,
installrepaitmanager()
也能正常工作;也就是说,重量级组件将快速重新绘制以减少闪烁

//panel.setDoubleBuffered(true);
//panel.createToolTip().setDoubleBuffered(true);

嗯。。。我看不出有什么不同。我发现工具提示和弹出窗口并不是真正的双缓冲,即硬件双缓冲,而类的设置方式意味着不能通过子类化来改变etc@mgraham:启用
installRepaitManager()
时,与面板重叠的工具提示区域部分不会闪烁;另一部分闪烁。禁用
installRepaitManager()
时,整个工具提示将闪烁。这是一个微妙的差别,我想它没有留下任何不想要的东西。至少,当启用
installrepaitmanager()
时,工具提示区域中的文字有点清晰。是的,我现在可以看到了。我可以用一个未修饰的JFrame制作一个虚假的工具提示,其中包含一个JTooltip,我可以在屏幕上移动它,闪烁可以忽略不计,因此它似乎是工具提示所使用的重量级Opup类所特有的。。。对真正的双缓冲警告的怀疑。。。这对我来说更糟糕,因为我使用多行HTML工具提示,所以闪烁非常糟糕…+我想在工具提示中使用半透明的重量级窗口,这样即使在组件中也会出现闪烁。我会给你一个向上的投票或者其他任何尝试,但我不允许因为之前没有帖子…@mgraham:我已经测试了它的半透明重量级假工具提示。结果如何?它的行为仍然与我所描述的一模一样。但是,如果我希望它位于任何窗口的顶部,我就无法获得令人满意的结果。我会更新我的帖子,如果我有时间。。。别担心:我真的不在乎投票系统。重要的是我们可以学习和分享我们的知识;)@mgraham:对不起,这是另一种方式。它适用于
setAlwaysOnTop(true)
通过
PopupFactory
。但是,当
setOpaque(false)
//panel.setDoubleBuffered(true);
//panel.createToolTip().setDoubleBuffered(true);