# Minimieren und Maximieren eines JFrames verhindern



## Tobias (1. Apr 2008)

Hallo,

ich habe einen Dialog, der eigentlich modal sein soll, es aufgrund von GUI-Leitlinien aber nicht sein kann (der Dialog braucht eine Popup-Animation, welche bei setModal(true) nicht zu sehen wäre, weil setVisible() den Thread blockiert). Also bin ich gerade dabei, modales Verhalten zu imitieren. Das Abfangen von InputEvents ist dank GlassPane kein Problem, das Verhindern des Fensterschließens ebenfalls nicht.

Aber man kann das Elternfenster immer noch minimieren und maximieren, was ebenfalls nicht sein soll ... Wie kann ich das verhindern? Umbauen auf Window scheidet aus, weil ich keine Macht über das Elternfenster habe. Einen WindowListener, der bei windowIconified() setState(Frame.NORMAL) aufruft, habe ich ausprobiert, sieht aber scheiße aus.

Am liebsten wäre es mir, man könnte das Verhalten einfach deaktivieren - aber wie?

mpG
Tobias


----------



## thE_29 (1. Apr 2008)

Ich würde bei der Animation weitermachen!

Kann man den das modale verhalten nach setvisible true ändern? Falls ja, lass ihn zuerst nicht modal mach deine Animation und dann setz den auf modal!

Desweiteren verstehe ich nicht warum eine Animation blockiert wird? Oder wie machst/startest du die Animation?


----------



## Noar (1. Apr 2008)

Sollte man das nicht mit setResizable(false) verhindern können? 

Evtl. hab ich dich aber auch falsch verstanden.


----------



## Tobias (1. Apr 2008)

ARGH! Manchmal sieht man echt den Wald vor lauter Bäumen nicht! Dialog hat eine Methode setModal() mit der sich alles wunderbar machen lassen sollte ...

Danke, thE_29!

mpG
Tobias

P.S.: @Noar: setResizable() verhindert das Maximieren, aber nicht das Minimieren.
P.P.S.: Funktioniert leider nicht wie gewünscht. Zwar liefert isModal() true zurück, doch das Parentfenster läßt sich weiterhin schließen und nimmt auch Eingabeevents an ... Ich geh da mal mit nem Debugger dran.


----------



## Tobias (1. Apr 2008)

Ok, setModal funktioniert prima vor dem setVisible, aber leider nicht mehr danach. Muß ich also den ursprünglichen Ansatz weiterverfolgen ...

Zur Animation: Der Dialog ist dazu gedacht auf Touchscreens Eingabehilfen für Formulare anzubieten. Damit man nicht die Orientierung verliert, poppt der Dialog immer von da auf, wo man auf das Formular "geklickt" (mit dem Finger draufgepatscht) hat.

Diese Animation ist mit Hife des TimingFrameworks (https://timingframework.dev.java.net/) in der setVisible() des Dialogs realisiert. Damit man was sieht muß aber die Animation NACH super.setVisible() ausgeführt werden, was aber nicht passiert, da super.setVisible() den Thread blockiert. Wenn ich die Animation um ein paar Konsolenausgaben bereicher, sehe ich diese deshalb immer erst nach dem Schließen des Dialogs. Deshalb kommt ein modaler Dialog nicht in Frage.

mpG
Tobias


----------



## Illuvatar (1. Apr 2008)

Ähm... aber du weißt dass es sowas wie "Threads" gibt? (Ich gehe davon aus dass du das weißt )

Soll heißen: Du kannst die Animation natürlich nicht direkt in die setVisible-Methode packen. Aber du kannst an der Stelle einen Thread starten, der den Dialog animiert.

Edit: Oder blockieren modale Dialoge alle Threads? Kann ich mir eigentlich nicht vorstellen, mom


----------



## Tobias (1. Apr 2008)

Ja, das es Threads gibt, weiß ich. Die Animation wird in der setVisible ja auch nur angestoßen. Das TimingFramework ist intern eine Listener-Architektur auf Basis des javax.swing.Timers, wenn ich das richtig verstanden habe. Eigentlich sollte das doch im AWT Dispatch Thread weiterlaufen können, denn ein modaler Dialog sollte lediglich InputEvents auf das Elternfenster abblocken. Aber nach super.setVisible(true) passiert bei modalen Dialogen gar nichts mehr, bis der Dialog geschlossen ist. Da dürfte es dann auch schwierig werden nachträglich noch einen zweiten Thread mit der Animation anzustoßen (Zumal der dann ja auch mit dem AWT Dispatch Thread synchronisiert weden müßte).

Ich habe jetzt eine Ausweichstrategie geplant, die mir zwar nicht so gut gefällt, aber im Prototyp funktioniert: Ich animiere nicht den modalen Dialog selbst, sondern ein undekoriertes JWindow und setze den eigentlichen (jetzt modalen) Dialog nach Beendigung der Animation auf sichtbar und verstecke das "Platzhalterfenster" wieder.

mpG
Tobias


----------



## Illuvatar (2. Apr 2008)

Hm gut ich kenn das TimingFramework nicht.
Ich hab jetzt grad so schön ein Testbeispiel zusammengebastelt, das poste ich jetzt trotzdem mal noch 


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ModalTest extends JFrame
{
  public ModalTest(String title)
  {
    super(title);
    setDefaultCloseOperation (EXIT_ON_CLOSE);
    setSize(800, 600);
    setLocationRelativeTo(null);
    addMouseListener (new DialogCaller());
    setResizable(false);
    setVisible(true);
  }
  
  @Override
  public void paint (Graphics g)
  {
    super.paint(g);
    g.drawString("Click or die!", 100, 100);
  }

  public static void main(String[] args) {
    new ModalTest("ModalTest");
  }
}
class DialogCaller extends MouseAdapter
{
   @Override
   public void mouseClicked (MouseEvent evt)
   {
     JDialog popup = createDialog ((Component)evt.getSource());
     
     Dimension startSize = new Dimension (150, 50); // frames cannot be 0/0, that would thus look bad
     Point startPoint = new Point (evt.getPoint());
     SwingUtilities.convertPointToScreen (startPoint, (Component)evt.getSource());
     startPoint.translate (-startSize.width / 2, -startSize.height / 2); // center it
     DialogAnimator da = new DialogAnimator (popup, startPoint, popup.getLocation(),
                         startSize, popup.getSize(), 1500L);
                         
     da.start();
     popup.setVisible(true);
   }
   
   private static JDialog createDialog(Component parentComponent)
   {
     JOptionPane jop = new JOptionPane("That's just a simple test message, dude! No worryin'!",
                                       JOptionPane.ERROR_MESSAGE, JOptionPane.DEFAULT_OPTION);
     return jop.createDialog(parentComponent, "Test");
   }
}
class DialogAnimator implements Runnable
{
   private JDialog dialog;
   private Point startPoint, endPoint;
   private Dimension startSize, endSize;
   private long time, startTime;
   private boolean started;
   
   public DialogAnimator (JDialog dialog, Point startPoint, Point endPoint,
                          Dimension startSize, Dimension endSize, long time)
   {
      this.dialog = dialog;
      this.startPoint = startPoint;
      this.endPoint = endPoint;
      this.startSize = startSize;
      this.endSize = endSize;
      this.time = time;
      started = false;
   }
   
   public synchronized void start()
   {
      if (started)
         throw new IllegalStateException ("Animation has already started");
      startTime = System.currentTimeMillis();
      started = true;
      new Thread(this).start();
   }
   
   @Override
   public void run()
   {
      for (long timePassed = 0; timePassed < time; timePassed = System.currentTimeMillis() - startTime){
         double perc = 1.0 * timePassed / time;
         Point currentPoint = lerpPoint (startPoint, endPoint, perc);
         Dimension currentSize = lerpSize (startSize, endSize, perc);
         dialog.setLocation (currentPoint);
         dialog.setSize (currentSize);
      }
      dialog.setLocation (endPoint);
      dialog.setSize (endSize);
   }
   
   private static Point lerpPoint (Point p1, Point p2, double perc)
   {
     Point ret = new Point();
     ret.x = p1.x + (int) Math.round (perc * (p2.x - p1.x));
     ret.y = p1.y + (int) Math.round (perc * (p2.y - p1.y));
     return ret;
   }

   private static Dimension lerpSize (Dimension d1, Dimension d2, double perc)
   {
     Dimension ret = new Dimension();
     ret.width = d1.width + (int) Math.round (perc * (d2.width - d1.width));
     ret.height = d1.height + (int) Math.round (perc * (d2.height - d1.height));
     return ret;
   }
}
```


----------



## thE_29 (2. Apr 2008)

Wie wärs mit dem Aufruf von der Animation in 
	
	
	
	





```
SwingUtitlies.invokeLater(new Runnable(){public void run()
{
//aufruf hier
}
});
setVisible(true);
```


----------



## Tobias (2. Apr 2008)

Danke für eure zahlreichen Hilfestellungen. Besonderen Dank an Illuvatar für das Beispiel.

Da ich leider mehrere Tage hinterm Zeitplan hänge und im Prototyp eine funktionierende Lösung vorhanden ist, werde ich die jetzt auch so übernehmen - selbst wenn sie nicht gerade das Gelbe vom Ei ist .

mpG
Tobias


----------

