# Halb-modales Fenster erzeugen



## jf (12. Mrz 2012)

Ich möchte ein Fenster erzeugen, in welchem der Nutzer Eingaben machen kann und mit einem Klick auf OK sollen die Eingaben an die aufrufende Routine zurückgegeben werden:

String input = MeineFensterKlasse#getInstance.getInput();

Jetzt wäre aber mein Ziel, dass sich das Fenster wie ein nicht-modales Fenster verhält: man sollte in das Eltern-Fenster klicken könne, wobei das Kind-Fenster den Fokus verliert aber immer noch vor dem Eltern-Fenster angezeigt wird.
=> Das Fenster soll also die Ausführung des Codes der aufrufenden Routine blockieren, sich selber aber modeless verhalten.

In anderen Sprachen könnte man dies sehr hässlich über eine Warte-Schleife lösen - bei Java blockiert solch eine Schleife allerdings das UI.
Gibt es evtl. eine Technik, mit welcher ich mein Ziel dennoch erreichen könnte?


----------



## vanny (12. Mrz 2012)

jf hat gesagt.:


> Ich möchte ein Fenster erzeugen...



Dann tu das xD.
Hier kannst du nen neuen JFrame nutzen oder einen JDialog.



jf hat gesagt.:


> ... wobei das Kind-Fenster den Fokus verliert aber immer noch vor dem Eltern-Fenster angezeigt wird.


JFrame.setAllwaysOnTop(true); könnte helfen.

Aus designtechnischer Sicht ist dein Vorhaben aber äußerst fragwürdig, was willst du denn mit diesem
 Verhalten bezwecken?

Gruß Vanny


----------



## jf (13. Mrz 2012)

vanny hat gesagt.:


> Dann tu das xD.
> Hier kannst du nen neuen JFrame nutzen oder einen JDialog.


Ok.



vanny hat gesagt.:


> JFrame.setAllwaysOnTop(true); könnte helfen.


Nein, ich möchte kein TopMost-Window, sondern nur eins, welches immer vor seinem Owner angezeigt wird. (also einfach das Hauptfenster als Owner verwenden - egal ob modal oder modeless)



vanny hat gesagt.:


> Aus designtechnischer Sicht ist dein Vorhaben aber äußerst fragwürdig, was willst du denn mit diesem Verhalten bezwecken?


Was verstehtst du unter _designtechnisch_? - Klar ist es einfacher für den Programmierer, wenn die ganze Anwendung für den Nutzer erst einmal blockiert wird. Aber für den Nutzer ist es ein echtes Ärgernis: er macht Eingaben anhand des Fensterinhaltes im Hintergrund, merkt dann aber, dass er im Hauptfenster noch etwas nach unten Rollen müsste, um weitere Informationen zu erhalten. Er muss nun seine Eingaben kopieren, das Eingabefenster schließen, rolllen, das Eingabefenster erneut öffnen und die alten Eingaben erneut einfügen. => recht umständlich, findest du nicht auch?

Ideal wäre es eben, wenn man im ActionListener einfach InputWindow.getInput() aufrufen könnte, und dieses Fenster solange blockiert bis der Nutzer seine Eingaben getätigt hat - ein modales Verhalten eben.

Nur möchte ich das Fenster vom Verhalten dem Nutzer gegenüber modeless gestalten. - Ein sehr primitives Anliegen eigentlich... nur bin ich mir nicht sicher, ob ich da gegen das Fenster-Konzept unter Windows arbeite.


----------



## Ebenius (13. Mrz 2012)

So in der Art? 
	
	
	
	





```
/* (@)NonBlockingInputDialogFun.java */

/* Copyright 2012 Sebastian Haufe

 * Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       [url]http://www.apache.org/licenses/LICENSE-2.0[/url]

 * Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License. */

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.*;

/**
 * Provides a master frame and a non-modal input frame.
 * 
 * @author Sebastian Haufe
 */
public class NonBlockingInputDialogFun {

  static void getInput(final JButton button, final JTextArea area) {
    final JDialog inputDialog =
          new JDialog(SwingUtilities.getWindowAncestor(area));
    final JTextField tf = new JTextField(25);
    final JButton okButton = new JButton(new AbstractAction("OK") {

      private static final long serialVersionUID = 1L;

      public void actionPerformed(ActionEvent e) {
        area.setText(area.getText() + "User Input: " + tf.getText() + "\n");
        inputDialog.dispose();
      }
    });
    inputDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    inputDialog.getContentPane().add(tf, BorderLayout.CENTER);
    inputDialog.getContentPane().add(okButton, BorderLayout.SOUTH);
    inputDialog.addWindowListener(new WindowAdapter() {

      @Override
      public void windowClosed(WindowEvent e) {
        button.setEnabled(true);
      }
    });
    inputDialog.pack();
    inputDialog.setLocationByPlatform(true);
    inputDialog.setVisible(true);
  }

  /** Creates the GUI. Call on EDT, only! */
  static void createAndShowGui() {
    final JTextArea area = new JTextArea();
    area.setEditable(false);
    area.setColumns(80);
    area.setRows(25);
    final JButton inputButton =
          new JButton(new AbstractAction("Get Input\u2026") {

            private static final long serialVersionUID = 1L;

            public void actionPerformed(ActionEvent e) {
              final JButton button = (JButton) e.getSource();
              button.setEnabled(false);
              getInput(button, area);
            }
          });

    final JPanel contentPane = new JPanel(new BorderLayout(6, 6));
    contentPane.add(area, BorderLayout.CENTER);
    contentPane.add(inputButton, BorderLayout.SOUTH);

    final JFrame f = new JFrame("Test Frame: NonBlockingInputDialogFun");
    f.setContentPane(contentPane);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }

  /** @param args ignored */
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {

      public void run() {
        createAndShowGui();
      }
    });
  }
}
```
Ebenius


----------



## bERt0r (13. Mrz 2012)

Man kann auch ganz einfach einen WindowClosing-Listener and den Dialog hängen:

```
JDialog modalerDialog=new JDialog(frame,false);
modalerDialog.addWindowListener(new WindowAdapter()
{
	@Override
	public void windowClosing(WindowEvent e)
	{
		System.out.println("Done");
	}
});
```


----------



## jf (21. Mrz 2012)

Vielen Dank für eure Vorschläge. Ich habe es nun so wie bERt0r es vorgeschlagen hat gemacht.
Dabei enteht aber ein Aktualisierungsproblem, während der Vorgang läuft, welcher mit dem Closing-Event ausgelöst wird. Ich habe dazu schon ein neues Thema eröffnet und wollte hiermit nur noch die Verbindung herstellen.


----------

