Windows “Always On Top” com Java

85

Em Java, existe uma maneira de ter uma janela "Sempre no topo", independentemente se o usuário muda o foco para outro aplicativo? Eu pesquisei na web e todas as soluções tendem a algum tipo de interface JNI com ligações nativas. Na verdade, essa não pode ser a única maneira de fazer isso? .. ou é?

Laplie Anderson
fonte

Respostas:

159

Experimente este método da Windowclasse:

Window.setAlwaysOnTop (booleano)

Funciona da mesma forma que o padrão no Gerenciador de Tarefas do Windows: mude para outro aplicativo, mas ele sempre aparece no topo.

Isso foi adicionado em Java 1.5

Código de amostra:

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

A janela permanece no topo mesmo quando não está ativa

OscarRyz
fonte
3
você pensaria que uma simples pesquisa por "aplicativo java sempre no topo" teria essa resposta, mas não foi possível encontrá-la. Obrigado.
Laplie Anderson
46
Adivinha. Agora sim !! :) Isso traz você aqui! google.com/search?&q=java+application+always+on+top
OscarRyz
Isso é simples e incrível. Eu também estava procurando por algo assim, mas não sabia que eles implementaram isso no Java 1.5. Obrigado por publicar.
Kushal Paudyal
2
Infelizmente, isso não funciona para mim ao executar um aplicativo de tela inteira, como um videogame. Alguém sabe como forçá-lo a subir nessa situação?
Dream Lane
1
@Dream lane, provavelmente faria isso como uma nova pergunta
rogerdpack
11

De minha observação, descobri que o privilégio AlwaysOnTop é concedido ao processo mais recente que solicitou estar sempre no topo.

Portanto, se você tiver um aplicativo que setAlwaysOnTop(true)e posteriormente outro aplicativo use essa opção, o privilégio será concedido ao segundo aplicativo. Para contornar isso, configurei o setAlwaysOnTop(false)e novamente setAlwaysOnTop(true)sempre que uma janela aparecer no topo da janela atual.

Eu verifiquei com wordwebem windows. WordWeb é um dos aplicativos que usa a AlwaysOnTopopção doOS

Não tenho certeza se funciona corretamente com o cenário do seu jogo.

Aviso : não estou ciente dos efeitos colaterais.

Aqui está o exemplo 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 Cor de Rosa
fonte
Definir como falso e verdadeiro novamente quando outra janela aparece não parece uma solução viável por um motivo simples - e se o outro aplicativo fizer a mesma coisa?
Trejkaz
@Trejkaz Bem, esse é um ponto válido. Não estou mais em contato com o swing agora.
pinkpanther
Isso funciona perfeitamente para o meu caso de uso! Definir como falso primeiro foi a chave.
rococó de
0

não use setFullScreenWindow, apenas pegue o tamanho da tela e então setSize, e tudo ficará bem.

X.Zhang
fonte
É uma resposta ou comentário?
Failed Scientist
@FailedScientist um comentário glorificado
clankill3r