Wann existiert eine Instanz (eigene Klasse)

Sneedlewoods

Mitglied
Hallo,

ich habe eine eigene Klasse, abgeleitet von JLabel

Java:
public class TextLink extends JLabel {
    Rectangle2D bounds;
    int posX;
    int posY;
    ...
    public TextLink(String text, Font f, int x, int y) {
        //Konstruktor
        this.setText(text);
        this.setFont(f);
        posX = x;
        posY = y;
        getStringBounds();
    }

    private void getStringBounds() {
        //zur ermittlung von Breite und Höhe des Textes in Bezug auf einen
        //bestimmten Font
        FontMetrics metrics = this.getGraphics().getFontMetrics();
        bounds = metrics.getStringBounds(this.getText(), this.getGraphics());
    }
 
    ...   
}

Da bekomme ich jetzt eine NullPointerException. Ich vermute dass es evtl. an dem this.getGraphics liegt, was ja im Konstruktor über getStringBounds() aufgerufen wird.

Was ich will ist, dass wenn TextLink erzeugt wird, automatisch bounds gefüllt wird.

Kann mir da jemand helfen?
Danke Sneedle
 
Du setzt in deinem Konstruktor zwar die Font für das JLabel, aber dein JLabel selbst besitzt überhaupt kein Graphics Objekt. Entsprechend gibt dir getGraphics() natürlich null zurück.

Aber ein JLabel bzw ein Component besitzt selbst die Methode: getFontMetrics(). Wieso verwendest du die nicht?

Java:
FontMetrics metrics = this.getFontMetrics();

PS: Man ich muss echt schneller werden XDDD
Ruf mal super (); im Konstruktor auf. Klappt das?
Das klappt nicht 🙂 Dachte ich aber auch zuerst. Aber Graphics ist trotzdem null 😉
 
Zuletzt bearbeitet:
@ARadauer
mit super(); klappts leider nicht

@Highchiller
hm also des find ich jetzt komisch. Weil
Java:
JLabel l = new JLabel("Test");
Graphics g = l.getGraphics();
da meckert er nicht.
Weshalb ich ein Graphics-Object verwende: beim Googlen bin ich darauf gestoßen, dass getFontMetrics der Komponenten keine genauen Pixel-Angaben liefern, da sie z.B. Aliasing nicht berücksichtigen. Das getFontMetrics vom Graphics-Object soll da genauer sein.
 
Es könnte daran liegen, dass ein JLabel, wenn es leer ist, eine Größe von 0/0 hat und dementsprechend gar nicht gezeichnet wird ergo auch kein Graphics objekt instanziiert hat. Wenn du jetzt ein JLabel objekt mit dem Text "Test" erzeugst, steht ja was drinne und damit wäre getGraphics nicht mehr null.

Ist aber nur eine vermutung. Check das doch mal wenn du in deinem Beispiel statt new JLabel("Test"); einfach nur new JLabel(); machst. Ist getGraphics dann null?

Also es würde mich wundern wenn dir da Probleme begegnen weil das nicht genau genug ist.

Zur Not musste halt selbst ein Graphics objekt erzeugen und erst mal damit arbeiten. In weit das Probleme bringt weiß ich allerdings nicht.
 
@Highchiller
ja dass ist auch meine Vermutung, dass das Graphics-Object von JLabel noch nicht angelegt ist, während der Konstruktor aktiv ist.
Ein Extra-Graphics-Object erzeugen will ich eigentlich nicht, da es ja die Einstellungen vom JLabel haben soll. Das wäre für mein Empfinden dann unschön.

Natürlich kann ich in der JFrame-Klasse, ein JLabel erzeugen und danach alles machen, aber ich wollte es ja in die eigene Klasse auslagern. Das muss doch irgendwie möglich sein.

Ich hatte sogar auch folgendes probiert, was aber den gleichen Fehler erzeugte:

Java:
    public class TextLink extends JLabel {
        Rectangle2D bounds;
        int posX;
        int posY;
        ...
        public TextLink(String text, Font f, int x, int y) {
            //Konstruktor
            this.setText(text);
            this.setFont(f);
            posX = x;
            posY = y;
        }
        
        public void init() {
            getStringBounds();
        }

        private void getStringBounds() {
            //zur ermittlung von Breite und Höhe des Textes in Bezug auf einen
            //bestimmten Font
            FontMetrics metrics = this.getGraphics().getFontMetrics();
            bounds = metrics.getStringBounds(this.getText(), this.getGraphics());
        }
     
        ...  
    }

    //Main - Klasse
    public class MyFrame extends JFrame{
        TextLink start;
        Font menuFont;
    
        public MyFrame() {
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setLayout(null);
            this.setSize(800, 600);
            menuFont = new Font("Tahoma", Font.PLAIN, 10);
            //start = makeTextLink("Start", 50, 50);
            this.setVisible(true);
            JLabel l = new JLabel("Test");
            Graphics g = l.getGraphics();
        }
    
        public TextLink makeTextLink(String text, int x, int y) {
            TextLink tl = new TextLink(text, menuFont, x, y);
            this.add(tl);
            return tl;
         }
        
        public static void main(String[] args) {
            MyFrame menu = new MyFrame();
        }
}

und init() habe ich dann nach TextLink tl = new Textlink();
aufgerufen.

Oh jetzt seh ich gerade, hängt das evtl. damit zusammen, dass ich das Ganze im Konstruktor von MyFrame aufrufe und ich damit den ganzen Existiert-Es-Kram auslöse? Also wie gehe ich dann vor? Es soll ja alles automatisch angelegt werden, aber ich muss es wohl dann explizit aufrufen (nachdem der Konstruktor fertig ist) ?
 
Nee die Sache ist etwas komplizierter. Es liegt nicht daran das von deinem JLabel noch kein Objekt instanziiert wurde weil du noch im Konstruktor hängst, deine Überschrift hat mit deinem Problem leider überhaupt nichts zu tun.

Ich hab jetzt rausgefunden dass ein Graphics object auf einer Component erst instanziiert wird, wenn die Component auch tatsächlich gezeichnet wird. Solange du also nicht irgendwo auf einen Frame (der natürlich auch dein Label enthält) nicht setVisible(true); aufrufst, ist deine Graphics objekt null. Daran lässt sich leider auch nicht wirklich was ändern.

Wie dem auch sei. Ich hab mal einen kleinen Test geschrieben. Wenn ich mir vom String "Test" in Arial, Bold und Schriftgröße 12 die bounds ausrechnen lasse, aber erst NACH dem zeichnen, also mit dem richtigen Graphics objekt das du immer willst. Bekomme ich:
[x=0.0,y=-11.05957,w=25.0,h=13.798828]

Und wenn ich das ganze mit dem Vorschlag von mir tue, also einfach getFontMetrics vom Component benutze, also direkt vom JLabel aus getFontMetrics aufrufe erhalte ich:
[x=0.0,y=-11.05957,w=25.0,h=13.798828]

Also ich seh kein Unterschied 😀
Ist dir das genau genug? Kurz um, s***** aufs Aliasing und benutz einfach getFontMetrics. Das ist für deine Aufgaben bei weitem genau genug 😉
 
Wow danke für die Mühe.

Also ich werd Deinem Rat folgen und getFontMetrics der Komponente verwenden, ABER 😀

zuerst probier ich einfach TextLink.setVisible(true); bevor ich das Graphics benutze, mal schauen. Wenn es so klappt, dann meld ich mich wieder, ansonsten benutze ich Deinen Weg.

Danke.
 

Zurück
Oben