2010-02-16 5 views
6

Ich versuche, eine benutzerdefinierte Swing-Komponente zu rendern, wo ich die JComponent-Klasse erweitert habe.Wann gibt getGraphics() eine gültige Grafikinstanz zurück?

Um die Komponentenanforderungen zu vereinfachen, lassen Sie meine Komponente einfach so zusammenfassen, dass sie einige Zeichenfolgen mit jeweils eigenen Zeichensätzen darstellen müssen.

Ich brauche meine Komponente genau auf die summierte Breite und Höhe meiner gerenderten Saiten.

Um diese Größe zu bestimmen, verwende ich die FontMetrics, um die Dimensionen jeder Zeichenfolge zu berechnen. Mit diesen Informationen kann ich herausfinden, wie groß meine Komponente sein wird und die Größe entsprechend ändern.

Das Problem ist, dass, wenn ich auf die getGraphics() zugreifen immer Null ist, so kann ich nicht die FontMetrics-Instanz abrufen. Wenn ich darauf warte, meine Komponentengröße aus der überschriebenen paintComponent() -Methode zu berechnen, ist es viel zu spät (die Komponente hat bereits eine Größe, richtig?).

Die Dokumentation besagt, dass "diese Methode null zurückgibt, wenn diese Komponente derzeit nicht angezeigt werden kann". Wann weiß ich, wann die Komponente zur Anzeige bereit ist, und habe ein Graphics-Objekt, mit dem ich die Größe meiner Komponente ändern kann?

Wie lautet die Swing-Invokationsreihenfolge für das Rendern der Komponente, sobald der Frame setVisible (true) aufgerufen wurde?

Dank


aktualisieren: Freitag, 6. Februar 2010 um 23:34 Uhr

Wie in den Kommentaren unten erwähnt, das Gridlayout respektiert keine setXxxSize() überhaupt. Für alle Interessierten habe ich die Ergebnisse der Verwendung von GridLayout, BoxLayout und FlowLayout unter Verwendung eines einfachen Rahmens veröffentlicht, der 5 Komponenten fester Größe mit einer Breite von 200 x 50 erhält (durch Einstellung von min, max und preferred).

Testergebnisse:

Die Grid wird immer entlang der Breite und Höhe der Größe verändert (wie in den Kommentaren erwähnt)

Die Flow immer respektiert die Komponenten unabhängig Größe.

Wie für die der BoxLayout ...

Die PAGE_AXIS und Y_AXIS die Breite der Komponenten auf etwa die Hälfte ihrer Größe geschrumpft (104), aber nicht die Höhe schrumpfen.

Die LINE_AXIS und x_axis schrumpfte die Höhe der Komponenten, was Null schien aber die Breite nicht berühren.

Antwort

7

Zuerst können Sie Ihre Strings mit der TextLayout Klasse und den damit verbundenen Sachen messen.Zum Beispiel

public static void main(final String[] args) throws Exception 
{ 
    final FontRenderContext frc = new FontRenderContext(null, true, true); 
    final Font font = new Font("serif", Font.PLAIN, 18); 
    final TextLayout layout = new TextLayout("This is a test", font, frc); 
    final Rectangle2D bounds = layout.getBounds(); 
    System.err.println((int) (bounds.getWidth() + .5)); 
} 

Zweitens können Sie informiert werden, wenn die Komponente durch die Verwendung eines ComponentListener sichtbar geworden ist, aber das ist nicht notwendig für die Saiten in „advance“ Messen!

+0

Ich sehe, dass Sie Ihre Schriftart erstellen? Wenn ich getFont() versuchte, ist die Schriftart null. Ich nehme an, dass eine JComponent keine Standardschrift hat? – Jeach

+0

Eine Komponente, deren Schriftart nicht explizit festgelegt ist, verwendet die Schriftart des übergeordneten Elements. Wenn Sie kein Elternteil haben, dann haben Sie keine Schriftart. Sie sollten besser Ihre eigene Schriftart in Ihrem Konstruktor explizit festlegen. –

+0

Danke Jonathan! Ich habe angefangen, die Schriftart zu setzen. Ich kann die Komponente jetzt auf diese Weise korrekt darstellen, aber aus irgendeinem Grund verweigert diese Komponente immer noch die Größenanpassung an meine Dimensionen. Wenn ich einen Rahmen mit einem Rasterlayout (0 Zeilen, 1 Spalte) erzeuge und 10 meiner Komponenten hinzufüge, mache den Rahmen im Vollbildmodus. Jedes Element erhält 1/10 der Höhe des Bildschirms in der Höhe, wenn sie nicht viel kleiner sein sollte. Ich setze die min, max, preferred, setSize() und es macht irgendwie immer noch zu seinem eigenen Geschmack !! – Jeach

2

Verwenden Sie ein JLabel zum Rendern Ihrer Strings, dann können Sie einfach die getPreferredSize() - Methode dieser Bezeichnung verwenden.

+0

Ich vermute, dass ich erwartet habe, dass mir jemand sagt, dass ich bestehende Swing-Komponenten dafür verwenden soll . Meine Anforderungen sind, einen Großteil des vorhandenen Bloat aus dieser Komponente zu entfernen und es direkt selbst zu rendern. Es sind Etiketten und Icons innerhalb von Panels und innerhalb von Panels mit Layouts usw. Ich schätze, es wurde mit einem automatisierten Tool erstellt. Jetzt muss es auf eine Diät gehen, die mir gesagt wird! – Jeach

+0

Auf den zweiten Gedanken, Ereignis JLabel sind problematisch, weil wie in meinem Kommentar zu Jonathan erwähnt, sollte das Etikett auf eine feste Höhe nicht viel größer als die Schriftgröße bleiben. JLabels neigen dazu, genau das zu tun, was meine Komponente tut ... stretch! – Jeach

+0

Wie von Jonathan erwähnt, ist dies ein Layout-Problem, keine "bevorzugte Größe" Berechnung. Wenn Sie weiterhin ein GridLayout für Ihr Panel verwenden möchten, besteht ein weiterer Ansatz darin, ein übergeordnetes Panel mit einem BorderLayout zu erstellen. Fügen Sie das Panel mit dem GridLayout zum NORD des übergeordneten Panels hinzu. Jetzt wird der gesamte zusätzliche Platz für die Mitte vergeben und Ihr Panel wird in seiner bevorzugten Größe angezeigt. – camickr

Verwandte Themen