Windows "Always on Top" con Java

85

En Java, ¿hay alguna manera de tener una ventana que esté "Siempre visible" sin importar si el usuario cambia el foco a otra aplicación? He buscado en la web y todas las soluciones se basan en algún tipo de interfaz JNI con enlaces nativos. ¿Verdaderamente esta no puede ser la única manera de hacerlo? ... ¿o no?

Laplie Anderson
fuente

Respuestas:

159

Prueba este método de la Windowclase:

Window.setAlwaysOnTop (booleano)

Funciona de la misma manera que la predeterminada en el Administrador de tareas de Windows: cambie a otra aplicación, pero se muestra siempre en la parte superior.

Esto se agregó en Java 1.5

Código de muestra:

import javax.swing.JFrame;
import javax.swing.JLabel;

public class Annoying {
    public static void main(String[] args) {
        JFrame frame = new JFrame("Hello!!");

        // Set's the window to be "always on top"
        frame.setAlwaysOnTop( true );

        frame.setLocationByPlatform( true );
        frame.add( new JLabel("  Isn't this annoying?") );
        frame.pack();
        frame.setVisible( true );
    }
}

texto alternativo

La ventana permanece en la parte superior incluso cuando no está activa

OscarRyz
fuente
3
usted pensaría que una simple búsqueda de "aplicación java siempre en la parte superior" tendría esta respuesta, pero no pudo encontrarla. Gracias.
Laplie Anderson
46
Adivina qué. ¡¡Ahora sí !! :) ¡Te trae aquí! google.com/search?&q=java+application+always+on+top
OscarRyz
Esto es simple y asombroso. También estaba buscando algo como esto, pero no sabía que lo implementaron en Java 1.5. Gracias por publicar.
Kushal Paudyal
2
Desafortunadamente, esto no me funciona cuando ejecuto una aplicación de pantalla completa, como un videojuego. ¿Alguien conoce una forma de forzarlo a la cima en esa situación?
Dream Lane
1
@Dream Lane Probablemente haría eso como una nueva pregunta
rogerdpack
11

De mi observación, descubrí que el privilegio AlwaysOnTop se otorga al último proceso que solicitó estar siempre en la parte superior.

Entonces, si tiene una aplicación que setAlwaysOnTop(true)y luego otra aplicación usa esta opción, el privilegio se otorga a la segunda aplicación. Para solucionar este problema, configuré setAlwaysOnTop(false)y de nuevo setAlwaysOnTop(true)cada vez que aparezca una ventana en la parte superior de la ventana actual.

He comprobado con wordweben windows. WordWeb es una de las aplicaciones que utiliza la AlwaysOnTopopción delOS

No estoy seguro de si funciona correctamente con tu escenario de juego.

Advertencia : no estoy al tanto de los efectos secundarios.

Aquí está el ejemplo de código:

import java.awt.event.*;

import javax.swing.*;

public class MainWindow extends JFrame implements WindowFocusListener
{
    public MainWindow()
    {
        addWindowFocusListener(this);
        setAlwaysOnTop(true);
        this.setFocusable(true);
       // this.setFocusableWindowState(true);
        panel = new JPanel();
        //setSize(WIDTH,HEIGHT);
        setUndecorated(true);
        setLocation(X,Y);
        setExtendedState(MAXIMIZED_BOTH);
        setVisible(true);
    }

    public void windowGainedFocus(WindowEvent e){}
    public void windowLostFocus(WindowEvent e)
    {
        if(e.getNewState()!=e.WINDOW_CLOSED){
            //toFront();
            //requestFocus();
            setAlwaysOnTop(false);
            setAlwaysOnTop(true);
            //requestFocusInWindow();
            System.out.println("focus lost");
        }

    }

    private JPanel panel;
    private static final int WIDTH = 200;
    private static final int HEIGHT = 200;
    private static final int X = 100;
    private static final int Y = 100;

    public static void main(String args[]){
              new MainWindow();}
    }
Pantera Rosa
fuente
Establecerlo en falso y verdadero de nuevo cuando aparece otra ventana en la parte superior no parece una solución viable por una simple razón: ¿y si la otra aplicación hace lo mismo?
Trejkaz
@Trejkaz Bueno, ese es un punto válido. Ya no estoy en contacto con el swing ahora.
pinkpanther
¡Esto funciona perfectamente para mi caso de uso! Volver a establecerlo en falso primero fue clave.
rococó
0

no use setFullScreenWindow, solo obtenga el tamaño de la pantalla y luego setSize, y todo estará bien.

X.Zhang
fuente
¿Es una respuesta o un comentario?
Científico fallido
@FailedScientist un comentario glorificado
clankill3r