endlich habe ich mich mal wieder mit Netbeans ans programmieren getraut. Nun gleich ein Problem. Ich habe folgendes Layout:
-JFrame
---|- jTabbedPane1
------|- jPanel1
----------|- ca 400 jTexfields
----------|- ca 500 Labels
------|- jPanel2
----------|- ca 400 jTexfields
----------|- ca 500 Labels
------|- jPanel3
----------|- ca 400 jTexfields
----------|- ca 500 Labels
... und es soll noch mehr kommen. Als ich mit Netbeans angefangen habe, wusste ich nichts von dieser Beschränkung, dass die class wohl nur 65kb haben darf (Java Code too large). Die Frage ist, wie ich nun z.B. jPanel 2 und jPanel3 in eine neue test2.java verschiebe, mir diese aber trotzdem auf dem aktuellen jFrame von test1.java angezeigt wird?
... wie erwartet wieder eine hilfreiche Antwort gleich zu Beginn. Warum kann man in diesem Fall einfach mal nichts sagen, wenn man nicht helfen möchte. Wenn dir das Layout mit 900 Elementen nicht gefällt, kannst du es dir gern denken. Mir hilft dieser comment genau NULL weiter. Wenn ich mir bei kicker die Spieltabelle anschaue (Kreuztabelle) sehe ich dort 18² Zellen. Für dich sicher ein naiver Fall von STRG+w.
Naja, egal Kritik angenommen.
Also, es hätte sicher auch eine Tabelle getan. Hab ich bei Netbeans bereits gefunden. Ich finde es so immo mit jTextField für mich "besser". Wenn ich mal Bock habe, baue ich es vllt um in eine Tabelle oder lass mich etwas besseren belehren. Immo soll es so laufen, wie ich es jetzt gebastelt habe Falls unter dem Gesichtspunkt der "900 Elemente" trotzdem jemand helfen möchte, gerne.
Generell ist es ratsam, jede Klasse in eine eigene Datei zu schieben.
Warum sollte das irgendwelche Probleme beim Anzeigen machen?
Tabelle muss nicht mal sein, vermutlich reicht es schon, die Dinge zusammen zu fassen und zusammen gehörenden Elementen oder diese dynamisch zB mit Schleifen zu erzeugen, das hält das ganze deutlich kleiner, ohne das sich die Optik ändert.
Das ist mMn aber die falsche Einstellung. Warum Widgets für etwas missbrauchen, wenn es dafür schon fertige Lösungen gibt? Dann muss man sich über solche Fehlermeldungen nicht wundern.
Naja.. B2T:
Du könntest bspw. für jedes deiner JPanels eine eigene Klasse machen, welche dann die X Elemente enthalten. Das würde den ganzen Code zmd schon mal etwas aufteilen.
Dann könntest du, wie @mrBrown schon sagte, auf Schleifen setzen um Objekte gleicher Art dynamisch zu erstellen. Auch das würde noch ein paar Zeilen sparen.
Die Frage wie man das macht sollte sich eigentlich nicht stellen. Lagere den entsprechenden Code in eine Klasse aus und hol dir über Getter das JPanel um es dem JFrame / TabbedPane hinzuzufügen.. (man könnte die Klasse auch von JPanel erben lassen, bringt aber in der Hinsicht nicht wirklich einen Mehrwert).
So, nachdem ich gestern ewig probiert habe, irgendwie diese eine java-datei mit den verschiedenen Panels aufzuspalten in mehrere kleinere, muss ich nun doch um Hilfe bitten. Ich weiß nicht, wie ich das hinbekomme. Ich kann zwar mittels c&p Teile der GUI in eine neue Datei kopieren, jedoch kann ich es dann in der Hauptdatei nicht mehr ansprechen. Es gibt zwar jede Menge user, die das gleiche Problem haben, aber niemand zeigt ein Tutorial auf, in dem das ordentlich erklärt wird. Es scheint also nachträglich nicht ganz so trivial zu sein.
Wenn ich mein Projekt von neu beginne, kann ich natürlich mehrere *.java erstellen mit je nur einem Panel. Diese bekomme ich dann aber auch nicht auf meiner "GesamtGUI" zu sehen.
Ich stell auch gern meinen Code als zip zur verfügung
Ehrlich gesagt versteh ich nicht mal das Problem...
Du hast eine .java-Datei, und in dieser hast du mehrer Klassen?
Oder du hast eine .java-Datei, und in dieser eine Klasse, und möchtest diese eine Klasse trennen?
Pro Klasse eine Datei, alle Klassen in entsprechenden Packages, und dann wenn nötig importieren und die Klasse einfach nutzen.
Das die Panels nicht auf magische Weise in der GUI erscheinen ist logisch, man muss sie der schon hinzufügen, aber das muss man doch sowieso?
Es gibt zwar jede Menge user, die das gleiche Problem haben, aber niemand zeigt ein Tutorial auf, in dem das ordentlich erklärt wird. Es scheint also nachträglich nicht ganz so trivial zu sein.
Mehrere Java-Datein zu nutzen ist fast das trivialste, das sind absolute Grundlagen. Vermutlich ist das das Problem dabei - kaum jemand hat damit Probleme und deshalb gibts dazu auch kaum was.
Also, es hätte sicher auch eine Tabelle getan. Hab ich bei Netbeans bereits gefunden. Ich finde es so immo mit jTextField für mich "besser". Wenn ich mal Bock habe, baue ich es vllt um in eine Tabelle oder lass mich etwas besseren belehren. Immo soll es so laufen, wie ich es jetzt gebastelt habe.
Und was glaubst du, worin man in einer JTable die Texte eingibt? Richtig, in eine JTextfield.
Angezeigt werden die Elemente mit Labels. Der Clou: Für ALLE Zellen wird das gleiche JTextfield verwendet, es steht also nur einmal im Speicher anstatt zig mal.
Bei 65k code in einer Datei gehe ich stark davon aus, dass du den gleichen Code wieder und wieder stehen hast. Fang also erst mal damit an, eine Methode zu erstellen, welche immmer wieder auftretende Aufgaben per Parameter erledigt.
Damit reduzierst du deinen Code deutlich.
Wenn du schon unbedingt tausende von Textfeldern verwenden willst, verwalte sie nicht alle einzeln, sondern in einem Array oder ein Map, greife per Index/Key darauf zu.
Du kannst auch jedes deiner Panels in eine eigene Klasse packen, damit hast du den Code aufgeteilt.
Besser: denke objektorientiert. Deine Panels scheinen alle eine ähnliche Struktur zu haben. Erstelle also EINE Klasse, die für alle Panels verwendet werden kann.
Ob du jetzt this.getContentPane().add(new JPanel(), props) oder this.getContentPane().add(new MyClass(), props) schreibst, ist Jacke wie Hose. In beiden Fällen fügst du eine Instanz manuell deinem Layout hinzu.
btw. tausende von JTextfields sind in keinem mir bekannten Fall "besser", weder codetechnisch, noch speicher-/leistungsmäßig.
Wenn du schon unbedingt tausende von Textfeldern verwenden willst, verwalte sie nicht alle einzeln, sondern in einem Array oder ein Map, greife per Index/Key darauf zu.
Wo hast du das denn gelesen?
Ein Table beinhaltet keine Textfelder, sie ist eine Kombination aus Daten, Renderer und Editor.
Die Daten selbst sind Strings oder Boolean oder Double oder was auch immer.
Der Renderer liefert an die Grafikengine dann ein Label mit der Darstellung eines Feldes (man kann natürlich jede Komponente dafür nutzen). Die Tabelle wird pro Zelle gerendert, nach dem Aufruf der Methode des Renderers wird die Grafik des Labels in das Display oder den Buffer kopiert, anschließend wird das SELBE Label für die nächste Zelle verwendet. Eine Änderung des Labels nach dem Rendern verändert die angezeigte Grafik nicht.
Wird eine Zelle editiert, so holt sich Java die Editor-Komponente (default ist für die meisten Datentypen ein Textfield), zeigt sie an. Sobald die Änderung bestätigt wird, wird der Wert des Editors in das TableModel übertragen (bei Abbruch des Editierens natürlich nicht), die Zelle mit dem Renderer neu gerendert. Das Textfield ist ab jetzt unsichtbar und wird beim nächsten Mal befüllt und verwendet, wenn eine Zelle editiert werden soll.
Edit:
Der DefaultTableCellRenderer ist sogar selbst das entsprechende Label und liefert sich beim Aufruf von getTableCellRendererComponent(...) jeweils selbst, verändert vorher seinen Inhalt und Formatierung.
Es wäre unglaubliche Resourcenverschwendung, bei einer Tabelle Tausenden von Einträgen jeweils ein JTextfield zu hinterlegen.
In meinen frühen Tagen hab ich für einen JList-Renderer pro Element ein Label erzeugen lassen, Java ging schon bei unter 1000 in die Knie (ok, das war vor knapp 20 Jahren, Speicherüberlauf gibt es aber auch heute noch) und das war eine einfache Liste, von der nur 20 Elemente gleichzeitig angezeigt wurden (noch ein Grund, warum nicht jedes Element eine eigene Komponente braucht, wenn's eh nicht sichtbar ist).
Ich bin grad von dem JavaFX (und afaik Android-Weg) ausgegangen, da werden genügend Zellen für den sichtbaren Bereich erstellt, die dann wieder benutzt werden.
Ist's DefaultTabelCellRenderer, der das so macht? TabelCellRenderer macht dazu ja keine Angaben, mit dem kann man das Problemlos auch über einzelne Zellen lösen...
Das ist die Default-Implementierung in AWT und Swing, ja.
Da der TableCellRender nur ein Interface ist, kann das freilich jeder implementieren,wie er will. Ich schreib immer wieder Renderer und Editoren und hab noch keinen Grund dafür gefunden, nicht nach einem ähnlichen Schema vorzugehen. Da jeweils nur ein Feld gleichzeitig editiert werden kann, braucht es auch nur eine Instanz des Editors, egal wie viele Zeilen man hat.
Letztens hatte ich es mal mit einer etwas komplexeren Tabelle zu tun.
Spalte 0 hat nur in der ersten Zeile einen Wert, während alle anderen Zeilen in Zeile 0 Steuerelemente haben.
Mein Renderer liefert für Zelle(0,0) also ein JLabel, der Editor eine Kombobox. Für alle anderen Zellen der Spalte 0 wird ein Panel geliefert mit den Buttons. Dieses allerdings existiert nur ein einziges Mal, egal, wie viele Zeilen ich verwende.
Spalte x verwendet für Rendering und Editing einen Button, welcher dann abhänig vom Wert der gleichen Zeile in Spalte x-1 einen jeweils anderen Dialog öffnet.
Man hat da also einige Freiheiten.
Wie gehen JavaFX und Android denn vor, wenn andere Datentypen (z.B. Dimension, Color oder ähnliches) verwendet werden? Ich hab mich zu dem Thema noch nicht schlau gemacht.
Wie gehen JavaFX und Android denn vor, wenn andere Datentypen (z.B. Dimension, Color oder ähnliches) verwendet werden? Ich hab mich zu dem Thema noch nicht schlau gemacht.
Standardmäßig toString
Man kann eine CellValueFactory angeben, die bekommt im wesentlichen die Zeile, und gibt das anzuzeigende zurück - wenn das ein Node ist, wird der angezeigt, ansonsten mit toString.
Oder zusätzliche eine CellFactory, die gibt jeweils eine Zelle zurück und kann deren Content setzen.
Für Farben ginge zB einfach n farbiges Feld, für Dimension könnte man das grafisch Darstellen, oder als Text oder wie auch immer man möchte
Spalte 0 hat nur in der ersten Zeile einen Wert, während alle anderen Zeilen in Zeile 0 Steuerelemente haben.
Mein Renderer liefert für Zelle(0,0) also ein JLabel, der Editor eine Kombobox. Für alle anderen Zellen der Spalte 0 wird ein Panel geliefert mit den Buttons. Dieses allerdings existiert nur ein einziges Mal, egal, wie viele Zeilen ich verwende.
Spalte x verwendet für Rendering und Editing einen Button, welcher dann abhänig vom Wert der gleichen Zeile in Spalte x-1 einen jeweils anderen Dialog öffnet.
Man hat da also einige Freiheiten.