Pergunta

Temos um aplicativo Java que precisa ser trazido para o primeiro plano quando um mecanismo de telecontrole ativa algo no aplicativo.

Para conseguir isso, percebemos no método chamado da classe que representa o quadro de nossa aplicação (extensão de um JFrame) Após a implementação:

setVisible(true);
toFront();

No Windows XP, isso funciona na primeira vez que é chamado, na segunda vez apenas a guia na barra de tarefas flashes, o quadro não chega mais à frente. O mesmo vale para Win2K. No Vista, parece funcionar bem.

Você tem alguma ideia?

Foi útil?

Solução

Uma solução possível é:

java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        myFrame.toFront();
        myFrame.repaint();
    }
});

Outras dicas

Eu tive o mesmo problema em trazer um JFrame para a frente no Ubuntu (Java 1.6.0_10). E a única maneira de resolver isso é fornecer um WindowListener. Especificamente, eu tive que definir meu JFrame para sempre ficar no topo sempre que toFront() é invocado e fornecer windowDeactivated manipulador de eventos para setAlwaysOnTop(false).


Então, aqui está o código que pode ser colocado em uma base JFrame, que é usado para derivar todos os quadros de aplicação.

@Override
public void setVisible(final boolean visible) {
  // make sure that frame is marked as not disposed if it is asked to be visible
  if (visible) {
      setDisposed(false);
  }
  // let's handle visibility...
  if (!visible || !isVisible()) { // have to check this condition simply because super.setVisible(true) invokes toFront if frame was already visible
      super.setVisible(visible);
  }
  // ...and bring frame to the front.. in a strange and weird way
  if (visible) {
      toFront();
  }
}

@Override
public void toFront() {
  super.setVisible(true);
  int state = super.getExtendedState();
  state &= ~JFrame.ICONIFIED;
  super.setExtendedState(state);
  super.setAlwaysOnTop(true);
  super.toFront();
  super.requestFocus();
  super.setAlwaysOnTop(false);
}

Sempre que seu quadro deve ser exibido ou trazido para a frente frame.setVisible(true).

Desde que me mudei para o Ubuntu 9.04, parece não haver necessidade de ter um WindowListener para invocar super.setAlwaysOnTop(false) - como pode ser observado; Este código foi movido para os métodos toFront() e setVisible().

Observe esse método setVisible() deve sempre ser chamado no EDT.

O Windows tem a instalação para impedir que o Windows roube foco; Em vez disso, pisca o ícone da barra de tarefas. No XP, está por padrão (o único lugar que eu vi mudando é usar o Tweakui, mas há um cenário de registro em algum lugar). No Vista, eles podem ter alterado o padrão e/ou expostos como uma configuração acessível ao usuário com a interface do usuário pronta para uso.

Impedir que as janelas se forçam à frente e assumir o foco é um recurso desde o Windows 2k (e eu, por um lado, sou grato por isso).

Dito isto, tenho um pequeno aplicativo Java que eu uso para me lembrar de gravar minhas atividades enquanto trabalha, e isso se torna a janela ativa a cada 30 minutos (configurável, é claro). Ele sempre funciona de forma consistente no Windows XP e nunca pisca a janela da barra de título. Ele usa o seguinte código, chamado no tópico da interface do usuário como resultado de um evento de evento do timer:

if(getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();

(A primeira linha restaura se minimizada ... na verdade, ela a restauraria se maximizasse também, mas eu nunca o tenho).

Embora eu normalmente tenha esse aplicativo minimizado, muitas vezes está simplesmente por trás do meu editor de texto. E, como eu disse, sempre funciona.

Eu tenho uma idéia sobre qual poderia ser o seu problema - talvez você tenha uma condição de corrida com a chamada setvisible (). Tofront () pode não ser válido, a menos que a janela seja realmente exibida quando é chamada; Eu tive esse problema com o requestFocus () antes. Pode ser necessário colocar a chamada Tofront () em um ouvinte da interface do usuário em um evento ativado pela janela.

2014-09-07: Em algum momento, o código acima parou de funcionar, talvez em Java 6 ou 7. Após alguma investigação e experimentação, tive que atualizar o código para substituir a janela toFront Método Faça isso (em conjunto com o código modificado do que está acima):

setVisible(true);
toFront();
requestFocus();
repaint();

...

public @Override void toFront() {
    int sta = super.getExtendedState() & ~JFrame.ICONIFIED & JFrame.NORMAL;

    super.setExtendedState(sta);
    super.setAlwaysOnTop(true);
    super.toFront();
    super.requestFocus();
    super.setAlwaysOnTop(false);
}

A partir de Java 8_20, esse código parece estar funcionando bem.

Aqui está um método que realmente funciona (testado no Windows Vista): D

   frame.setExtendedState(JFrame.ICONIFIED);
   frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);

A variável de tela cheia indica se você deseja que o aplicativo seja executado em tela cheia ou com janela.

Isso não exibe a barra de tarefas, mas traga a janela para a frente de maneira confiável.

HJ, todos os seus métodos não estão funcionando para mim, no Fedora KDE 14. Tenho uma maneira suja de fazer uma janela para a frente, enquanto estamos esperando o Oracle para corrigir esse problema.

import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;

public class FrameMain extends javax.swing.JFrame {

  //...
  private final javax.swing.JFrame mainFrame = this;

  private void toggleVisible() {
    setVisible(!isVisible());
    if (isVisible()) {
      toFront();
      requestFocus();
      setAlwaysOnTop(true);
      try {
        //remember the last location of mouse
        final Point oldMouseLocation = MouseInfo.getPointerInfo().getLocation();

        //simulate a mouse click on title bar of window
        Robot robot = new Robot();
        robot.mouseMove(mainFrame.getX() + 100, mainFrame.getY() + 5);
        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

        //move mouse to old location
        robot.mouseMove((int) oldMouseLocation.getX(), (int) oldMouseLocation.getY());
      } catch (Exception ex) {
        //just ignore exception, or you can handle it as you want
      } finally {
        setAlwaysOnTop(false);
      }
    }
  }

  //...

}

E isso funciona perfeitamente no meu Fedora KDE 14 :-)

Este método simples funcionou para mim perfeitamente no Windows 7:

    private void BringToFront() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if(jFrame != null) {
                    jFrame.toFront();
                    jFrame.repaint();
                }
            }
        });
    }

Eu testei suas respostas e apenas Stefan Reich's One trabalhou para mim. Embora eu não conseguisse restaurar a janela para o estado anterior (maximizado/normal). Achei melhor esta mutação:

view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);

Aquilo é setState ao invés de setExtendedState.

Maneira mais simples que descobri que não tem inconsistência entre as plataformas:

setvisible (false); setvisible (true);

As regras que regem o que acontece quando você .tofront () um jframe são as mesmas no Windows e no Linux:

-> Se uma janela do aplicativo existente é atualmente a janela focada, foco swaps para a janela solicitada -> se não, a janela apenas pisca na barra de tarefas

MAS :

-> New Windows obtém o foco automaticamente

Então, vamos explorar isso! Você quer trazer uma janela para a frente, como fazê -lo? Nós iremos :

  1. Crie uma janela vazia sem fins
  2. Mostre
  3. Espere que ele apareça na tela (Setvisible faz isso)
  4. Quando mostrado, solicite o foco para a janela que você realmente deseja trazer o foco para
  5. Esconda a janela vazia, destrua -a

Ou, no código Java:

// unminimize if necessary
this.setExtendedState(this.getExtendedState() & ~JFrame.ICONIFIED);

// don't blame me, blame my upbringing
// or better yet, blame java !
final JFrame newFrame = new JFrame();
newFrame.add(new JLabel("boembabies, is this in front ?"));

newFrame.pack();
newFrame.setVisible(true);
newFrame.toFront();

this.toFront();
this.requestFocus();

// I'm not 100% positive invokeLater is necessary, but it seems to be on
// WinXP. I'd be lying if I said I understand why
SwingUtilities.invokeLater(new Runnable() {
  @Override public void run() {
    newFrame.setVisible(false);
  }
});

Existem numerosos ressalvas No Javadoc para o método tofront () que pode estar causando seu problema.

Mas vou adivinhar de qualquer maneira, quando "apenas a guia na barra de tarefas flashes", o aplicativo foi minimizado? Nesse caso, a linha a seguir do Javadoc pode se aplicar:

"Se essa janela estiver visível, traz essa janela para a frente e pode torná -la a janela focada".

Para evitar a janela que perde o foco quando retorna ao visível depois de estar escondido tudo o que é necessário é:

setExtendedState(JFrame.NORMAL);

Igual a:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top