可以在重量级模式下停止闪烁的 Java 工具提示吗? [英] Possible to stop flickering java tooltip in heavyweight mode?

查看:22
本文介绍了可以在重量级模式下停止闪烁的 Java 工具提示吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

类似于 Java 中的工具提示在 JFrame 之外闪烁吗?

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

A constantly updating lightweight tooltip works fine, but once it moves out the window bounds or is made heavyweight (by disabling lightweight popups), it's flicker city.

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

Tried the "-Dsun.awt.noerasebackground=true" hint which works inside a window, but at the expense of some painting artefacts over other components (this example is just a blank panel). Outside a window bounds it doesn't help, there's still horrible amounts of flicker.

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

Anyone know how to solve this? Or is it not currently possible?

示例在此代码中 -->

Example is in this code -->

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 章,Repaint Manager 中的示例:http://www.java.net/external?url=http://www.curious-creature.org/2007/07/22/repaint-manager-demos-chapter-11/

Somehow, the javax.swing.RepaintManager class can help with the tool-tip repaint issue. The class that extends the RepaintManager below is taken from the example in Chapter 11, Repaint Manager: http://www.java.net/external?url=http://www.curious-creature.org/2007/07/22/repaint-manager-demos-chapter-11/

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

It is modified to repaint JTooltipFlickerTest's contentpane...

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

Try to comment out installRepaintManager() call in the constructor and you will see the difference...

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

已编辑

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

When installRepaintManager() is disabled, the whole tooltip flickers on both sides of the the edge boundary (it is the same effect as in OP's original code).

启用installRepaintManager() 时,工具提示区域的一部分不会在边缘边界内闪烁.相反,它的另一部分在边缘边界外闪烁.但是,与禁用 installRepaintManager() 时相比,闪烁并没有那么糟糕.

When installRepaintManager() is enabled, one part of the tooltip area doesn't flicker inside of the edge boundary. In contrast, the other part of it flickers outside of the edge boundary. But, the flicker is not so bad compared to when installRepaintManager() is disabled.

我知道,这是一个微妙的差异,我想它没有什么可取的.至少,在启用installRepaintManager() 时,工具提示区域中的文字是有点清晰的.

I know, it is a subtle difference which I guess it leaves nothing to be desired of. At least, the words in the tooltip area are a little bit legible when installRepaintManager() is enabled.

即使禁用双缓冲代码,installRepaintManager() 也能按预期工作;即对重量级组件进行快速重绘以减少闪烁.

Even when the double-buffered codes are disabled, installRepaintManager() works as expected; that is, the heavyweight component is rapidly repainted to reduce the flicker.

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

这篇关于可以在重量级模式下停止闪烁的 Java 工具提示吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆