Nous avons une application Java qui doit être mise au premier plan lorsqu'un mécanisme de télécontrôle active quelque chose dans l'application.
Pour obtenir cela, nous avons réalisé dans la méthode appelée de la classe qui représente le cadre de notre application (extension d'un JFrame
) après la mise en oeuvre:
setVisible(true);
toFront();
Sous Windows XP, cela fonctionne la première fois qu'il est appelé, et la deuxième fois, seul l'onglet de la barre des tâches clignote, le cadre n'apparaît plus au premier plan. Même chose pour Win2k. Sur Vista, cela semble bien fonctionner.
Avez-vous des idées?
Une solution possible est:
Java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
J'ai eu le même problème en apportant une JFrame
au premier plan sous Ubuntu (Java 1.6.0_10). Et le seul moyen de résoudre ce problème est de fournir un WindowListener
. Plus précisément, je devais configurer ma JFrame
pour qu'elle reste toujours au top lorsque toFront()
est invoquée et fournir le gestionnaire d'événements windowDeactivated
à setAlwaysOnTop(false)
.
Donc, voici le code qui pourrait être placé dans une base JFrame
, qui est utilisée pour dériver tous les cadres d’application.
@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);
}
Chaque fois que votre cadre doit être affiché ou mis au premier plan, appelez frame.setVisible(true)
.
Depuis que j'ai migré vers Ubuntu 9.04, il semble inutile de disposer d'une WindowListener
pour invoquer super.setAlwaysOnTop(false)
- comme on peut l'observer; ce code a été déplacé vers les méthodes toFront()
et setVisible()
.
Veuillez noter que la méthode setVisible()
doit toujours être invoquée sur EDT.
Windows a la possibilité d'empêcher Windows de voler le focus; à la place, l'icône de la barre des tâches clignote. Dans XP, il est activé par défaut (le seul endroit où j'ai constaté une modification utilise TweakUI, mais il existe un paramètre de registre quelque part). Sous Vista, ils peuvent avoir modifié la valeur par défaut et/ou l'exposer en tant que paramètre accessible à l'utilisateur avec l'interface utilisateur prête à l'emploi.
Empêcher les fenêtres de s’imposer et de se concentrer est une fonctionnalité depuis Windows 2K (et moi, je l’en suis reconnaissant).
Cela dit, j’utilise une petite application Java pour me rappeler d’enregistrer mes activités tout en travaillant et c’est elle-même la fenêtre active toutes les 30 minutes (configurable bien sûr). Il fonctionne toujours de manière cohérente sous Windows XP et ne fait jamais clignoter la fenêtre de la barre de titre. Il utilise le code suivant, appelé dans le thread d'interface utilisateur à la suite du déclenchement d'un événement timer:
if(getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();
(la première ligne restaure si minimisée ... en fait, elle le restaurera aussi si elle est maximisée, mais je ne l'ai jamais ainsi).
Bien que cette application soit généralement réduite au minimum, elle se trouve souvent derrière mon éditeur de texte. Et, comme je l'ai dit, cela fonctionne toujours.
J'ai une idée de ce que votre problème pourrait être - peut-être vous avez une condition de concurrence avec l'appel setVisible (). toFront () peut ne pas être valide à moins que la fenêtre ne soit réellement affichée à l'appel. J'ai déjà eu ce problème avec requestFocus (). Vous devrez peut-être placer l'appel toFront () dans un écouteur d'interface utilisateur sur un événement activé par une fenêtre.
2014-09-07: À un moment donné, le code ci-dessus a cessé de fonctionner, peut-être sous Java 6 ou 7. Après quelques recherches et expérimentations, j'ai dû mettre à jour le code pour surcharger la méthode toFront
de la fenêtre avec le code modifié de ce qui est ci-dessus):
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);
}
Depuis Java 8_20, ce code semble bien fonctionner.
Voici une méthode qui fonctionne vraiment (testé sur Windows Vista): D
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
La variable plein écran indique si vous souhaitez que l'application s'exécute en plein écran ou en fenêtre.
Cela ne fait pas clignoter la barre des tâches, mais amène la fenêtre de manière fiable.
Hj, toutes vos méthodes ne fonctionnent pas pour moi, dans Fedora KDE 14. J'ai un mauvais moyen de mettre une fenêtre à l’avant, en attendant que Oracle corrige ce problème.
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);
}
}
}
//...
}
Et cela fonctionne parfaitement dans mon Fedora KDE 14 :-)
Cette méthode simple a parfaitement fonctionné pour moi sous Windows 7:
private void BringToFront() {
Java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if(jFrame != null) {
jFrame.toFront();
jFrame.repaint();
}
}
});
}
J'ai testé vos réponses et seulement celle de Stefan Reich a fonctionné pour moi. Bien que je n'ai pas réussi à restaurer la fenêtre à son état précédent (maximisé/normal). J'ai trouvé cette mutation mieux:
view.setState(Java.awt.Frame.ICONIFIED);
view.setState(Java.awt.Frame.NORMAL);
C'est setState
au lieu de setExtendedState
.
Le moyen le plus simple que j'ai trouvé ne présente pas d'incohérence sur toutes les plateformes:
setVisible (false); setVisible (true);
Les règles régissant ce qui se passe lorsque vous utilisez .toFront () un JFrame sont les mêmes dans Windows et Linux:
-> si une fenêtre de l'application existante est actuellement la fenêtre active, celle-ci bascule vers la fenêtre demandée -> sinon, la fenêtre clignote simplement dans la barre des tâches
MAIS :
-> les nouvelles fenêtres obtiennent automatiquement le focus
Alors exploitons cela! Vous voulez apporter une fenêtre à l'avant, comment le faire? Bien :
Ou, en code 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);
}
});
Il existe de nombreux mises en garde dans le fichier javadoc pour la méthode toFront () qui peuvent être à l'origine du problème.
Mais je vais quand même deviner, quand "seul l'onglet de la barre des tâches clignote", l'application a-t-elle été réduite? Si c'est le cas, la ligne suivante du javadoc peut s'appliquer:
"Si cette fenêtre est visible, amène cette fenêtre au premier plan et peut en faire la fenêtre ciblée."
Pour éviter que la fenêtre ne perde le focus lorsqu'elle redevient visible après avoir été masquée, il suffit de:
setExtendedState(JFrame.NORMAL);
Ainsi:
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showWindow();
setExtendedState(JFrame.NORMAL);
}
});