Swing JDesktopPanel, transparenter Schleier beim OUTLINE_DRAG_MODE

Status
Nicht offen für weitere Antworten.

localhorst

Mitglied
Hi,

ich habe ein JDesktopPanel mit dem Dragmodus: OUTLINE_DRAG_MODE.

Wenn ich nun die Größe eines JInternalFrame ändern will, erscheint ja erstmal nur ein Rahmen,
damit man erkennt, wie groß das Fenster beim loslassen der Maustaste sein wird.

Meine Frage:

Wie bekomme ich es hin, diesen Rahmen auch noch mit einer transparenten Farbe zu füllen?

Welche Methode ist überhaupt dafür zuständig also welche Methode zeichnet diesen Rahmen? ist sie Im DesktopManager, DesktopPanel oder direkt im JInternalFrame?

Ansonsten werde ich mir was mit MouseListenern zusammen klicken aber ich möchte lieber die vorhandene Methode überschreiben wegen der Übersichtlichkeit.

Danke im voraus.
 

Ebenius

Top Contributor
Reine Mutmaßung: Ich tippe stark darauf, dass die Linie vom UI-Delegate des JDesktopPane gezeichnet wird. Daher würde ich annehmen, dass das Aussehen der Outline zu ändern in einem eigenen UI-Delegate enden würde.

Ebenius
 

Ebenius

Top Contributor
So ist's wenn man nur rät und nicht nachschaut. Der DesktopManager macht das in [c]resizeFrame(...)[/c]. Schau Dir mal den Quelltext der Default-Implementierung an. Ich würde also einen eigenen DesktopManager mit einer eigenen [c]resizeFrame(...)[/c]-Methode ausstatten, die das Zeichnen dann selbst übernimmt.

Ebenius
 

localhorst

Mitglied
So ist's wenn man nur rät und nicht nachschaut. Der DesktopManager macht das in [c]resizeFrame(...)[/c]. Schau Dir mal den Quelltext der Default-Implementierung an. Ich würde also einen eigenen DesktopManager mit einer eigenen [c]resizeFrame(...)[/c]-Methode ausstatten, die das Zeichnen dann selbst übernimmt.

Ebenius

Das habe ich bereits getan,

Java:
        this.desktopManager = new OwnDesktopManager();
        this.desktopPane.setDesktopManager(desktopManager);

es scheint jedoch so, dass keine einzige Methode aus dem DesktopManager jemals aktiv wird.
habe alle möglichen Methoden überschrieben und noch ein System.out.println reingemacht.
Im JInternalFrame wird beim resizen 1 mal die Paint Methode ausgeführt.. aber die Methode, die den Border macht, müsste doch eigentlich bei jeder kleinen Mausbewegung aufgerufen werden.
 
Zuletzt bearbeitet von einem Moderator:

Ebenius

Top Contributor
es scheint jedoch so, dass keine einzige Methode aus dem DesktopManager jemals aktiv wird.
Dann hast Du wahrscheinlich was falsch gemacht. Funktioniert bei Dir dieser Test?

Java:
/* (@)JInternalFrameResizeTest.java */

/* Copyright 2009 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. */

package com.ebenius;

import java.awt.Dimension;

import javax.swing.*;

/**
 * Test GUI for internal frame resizing.
 * 
 * @version $Revision$ as of $Date$
 * @author Sebastian Haufe
 * @since Playground-3.8
 */
public class JInternalFrameResizeTest {

  /**
   * Test main method.
   * 
   * @param args ignored
   */
  public static void main(String[] args) {
    final JDesktopPane contentPane = new JDesktopPane();
    contentPane.setPreferredSize(new Dimension(640, 480));
    contentPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

    contentPane.setDesktopManager(new DefaultDesktopManager() {

      private static final long serialVersionUID = 1L;

      @Override
      public void resizeFrame(
            JComponent f,
            int newX,
            int newY,
            int newWidth,
            int newHeight) {
        System.out.println("resize IN");
        super.resizeFrame(f, newX, newY, newWidth, newHeight);
        System.out.println("resize OUT");
      }
    });

    final JInternalFrame innerFrame = new JInternalFrame("Test Frame");
    innerFrame.setResizable(true);
    innerFrame.setSize(100, 100);
    innerFrame.setVisible(true);
    contentPane.add(innerFrame);

    final JFrame f = new JFrame("Internal Frame Resize Fun"); //$NON-NLS-1$
    f.setContentPane(contentPane);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}
Ebenius
 

localhorst

Mitglied
Dann hast Du wahrscheinlich was falsch gemacht. Funktioniert bei Dir dieser Test?

Java:
/* (@)JInternalFrameResizeTest.java */

/* Copyright 2009 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. */

package com.ebenius;

import java.awt.Dimension;

import javax.swing.*;

/**
 * Test GUI for internal frame resizing.
 * 
 * @version $Revision$ as of $Date$
 * @author Sebastian Haufe
 * @since Playground-3.8
 */
public class JInternalFrameResizeTest {

  /**
   * Test main method.
   * 
   * @param args ignored
   */
  public static void main(String[] args) {
    final JDesktopPane contentPane = new JDesktopPane();
    contentPane.setPreferredSize(new Dimension(640, 480));
    contentPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

    contentPane.setDesktopManager(new DefaultDesktopManager() {

      private static final long serialVersionUID = 1L;

      @Override
      public void resizeFrame(
            JComponent f,
            int newX,
            int newY,
            int newWidth,
            int newHeight) {
        System.out.println("resize IN");
        super.resizeFrame(f, newX, newY, newWidth, newHeight);
        System.out.println("resize OUT");
      }
    });

    final JInternalFrame innerFrame = new JInternalFrame("Test Frame");
    innerFrame.setResizable(true);
    innerFrame.setSize(100, 100);
    innerFrame.setVisible(true);
    contentPane.add(innerFrame);

    final JFrame f = new JFrame("Internal Frame Resize Fun"); //$NON-NLS-1$
    f.setContentPane(contentPane);
    f.pack();
    f.setLocationRelativeTo(null);
    f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    f.setVisible(true);
  }
}
Ebenius

Danke für das Beispiel ;)

so hatte ich es zwar auch, habe aber jetzt den Grund gefunden, warum es bei mir nicht ging.

hatte einen Betriebssystem abhängigen Look And Feel drin, deshalb wurde der DesktopManager irgendwie nicht benutzt.

Java:
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

Leider muss ein Betriebssystem abhängiger Look verwendet werden.
Wie soll das denn dann funktionieren?
Kann man das Look and Feel ding für das Betriebssystem auch überschreiben?
 

Ebenius

Top Contributor
Welches L&F ist's denn, mit dem's nicht tut? Windows-L&F?

EDIT: Mit Nimbus, Metal und CDE funktioniert der Weg; mit GTK+ tut's bei mir auch nicht... :-(

EDIT2: ... was sehr seltsam ist, denn sowohl GTK+ als auch Nimbus sind Synth-L&Fs. Warum's mit einem tut und mit dem anderen nicht, ist mir bisher nicht klar.

Ebenius
 
Zuletzt bearbeitet:

Ebenius

Top Contributor
Ahja, jetzt weiß ich, warum es beim GTK+ nicht geht, beim Nimbus aber doch. Das SynthDesktopPaneUI setzt den [c]desktopManager[/c] wieder zurück, wenn die DesktopPane eine Taskbar hat. Siehe [c]javax.swing.plaf.synth.SynthDesktopPaneUI[/c]: [java=133] protected void installDesktopManager() {
if (UIManager.getBoolean("InternalFrame.useTaskBar")) {
desktopManager = oldDesktopManager = desktop.getDesktopManager();
if (!(desktopManager instanceof SynthDesktopManager)) {
desktopManager = new SynthDesktopManager();
desktop.setDesktopManager(desktopManager);
}
} else {
super.installDesktopManager();
}
}
[/code]
Diese Methode wird direkt auf die Veränderung des "desktopManager"-Properties aufgerufen. Das bedeutet, Dein eigener DesktopManager wird im GTK+-L&F nie verwendet.

Ist ein sehr hässliches Verhalten wie ich finde. Soetwas tut keine der anderen Standard-L&F-Implementierungen, auch nicht Windows-L&F. Als Workaround könnte man (nach dem setzen des L&Fs) die Taskbar wegkonfigurieren:
Java:
UIManager.getDefaults().put("InternalFrame.useTaskBar", Boolean.FALSE);
Ebenius
 

localhorst

Mitglied
genau, ich benutze das GTKLookAndFeel.

ist ja merkwürdig..
Dann kenn ich nur die Möglichkeit, alle Betriebssystem LookAndFeel Klassen zu überschreiben.
aber das ist doch viel zu aufwändig.
Klappt es mit dem Windows LookAndFeel?
Ich vermute auch nicht.
 

Ebenius

Top Contributor
Klappt es mit dem Windows LookAndFeel?
Ich vermute auch nicht.
Siehe: mein letzter Beitrag.

Das gesamte L&F zu überschreiben ist doch etwas übertrieben. Du kannst natürlich Dein eigenes DesktopPaneUI implementieren. Wenn Du tatsächlich das Aussehen der ganzen DesktopPane verändern willst, dann ist das ohnehin nicht die schlechteste Idee. Ist zwar nicht trivial aber als Ableitung von BasicDesktopPaneUI auch nicht übermäßig kompliziert. Und dann einfach
Java:
desktopPane.setUI(new MyOwnDesktopPaneUI());
Ebenius
 

localhorst

Mitglied
oha, das ging ja fix.

hm, leider wieder diese Taskbar benötigt, wenn man es auf false setzt, wird dann die Taskbar ausgeblendet?
 

localhorst

Mitglied
Du hattest recht, die Taskbar ist nun weg .. aber mein DesktopManager wird verwendet.
Vielen Dank schonmal für die Hilfe.

Habe leider noch nicht viel Erfahrung in Sachen gui.

Selbst wenn ich es ohne die Taskbar mache, weiss ich nicht, in welcher Methode genau der Border beim Resizen erstellt wird.

Beim Debuggen habe ich rausgefunden, dass unter anderem auch ein BorderListener in der JinternalFrameUI reagiert.. damit kann ich aber irgendwie nichts anfangen.

Ich muss es zumindest schaffen, den alten Border, der standartmäßig gezeichnet wird zu entfernen.
 

Ebenius

Top Contributor
Selbst wenn ich es ohne die Taskbar mache, weiss ich nicht, in welcher Methode genau der Border beim Resizen erstellt wird.
Genau in der die mein Testprogramm überschreibt: [c]resizeFrame(...)[/c]. Die Default-Implementierung zeichnet da so: [java=403]
if ( dragMode == DEFAULT_DRAG_MODE || dragMode == FASTER_DRAG_MODE ) {
setBoundsForFrame(f, newX, newY, newWidth, newHeight);
} else {
JDesktopPane desktopPane = getDesktopPane(f);
if (desktopPane != null){
Graphics g = JComponent.safelyGetGraphics(desktopPane);

g.setXORMode(Color.white);
if (currentBounds != null) {
g.drawRect( currentBounds.x, currentBounds.y, currentBounds.width-1, currentBounds.height-1);
}
g.drawRect( newX, newY, newWidth-1, newHeight-1);

// Work around for 6635462, see comment in dragFrame()
sun.java2d.SurfaceData sData =
((sun.java2d.SunGraphics2D)g).getSurfaceData();
if (!sData.isSurfaceLost()) {
currentBounds = new Rectangle (newX, newY, newWidth, newHeight);
}

g.setPaintMode();
g.dispose();
}
}

[/code]

Beim Debuggen habe ich rausgefunden, dass unter anderem auch ein BorderListener in der JinternalFrameUI reagiert.. damit kann ich aber irgendwie nichts anfangen.
Den brauchst Du nicht. Das landet am Ende in [c]resizeFrame(...)[/c] im DesktopManager.

Ich muss es zumindest schaffen, den alten Border, der standartmäßig gezeichnet wird zu entfernen.
Einfach die super-Methode nicht aufrufen (also leer überschreiben) sollte funktionieren, oder?

Ebenius
 
Zuletzt bearbeitet:
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben