Hallo
Ich dachte eigentlich, dass ich mich besser mit Java auskenne aber mein aktuelles "Projekt" belehrte mich eines besseren. Zugegeben, habe mich nie intensiv mit GUIs beschäftigt und brauchte es bisher auch nicht. Programmiere jetzt seit ca 5 Jahren mit Java und habe dafür fast ausschließlich die Konsole als I/O verwendet. Erst im ersten Semester Informatik Studium habe ich erste Berührungen mit der GUI gemacht. Nun gut zu meiner Frage:
Habe ein JFrame in dem befindet sich der Einfachheit halber ein JButton und ein JTextPane.
[Java]
package gui;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class TestFrame extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private TestPane tp = new TestPane();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestFrame frame = new TestFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public TestFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
init();
}
private void init() {
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//contentPane.remove(1);
tp.doSmth("test");
//contentPane.updateUI();
}
});
contentPane.add(btnNewButton, BorderLayout.SOUTH);
contentPane.add(new TestPane(), BorderLayout.CENTER);
//contentPane.add(new TestPane(), BorderLayout.CENTER, 1);
}
}
[/Java]
Nun möchte ich, wie sicherlich erkennbar, per Knopfdruck das JTextPane entfernen und ein anderes darstellen lassen.
Hier dazu die Klasse:
[Java]
package gui;
import javax.swing.JPanel;
import javax.swing.JTextPane;
public class TestPane extends JPanel {
private static final long serialVersionUID = 1L;
public TestPane() {
initA();
}
private void initA() {
JTextPane txtPaneA = new JTextPane();
txtPaneA.setText("bla bla bla");
add(txtPaneA);
}
private void initB() {
removeAll();
JTextPane txtPaneB = new JTextPane();
txtPaneB.setText("test test test test");
add(txtPaneB);
updateUI();
}
public void doSmth(String str) {
switch (str) {
case "test" :
initB();
break;
default:
break;
}
}
}
[/Java]
Eigentlich eine ganz simple Sache, dachte ich jedenfals. Nun sitze ich seit 3 Tagen und bekomme es einfach nicht hin. Google und andere Foren sagen mir dauernd die magischen Wörter:" du musst das Frame neu painten". Mit "validate(), revalidate(), repaint(g), updateUI(), pack()" und haste nicht gesehen, funktioniert es nicht.
Ich habe sogar einen eigenen Lösungsansatz für die Problematik und denke sogar inzwischen verstanden zu haben, wieso es nicht geht. Meine Lösung (oder doch nur ein Workaround?) für das Problem ist, dass ich, wie am auskommentierten Teil zu erkennen, die Textfelder direkt in der TestFrame.class per [c]contentPane.add(new TestPane(), ..., ...)[/c] setze und auch entferne. Eigentlich möchte ich das aber gar nicht, da ich dann von vornherein alles in einer Klasse lassen kann, da ich momentan nicht weiß, wie ich dann das zweite TextPane setzen kann. Es befindet sich ja nur theoretisch in der TestPane.class. Praktisch wird es erst durch die doSmth methode aufgerufen. Meine Lösungsidee wäre hierfür mittels return das TextPane übergeben lassen, aber das habe ich bisher nicht testen können, da mir das gerade eben erst eingefallen ist und jetzt keine Zeit habe es zu probieren. Auch habe ich das bisher noch nicht gemacht. Am liebsten wäre mir jedoch "meine" Methode, mittels alleiniger Veränderung in dem JPanel von TestPane.
Meine Gedanken warum es so nicht geht:
Ich vermute, da GUI Komponente in der Regel statisch sind, dass sich das Fenster den Button + txtPaneA holt und diese auch korrekt darstellt. Nun wird mittels switch-case das JPanel von TestPane gelöscht und mit txtPaneB ersetzt und vermutlich auch mit updateUI(); neu gerendert, aber das JFrame selbst erfährt von der Veränderung nichts. Allerdings kann ich nicht sagen, warum dann ein Aufruf von contentPane.validate(); bzw. revalidate(); im JFrame die Sache nicht behebt...
Das Minimalbeispiel oben muss laufen, natürlich mit angepasster package Info.
Zu meinem OS:
Ubuntu 12.04, Java7 und Eclipse Indigo
Ich hoffe mir kann jemand etwas Erläuchtung schenken.
Ich dachte eigentlich, dass ich mich besser mit Java auskenne aber mein aktuelles "Projekt" belehrte mich eines besseren. Zugegeben, habe mich nie intensiv mit GUIs beschäftigt und brauchte es bisher auch nicht. Programmiere jetzt seit ca 5 Jahren mit Java und habe dafür fast ausschließlich die Konsole als I/O verwendet. Erst im ersten Semester Informatik Studium habe ich erste Berührungen mit der GUI gemacht. Nun gut zu meiner Frage:
Habe ein JFrame in dem befindet sich der Einfachheit halber ein JButton und ein JTextPane.
[Java]
package gui;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class TestFrame extends JFrame {
private static final long serialVersionUID = 1L;
private JPanel contentPane;
private TestPane tp = new TestPane();
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestFrame frame = new TestFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public TestFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
init();
}
private void init() {
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//contentPane.remove(1);
tp.doSmth("test");
//contentPane.updateUI();
}
});
contentPane.add(btnNewButton, BorderLayout.SOUTH);
contentPane.add(new TestPane(), BorderLayout.CENTER);
//contentPane.add(new TestPane(), BorderLayout.CENTER, 1);
}
}
[/Java]
Nun möchte ich, wie sicherlich erkennbar, per Knopfdruck das JTextPane entfernen und ein anderes darstellen lassen.
Hier dazu die Klasse:
[Java]
package gui;
import javax.swing.JPanel;
import javax.swing.JTextPane;
public class TestPane extends JPanel {
private static final long serialVersionUID = 1L;
public TestPane() {
initA();
}
private void initA() {
JTextPane txtPaneA = new JTextPane();
txtPaneA.setText("bla bla bla");
add(txtPaneA);
}
private void initB() {
removeAll();
JTextPane txtPaneB = new JTextPane();
txtPaneB.setText("test test test test");
add(txtPaneB);
updateUI();
}
public void doSmth(String str) {
switch (str) {
case "test" :
initB();
break;
default:
break;
}
}
}
[/Java]
Eigentlich eine ganz simple Sache, dachte ich jedenfals. Nun sitze ich seit 3 Tagen und bekomme es einfach nicht hin. Google und andere Foren sagen mir dauernd die magischen Wörter:" du musst das Frame neu painten". Mit "validate(), revalidate(), repaint(g), updateUI(), pack()" und haste nicht gesehen, funktioniert es nicht.
Ich habe sogar einen eigenen Lösungsansatz für die Problematik und denke sogar inzwischen verstanden zu haben, wieso es nicht geht. Meine Lösung (oder doch nur ein Workaround?) für das Problem ist, dass ich, wie am auskommentierten Teil zu erkennen, die Textfelder direkt in der TestFrame.class per [c]contentPane.add(new TestPane(), ..., ...)[/c] setze und auch entferne. Eigentlich möchte ich das aber gar nicht, da ich dann von vornherein alles in einer Klasse lassen kann, da ich momentan nicht weiß, wie ich dann das zweite TextPane setzen kann. Es befindet sich ja nur theoretisch in der TestPane.class. Praktisch wird es erst durch die doSmth methode aufgerufen. Meine Lösungsidee wäre hierfür mittels return das TextPane übergeben lassen, aber das habe ich bisher nicht testen können, da mir das gerade eben erst eingefallen ist und jetzt keine Zeit habe es zu probieren. Auch habe ich das bisher noch nicht gemacht. Am liebsten wäre mir jedoch "meine" Methode, mittels alleiniger Veränderung in dem JPanel von TestPane.
Meine Gedanken warum es so nicht geht:
Ich vermute, da GUI Komponente in der Regel statisch sind, dass sich das Fenster den Button + txtPaneA holt und diese auch korrekt darstellt. Nun wird mittels switch-case das JPanel von TestPane gelöscht und mit txtPaneB ersetzt und vermutlich auch mit updateUI(); neu gerendert, aber das JFrame selbst erfährt von der Veränderung nichts. Allerdings kann ich nicht sagen, warum dann ein Aufruf von contentPane.validate(); bzw. revalidate(); im JFrame die Sache nicht behebt...
Das Minimalbeispiel oben muss laufen, natürlich mit angepasster package Info.
Zu meinem OS:
Ubuntu 12.04, Java7 und Eclipse Indigo
Ich hoffe mir kann jemand etwas Erläuchtung schenken.