Absolute Koordinaten von JComponent ermitteln

Ist es möglich von einem JComponent-Objekt, genauer gesagt einem JButton, die absoluten Koordinaten zu ermitteln - spricht von den äußeren Bildschirmrändern.
Ich möchte nämlich, dass nach dem Klick auf einen Button ein kleines JWindow als Auswahl-Panel aufspringt - und zwar exakt unter diesem Button, egal wo das Fenster sich befindet bzw wie groß es aufgezogen wurde.
Ferner wäre noch interessant, wie ich das JWindow nach Verlust des Fokus wieder verschwinden lassen kann. Über addFocusListener() hatte ich bisher kein Glück …

du wirst deine Freude mit http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/SwingUtilities.html haben :smiley:

Hm, entweder bin ich zu dumm, oder ich kann mit diesen Methoden echt nix anfangen .__.
Vielleicht funktionieren sie beim Einsatz von GridBagLayout nicht? :confused:

das hat doch mitm GBL nichts zu tun :wink:
probier doch mal http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/SwingUtilities.html#convertPointToScreen(java.awt.Point, java.awt.Component)

jButton1.getLocationOnScreen()

Du bist mein Hero! :smiley:
Das positionieren funzt jetzt schon super, bleibt nur die Frage offen wie ich das JWindow auch wieder entfernen kann …
Über addFocusListener() hatte ich bisher leider kein Glück :frowning:

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

public class SpecialTagsPanel implements ActionListener {
	JWindow win;
	JComponent component;
	
	public SpecialTagsPanel( JComponent jc ) {
		this.component = jc;
	}

	public void actionPerformed( ActionEvent e ) {
		initPanel();
	}
	
	public void initPanel() {
		Point coords =  this.component.getLocationOnScreen();
		
		this.win = new JWindow();
		this.win.setBounds( coords.x, (coords.y+this.component.getHeight()), 400, 200 );
		this.win.setAlwaysOnTop( false );
		this.win.addFocusListener( 
				new FocusListener() {
					public void focusGained( FocusEvent fe ) {
						System.out.println("focus");
					}

					public void focusLost( FocusEvent fe ) {
						win.setVisible( false );
						win.dispose();
						component.setEnabled( true );
						System.out.println("no focus");
					}
				}
		);
		
		JPanel panel = new JPanel();
		panel.setBorder( BorderFactory.createLineBorder(Color.BLACK) );
		panel.add( new JLabel("Noch nicht verfügbar!") );
		
		this.win.getContentPane().add( panel );
		this.win.setVisible( true );
		this.component.setEnabled( false );
	}
}```

du musst es auch auf die Komponenten auf dem Fenster hinzufügen bzw darüber machen weil diese haben ja den Fokus

Wieso? Das JWindow ist ja eigentlich vom Hauptfenster unabhängig, und es soll auch verschwinden wenn ich zB irgendein anderes Programm fokusiere!

ja aber sobald du etwas auf das Fenster packst wirst du feststellen dass es nie den Fokus bekommt.

kommen die Ausgaben bei dir?
(Solange du nichts draufpackst sollten sie kommen und es sollte auch alles klappen ;))

Nein sie kommen nicht, und wenn ich den FocusListener auf das Hauptfenster ansetze passiert ebenfalls nichts! :frowning:

adde den Listener mal deinem PAnel und dem Label dann wirst du etwas feststellen :smiley:

Ohne owner ist JWindow eh nicht fokusierbar.
Ich würde das Problem jedoch so lösen:
anstatt des FocusListeners machst du einen MouseListener auf component und schliesst das Fenster bei mousePressed.
Wenn du dem JWindow den Frame als owner gibst, kannst du
zusätzlich mit dem FocusListener arbeiten.
Du bekommst focusLost aber nur, wenn du auf eine fokusierbare Komponente klickst:
der Button kommt in dem Fall nicht in Frage, weil er disabled ist!
Daher würde ich den MouseListener jedenfalls auch machen.

/*
 * SpecialTagsPanel.java
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SpecialTagsPanel implements ActionListener {
    JWindow win;
    JComponent component;
    private Frame owner;
    
    public SpecialTagsPanel( JComponent jc, Frame owner ) {
        this.component = jc;
        this.owner = owner;
    }
    public void actionPerformed( ActionEvent e ) {
        initPanel();
    }
    public void initPanel() {
        Point coords =  this.component.getLocationOnScreen();
        this.win = new JWindow(owner);
        this.win.setBounds( coords.x, (coords.y+this.component.getHeight()), 400, 200 );
        this.win.setAlwaysOnTop( false );
        this.component.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                win.setVisible( false );
                win.dispose();
                component.setEnabled( true );
            }
        });
        win.setFocusable(true);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                win.requestFocus();
            }
        });
        this.win.addFocusListener(
                new FocusListener() {
            public void focusGained( FocusEvent fe ) {
                System.out.println("focus");
            }
            public void focusLost( FocusEvent fe ) {
                win.setVisible( false );
                win.dispose();
                component.setEnabled( true );
                System.out.println("no focus");
            }
        });
        JPanel panel = new JPanel();
        panel.setBorder( BorderFactory.createLineBorder(Color.BLACK) );
        panel.add( new JLabel("Noch nicht verfügbar!") );
        
        this.win.getContentPane().add( panel );
        this.win.setVisible( true );
        this.component.setEnabled( false );
    }
    public static void main(final String... args){
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400,300);
        f.setLocationRelativeTo(null);
        JButton bt = new JButton("Test");
        SpecialTagsPanel s = new SpecialTagsPanel(bt, f);
        f.add(bt, BorderLayout.NORTH);
        f.add(new JTextField(), BorderLayout.SOUTH);
        bt.addActionListener(s);
        f.setVisible(true);
    }
}```

@Andre Uhres
Ich habe jetzt versucht deinen Vorschlag so gut wie möglich zu integrieren, auch wenn ich manche Dinge noch nicht so ganz erfasst habe ^^
Es handelt sich hierbei übrigens um mein Softwareprojekt JMRename, welches ich bereits im Projekte-Forum gepostet habe.
Meine Implementierung des JWindow funktioniert leider trotzdem nur so halbwegs, ich wäre dir sehr dankbar wenn du dir das Ganze vielleicht mal ansehen könntest:
blog2 :: JMRename 0.0.7b steht zum Download bereit! :slight_smile:

Es gibt eine downloadbare Binär- und Source-Variante!

Mit dieser Version kannst du das Fenster schliessen,
indem du einfach daneben klickst oder den „OK“-Button im Fenster betätigst.
Das Fenster ist hier kein JWindow, sondern ein JPanel auf dem POPUP_LAYER.
Ich hoffe, das hilft dir:


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

public class SpecialTagsPanel implements ActionListener {

    private JPanel win;
    private JFrame frame;
    private JButton component;
    private JPanel panel;
    private ComponentListener cl;

    public SpecialTagsPanel(JFrame jf, JButton jc) {
        this.win = null;
        this.frame = jf;
        this.component = jc;
    }

    public void actionPerformed(ActionEvent e) {
        initPanel();
    }

    public void destroyWindow() {
        frame.removeComponentListener(cl);
        this.win.setVisible(false);
        this.win = null;
        component.setEnabled(true);
    }

    public void initPanel() {
        component.setEnabled(false);
        final Point coords = this.component.getLocationOnScreen();
        coords.translate(-frame.getLocationOnScreen().x, -frame.getLocationOnScreen().y - (JFrame.isDefaultLookAndFeelDecorated() ? 0 : 30));

        this.win = new JPanel(null);
        this.win.setSize(frame.getSize());
        win.setOpaque(false);
        cl = new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                destroyWindow();
            }
        };
        frame.addComponentListener(cl);
        win.addMouseListener(new MouseAdapter() {

            @Override
            public void mousePressed(MouseEvent e) {
                Point mousePoint = e.getPoint();
                if (!panel.getBounds().contains(mousePoint)) {
                    destroyWindow();
                }
            }
        });

        panel = new JPanel();
        panel.setBounds(coords.x, coords.y + this.component.getHeight(), 400, 200);
        panel.setBorder(BorderFactory.createLineBorder(Color.BLACK));
        panel.add(new JLabel("Noch nicht verfügbar!"));
        JButton bt = new JButton("OK");
        bt.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                destroyWindow();
            }
        });
        panel.add(bt);
        this.win.add(panel);
        this.frame.getLayeredPane().add(win, JLayeredPane.POPUP_LAYER);
        this.win.setVisible(true);
        bt.requestFocusInWindow();
    }
}```

Vielen Dank! :slight_smile:
Werd’s gleich ausprobieren

EDIT:
Wahnsinn oO
Das funzt ja noch viel besser als ich es mir überhaupt vorgestellt hatte!
Soll ich dich als Autor in dieser Datei dazuschreiben?

Wenn du willst, ich hab nix dagegen. Bin jedenfalls froh, dir ein wenig geholfen zu haben :slight_smile:

Ich hätte dein Programm grad gebraucht, um von allen Dateien eines Verzeichnisses den Dateityp zu ändern, z.B.:
03760100.007_2431 --> 03760100_007_2431.txt
03760100.007_2432 --> 03760100_007_2432.txt
03760100.007_2433 --> 03760100_007_2433.txt
usw.

Das scheint aber nicht zu gehen, oder?

Das Feature zum Extension-Handling hab ich leider noch nicht integriert :frowning:
Außerdem kannst du bislang immer nur ALLE Dateien im Verzeichnis umbenennen, selektives auswählen muss ich erst dazu programmieren.

Wenn du dich noch bis heute Abend geduldest, hab ist das geritzt :wink:

Naja, du brauchst dich jetzt nicht zu hetzen. Ich hab das erstmal mit einem kleinen Programm auf die Schnelle hart codiert. Aber ich brauch sowas immer wieder und könnte dein Programm dann gut gebrauchen. Das läuft aber nicht weg :wink:

Gut zu wissen ^^
Hab jetzt vorerst trotzdem mal ein “Notfallrelease” erstellt. Exklusiv-Download hier -> jmrename-0.0.7b2_full.zip