Можно ли остановить мерцание всплывающей подсказки Java в супертяжелом режиме? - PullRequest
2 голосов
/ 31 марта 2011

Аналогично Q для Мерцание всплывающей подсказки в Java, если он находится за пределами 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);
            }
        }
    );
}
}

1 Ответ

0 голосов
/ 31 марта 2011

Каким-то образом класс javax.swing.RepaintManager может помочь с проблемой перерисовки всплывающей подсказки. Класс, который расширяет RepaintManager ниже, взят из примера в Глава 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);
        }
    }
}

изм

Когда installRepaintManager() отключено, вся всплывающая подсказка мигает с обеих сторон границы края (это тот же эффект, что и в исходном коде OP).

Когда включен installRepaintManager(), одна часть области всплывающей подсказки не мерцает внутри границы края. Напротив, другая его часть мерцает за пределами границы края. Но мерцание не так плохо по сравнению с тем, когда installRepaintManager() отключено.

Я знаю, это тонкое различие, которое, я думаю, не оставляет желать лучшего. По крайней мере, слова в области всплывающей подсказки немного разборчивы, когда включен installRepaintManager().

Даже когда коды с двойной буферизацией отключены, installRepaintManager() работает как положено; то есть тяжелый компонент быстро перекрашивается для уменьшения мерцания.

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