2017-08-20 5 views
0

Ich implementiere eine Java/Swing-Anwendung für MacOS, bei der es üblich ist, dass das meiste Maustastenverhalten deaktiviert ist, bis das Fenster aktiviert wird. Mit anderen Worten, wenn eine Maustaste über ein inaktives Fenster gedrückt wird, wird das Fenster aktiviert, aber nichts anderes passiert. (Es gibt Ausnahmen. Einige Schaltflächen beim Klicken aktivieren das Fenster und führen auch ihre normale Aktion aus.) Gibt es eine Möglichkeit, dies zu tun? Das grundlegende Problem ist, dass das Fenster bereits aktiv ist, wenn die Anwendung ein Mausklick-Ereignis erhält. Mein einziger Gedanke ist bisher, das Fenster-aktivierte Ereignis und das Maus-gedrückt-Ereignis nach Zeit zu korrelieren, was möglicherweise nicht vollständig zuverlässig ist.Wie kann ich Java/Swing-Steuerelemente implementieren, die deaktiviert sind, bis das Fenster aktiviert ist?

+0

Ich weiß nicht 100% genau, welches Verhalten Sie versuchen zu entlocken, aber vielleicht möchten Sie Ihrem JFrame eine Glasscheibe geben, sie undurchsichtig und sichtbar machen und alle Mausaktionen einfangen. Geben Sie ihm einen MouseListener. Wenn er gedrückt wird, ist die Glasscheibe nicht mehr sichtbar ('.setVisible (false)') und Mausaktionen können jetzt die JFrame GUI erreichen. –

+0

Das ist eine interessante Idee, wie man das Verhalten eines Mausereignisses unterdrückt, aber mein Problem ist, wie man feststellen kann, ob das Mausereignis durch dieselbe Geste erzeugt wurde, die den Rahmen aktiviert hat. Nur in diesem Fall möchte ich die Aktion unterdrücken. –

Antwort

1

Sie Schaltfläche machen kann, enthält() ist abhängig von der Frame, der gerade aktiv ist oder nicht:

final JFrame frame = new JFrame(); 

    JButton button = new JButton() { 
     @Override 
     public boolean contains(int x, int y) { 
      return super.contains(x, y) && frame.isActive(); 
     } 
    }; 

Wenn der Rahmen deactive ist und der Bereich der Schaltfläche geklickt erhalten, Taste wird das Maus-Ereignis nicht akzeptieren, da contains() gibt false zurück, buttons übergeordnetes get testet contains() stattdessen (und das übergeordnete Element von Eltern, bis eines wahr zurückgibt), es macht den Frame noch immer aktiv, nur die Schaltfläche wird keine Chance erhalten, auf den Mausklick zu antworten.

+0

............... clever –

+1

Wie ich in meiner Frage zu sagen versuchte, ist der Rahmen bereits aktiv, wenn ein Mausereignis generiert und ausgelöst wird. –

+0

Vielleicht hat Mac OSX ein anderes Verhalten, ich habe den Code in Linux getestet und es funktioniert, aber es ist nicht ungewöhnlich, dass die Ereignisbehandlung in OS sogar für Java-Programme inkonsistent ist :) –

0

Da die erste Antwort, die ich geschrieben nicht in Mac OSX nicht funktioniert, lassen Sie uns eine Lösung versuchen, mit AWTListener (die ich lieber nicht, da es verheerend sein kann, wenn sie nicht richtig gehandhabt):

frame.addWindowListener(new WindowAdapter() { 
     private final AWTEventListener awtEventListener = new AWTEventListener() { 
      @Override 
      public void eventDispatched(AWTEvent event) { 
       if (event instanceof MouseEvent && event.getID() == MouseEvent.MOUSE_PRESSED 
         && event.getSource() == button) { 
        ((MouseEvent) event).consume(); 
        frame.toFront(); 

        System.out.println("Special handled"); 
       } 
      } 
     }; 

     @Override 
     public void windowActivated(WindowEvent aE) { 
      SwingUtilities.invokeLater(new Runnable() { 
       @Override 
       public void run() { 
        Toolkit.getDefaultToolkit().removeAWTEventListener(awtEventListener); 
       } 
      }); 
     } 

     @Override 
     public void windowDeactivated(WindowEvent aE) { 
      Toolkit.getDefaultToolkit().addAWTEventListener(awtEventListener, MouseEvent.MOUSE_EVENT_MASK); 
     } 
    }); 

Die Idee Wenn Frame deaktiviert wird, fangen wir alle Mausereignisse ab, und wenn ein Mausereignisziel auf den Button gedrückt wird, wird es verbraucht und wir aktivieren den Frame künstlich mit toFront() (ich habe versucht ohne ToFront() den Frame auch natürlich zu aktivieren) Linux, aber es schadet nicht, wieder anzurufen).

Wenn der Rahmen aktiviert ist, verzögern wir die Entfernung von AWTEventListener mithilfe von invokeLater(), so dass die Schaltfläche nicht unmittelbar nach dem Entfernen des AWTEventListener angeklickt wird.

+0

Ich denke, das Problem hier ist, dass es andere Möglichkeiten gibt, den Frame zu reaktivieren, und in diesen Fällen sollte das Mausereignis normal verarbeitet werden. –

Verwandte Themen