private Panel anderer Klasse verändern

coree

Mitglied
Hallo,
ich stehe gerade vor dem folgenden Problem.
Ich bin gerade dabei aus meiner Gui-Klasse einzelne Elemente in eigenen Klassen auszulagen.
Nun probiere ich dies zunächst mit Test-Klassen. Jetzt habe ich dabei das Problem, dass ich aus der einen Klasse zum Beispiel die Hintergrundfarbe eines anderen Panels, welches in einer anderen Klasse ist, verändern möchte.

1. Hauptklasse
Java:
public class MenuLayoutDemo extends JFrame {

    protected final JPanel programPanel; // UM DIESES PANEL GEHT ES
    
    public static void main(final String[] args) {
        new MenuLayoutDemo();
    }
    MenuLayoutDemo() {
    super("MusicBuddies v.1");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    final GraphicsEnvironment env = GraphicsEnvironment
            .getLocalGraphicsEnvironment();
    final Rectangle maxBounds = env.getMaximumWindowBounds();

    final Container content = getContentPane();
    content.setPreferredSize(new Dimension(maxBounds.width,
            maxBounds.height));
    content.setBackground(new Color(34, 34, 34));

    final GroupLayout guiLayout = new GroupLayout(content);
    content.setLayout(guiLayout);

    final MenuPanel menuPanel = new MenuPanel(this);
    programPanel = new JPanel();
    programPanel.setBackground(Color.red);

    guiLayout.setHorizontalGroup(guiLayout.createSequentialGroup()
      .addGroup(guiLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
         .addGroup(guiLayout.createSequentialGroup()
              .addComponent(menuPanel, GroupLayout.PREFERRED_SIZE,
                 GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
              .addComponent(programPanel)))
    );
    guiLayout.setVerticalGroup(guiLayout.createSequentialGroup()
        .addGroup(guiLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
           .addComponent(menuPanel)
           .addComponent(programPanel))
    );

    pack();
    setVisible(true);
    }
}

2. Panelklasse
Java:
public class MenuPanel extends JPanel {

    private final MenuLayoutDemo ml;
    private JButton sammlungButton;

    public MenuPanel(final MenuLayoutDemo ml) {
        super(new GridBagLayout());
        this.ml = ml;
        this.setBackground(new Color(34, 34, 34));

        final GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
        final Rectangle maxBounds = env.getMaximumWindowBounds();

        final GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;

        sammlungButton = new JButton(new ImageIcon(getClass().getResource("images/mb_button_musiksammlung_active.jpg")));
        sammlungButton.setFocusPainted(false);
        sammlungButton.setPreferredSize(new Dimension(200, 30));
        sammlungButton.setRolloverEnabled(false);
        sammlungButton.setBorder(null);
        sammlungButton.setContentAreaFilled(false);
        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(0, 20, 0, -78);
        sammlungButton.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent event) {
                System.out.println("Sammlung");
                ml.programPanel.setBackground(Color.black); // HIER BENÖTIGE ICH DAS PANEL
            }
        });
        this.add(sammlungButton, c);

    }
}

Indem ich das programPanel derzeit protected statt private setze umgehe ich sozusagen das Problem. Wie bekomme ich es zum laufen, dass die Variable weiterhin private bleiben kann und trotzdem alles funktioniert?
Mit getter/setter komme ich auch nicht weit.

Hoffe es kann mir jemand weiterhelfen. danke schonmal.
 

eher weil ich zu blöd dafür war 😉 aber nu klappts, danke.


nun hab ich aber noch eine weitere frage, bei der es um etwas ähnliches geht.
Ich habe nen ButtonListener, durch welchen ein Panel sich auf Knopfdruck ändern soll:
ButtonListener
Java:
class ButtonListener implements ActionListener {
    final SammlungPanel sammlungP2; // ich denk, hier muss sammlungP2 einfach nur noch das richtige zugewiesen werden, damit es klappt

    /**
     * ...
     * @param actionEvent ...
     */
    @Override
    public void actionPerformed(final ActionEvent actionEvent) {
                sammlungP2.getSammlungPanel2().removeAll();
                sammlungP2.getSammlungPanel2().add(jTree);
                sammlungP2.getSammlungPanel2().revalidate();
                sammlungP2.getSammlungPanel2().repaint();

    }
    
}
SammlungPanel mit sammlungPanel2
Java:
public class SammlungPanel extends JPanel {

    private final transient JPanel sammlungPanel2;

    public final JPanel getSammlungPanel2() {
        return sammlungPanel2;
    }

    public SammlungPanel(final MenuLayoutDemo mLayout)
            throws ClassNotFoundException, SQLException {
...
    }
}

nur kann ich hier nicht wie bei meiner ersten frage die referenz übergeben, da ich ja eine methode vom actionlistener verwende.
wie schaff ichs hier, auf die getSammlungPanel2()-Methode zugreifen zu können?
stehe im moment irgendwie auf dem schlauch... :/
 
Zuletzt bearbeitet:
[c]ButtonListener[/c] ist doch eine ganz normale Klasse..auch der kannst du einen Konstruktor einbauen der eine Referenz von einem [c]SammlungPanel[/c]-Objekt übergeben bekommt ?!
 
[c]ButtonListener[/c] ist doch eine ganz normale Klasse..auch der kannst du einen Konstruktor einbauen der eine Referenz von einem [c]SammlungPanel[/c]-Objekt übergeben bekommt ?!

das hatte ich soweit auch schon:
Java:
class ButtonListener implements ActionListener {

    final SammlungPanel sammlungP2;

    public ButtonListener(SammlungPanel sammlungP2) {
        this.sammlungP2 = sammlungP2;
    }

nur hab ichs nun nicht mehr hinbekommen, in einer anderen klasse mit
Java:
folderButton.addActionListener(new ButtonListener());
das ganze aufzurufen. muss ich dort auf wieder die sammlungpanel referenz übergeben um new ButtonListener(SammlungPanel sammlungP2); nutzen zu können? oder geht das auch auf ne andere art und weise? denn damit seh ich dann im weiteren verlauf neue probleme auf mich zu kommen.
 
nur hab ichs nun nicht mehr hinbekommen, in einer anderen klasse mit
Java:
folderButton.addActionListener(new ButtonListener());
das ganze aufzurufen. muss ich dort auf wieder die sammlungpanel referenz übergeben um new ButtonListener(SammlungPanel sammlungP2); nutzen zu können?
ja klar, du musst dann natürlich sammlungP2 übergeben ja...
oder geht das auch auf ne andere art und weise? denn damit seh ich dann im weiteren verlauf neue probleme auf mich zu kommen.

vllt stimmt ja dein "Design" dann nicht so ganz 🙂
Klar, es geht immer auch irgendwie anders, z.B. könntest du einfach alles public static oder so machen, aber ob das dann schöner ist, ist wieder eine ganz andere Sache 🙂
 
Naja das Problem kam nun doch... :/
ich post einfach ma die design struktur und die "wichtigen" stellen.
MenuLayoutDemo
Java:
public class MenuLayoutDemo extends JFrame {
    private static SammlungPanel sammlungP;
    public static void main(final String[] args)
            throws ClassNotFoundException, SQLException {
        new MenuLayoutDemo(sammlungP);
    }
    
    MenuLayoutDemo(SammlungPanel sammlungP)
            throws ClassNotFoundException, SQLException {
...
    this.sammlungP = sammlungP;
    final MenuBar menu = new MenuBar(sammlungP);
    setJMenuBar(menu.createMenuBar());
    final SammlungPanel sammlungPanel = new SammlungPanel(this);
...
   }
}
MenuBar
Java:
public class MenuBar {

    final SammlungPanel sammlungP;

    public MenuBar(SammlungPanel sammlungP) {
        this.sammlungP = sammlungP;
    }

   /**
    * Erstellt eine Menüleiste.
    * @return menuBar
    */
   public final JMenuBar createMenuBar() {
...
        menuItem.addActionListener(new Options(sammlungP));
...
    }
}
Options
Java:
class Options implements ActionListener {

    public static JTextPane folderText;

    final SammlungPanel sammlungP2;

    public Options(SammlungPanel sammlungP) {
        this.sammlungP = sammlungP;
    }
    /**
     * Einstellungsfenster.
     * @param e ActionEvent
     */
    @Override
    public void actionPerformed(final ActionEvent e) {
...
        folderButton.addActionListener(new ButtonListener(sammlungP));
...
   }
}
ButtonListener
Java:
class ButtonListener implements ActionListener {

    private final SammlungPanel sammlungP;

    public ButtonListener(SammlungPanel sammlungP) {
        this.sammlungP = sammlungP;
    }

    /**
     * ...
     * @param actionEvent ...
     */
    @Override
    public void actionPerformed(final ActionEvent actionEvent) {
...
                sammlungP.getSammlungPanel2().removeAll();
                sammlungP.getSammlungPanel2().add(jTree);
                sammlungP.getSammlungPanel2().revalidate();
                sammlungP.getSammlungPanel2().repaint();
...
    }
}
SammlungPanel
Java:
public class SammlungPanel extends JPanel {

    private final transient JPanel sammlungPanel2;

    public final JPanel getSammlungPanel2() {
        return sammlungPanel2;
    }

    public SammlungPanel(final MenuLayoutDemo mLayout)
            throws ClassNotFoundException, SQLException {
...
        sammlungPanel2 = new JPanel();
...
    }
}

als fehler bekomm ich ne NullPointerException wenn ich auf den Knopf drücke, welchem ButtonListener zugeordnet ist. also scheint meine übergabe noch nicht zu stimmen.
 
sammlungP wird nie initialisiert und ist null.
Ansonsten ist das Konstrukt mit dem Durchschleifen einer Referenz durch mehrere Klassen eher unschön.
 
wie kann ich das ganze denn schöner umsetzen?
Ist so pauschal schwer zu sagen, hängt davon ab, was genau Du vorhast. Allgemein würde ich mal das ModelViewController Pattern empfehlen.
Konkret solltest Du Dir mal die Fragestellen, ob Dein Listener sammlungP überhaupt kennen muss/sollte, oder ob er nicht besser eine Referenz auf ein Objekt von MenuLayoutDemo kennen sollte und diese Objekt auffordern entwas zu machen. MenuLayoutDemo kann dann ja intern diese "Aufforderung" weitder delegieren.

Ausserdem: Exceptions (throws ClassNotFoundException, SQLException) bis zur static main einfach durchzureichen ist für den Fall, dass solch eine Exception auftritt eher ungünstig. Dann bekommst Du ja garnicht mit wann und wieso eine Exception aufgetreten ist und Du fragst Dich irgendwann warum Deine Anwendung abschmiert. Mein Grundsatz bei Exceptions: So früh abfangen wie möglich, so weit durchreichen wie nötig.
 
hab nun erstmal getSammlungPanel2() public static und sammlungPanel2 private static gesetzt, damit gehts halt erstmal.
werd mir aber deinen vorschlag die tage auch mal genauer ansehen. danke
 

Zurück
Oben