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

2024-06-28

类似的问题如果在 JFrame 之外,Java 中的工具提示会闪烁吗? https://stackoverflow.com/questions/4922182/tooltip-flicker-in-java-if-outside-jframe

不断更新的轻量级工具提示效果很好,但一旦它超出了窗口范围或变得重量级(通过禁用轻量级弹出窗口),它就会变得闪烁。

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

有人知道如何解决这个问题吗?或者目前还不可能?

示例在此代码中 -->

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

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;


public class JTooltipFlickerTest extends JFrame {


JPanel panel;

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

public JTooltipFlickerTest () {
    super ();
    //ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); 
    //ToolTipManager.sharedInstance().setReshowDelay(0); 

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

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

    SwingUtilities.invokeLater (
        new Runnable () {

            @Override
            public void run() {
                panel = new JPanel ();

                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);
            }
        }
    );
}
}

不知何故,javax.swing.RepaintManager类可以帮助解决工具提示重画问题。扩展的类RepaintManager下面的例子取自第 11 章,重绘管理器: http://www.java.net/external?url=http://www.curious-creature.org/2007/07/22/repaint-manager-demos-chapter-11/ http://www.java.net/external?url=http://www.curious-creature.org/2007/07/22/repaint-manager-demos-chapter-11/

修改为重画JTooltipFlickerTest的内容面板...

尝试注释掉installRepaintManager()调用构造函数,你会看到区别......

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);
        }
    }
}

edited

When installRepaintManager()禁用后,整个工具提示会在边缘边界的两侧闪烁(与OP原始代码中的效果相同)。

When installRepaintManager()启用后,工具提示区域的一部分不会在边缘边界内闪烁。相反,它的另一部分在边缘边界之外闪烁。但是,与之前相比,闪烁并没有那么严重installRepaintManager()被禁用。

我知道,这是一个微妙的差异,我想它没有什么值得期待的。至少,工具提示区域中的文字在以下情况下有点清晰:installRepaintManager()已启用。

即使双缓冲代码被禁用,installRepaintManager()按预期工作;也就是说,快速重新绘制重量级组件以减少闪烁。

//panel.setDoubleBuffered(true);
//panel.createToolTip().setDoubleBuffered(true);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐