BackgroundColor aktualisieren

Guten Tag liebes Byte-Welt-Forum,

Ich habe ein Problem ich habe 2 (eigentlich sogar mehr) Dateien die eine davon ist ein JPanel und hat eine Hintergrundfarbe bekommen die es aus der 2ten Datei bezieht.
Die 2te Datei ist eine Klasse die eine statische Methode namens ‘read()’ besitzt die statischen Variablen vom Typ Color die Werte aus einer Datei herraus zuweist.

Folgendes Problem wenn ich das Program starte bezieht die erste Datei (Das JPanel) die Farbe aus der 2ten Datei wie gewollt.
Doch wenn ich jetzt nachträglich über einen Knopf die Datei neu einlese ändert sich nichts.
Wenn ich dann eine Ausgabe mache werden aber die geänderten Werte ausgegeben.
Ich dachte es liegt vllt. an repaint() oder revailidate(), doch das war anscheinend nicht das Problem.
Rufe ich allerdings update() verrutscht das gesamte Program nach unten (also alles wird so 50px nach unten gedrückt).

[Randbemerkung] 2te Datei ist komplett statisch und 1te nicht

Die Frage ist halt nur wie bekomme ich es hin das er die Änderrung wahrnimmt.

Mit freundlichem Gruß,
MrSmile07

bei der Initialisierung wird die Color sicher nur einmalig übernommen,
die GUI interessiert sich nicht dafür ob irgendwo eine statische Variable besteht oder es ein Zufallswert war oder wer weiß was,
da gibt es keine feste Verbindung, sondern es wurde nur der aktuelle Wert übertragen

vergleichbar Parameterübergabe Call by Value, falls dir das Thema was sagt
Java: Call-by-Value oder Call-by-Reference?
bzw. simpel

int x = 45;
array** = x;

// x neuen Wert zuweisen, Array schnuppe

auch für Objekte != primitive Datentypen gilt:
wenn einer Variablen ein neuer Wert zugewiesen wird, dann muss das alle Verwender des vorherigen Wertes nicht interessieren


nötig ist wohl, nach dem Einlesen wieder manuell in der GUI etwas zu ändern,
eine statische Klasse kann das alleine nicht,
aber nach Auslösen der Aktion (GUI-Button?) könnte der ActionListener mit Zugriff auf GUI als auch statische Klasse das machen,

theoretisch wäre denkbar, bei der statischen Klasse eine Callback-Aktion zu hinterlassen, die von der GUI weiß,
von der GUI am Anfang dort abgelegt, und die dann in der statischen Klasse aufgerufen wird, aber so exotisch muss es ja nicht werden


das hat wohl mit der aktuellen Frage nichts zu tun, allgemeine Schwierigkeiten von Swing…


auf eher unsinnige Bemerkungen im Thread-Titel wie hier ‚[Bitte erst lesen]‘ bitte besser verzichten

Ich mag gerne KSKBs, wo man sich das Problem ansehen und ausprobieren kann lieber, als teils abstrakte Texte, in die man sich erst hinein denken und hoffen muss, dass der Fragesteller weiß, wovon er schreibt.

[quote=SlaterB]bei der Initialisierung wird die Color sicher nur einmalig übernommen,
die GUI interessiert sich nicht dafür ob irgendwo eine statische Variable besteht oder es ein Zufallswert war oder wer weiß was,
da gibt es keine feste Verbindung, sondern es wurde nur der aktuelle Wert übertragen[/quote]

Ja das habe ich auch gemerkt.^^

[quote=SlaterB;140207]vergleichbar Parameterübergabe Call by Value, falls dir das Thema was sagt
Java: Call-by-Value oder Call-by-Reference?
bzw. simpel
Java Code:

int x = 45;
array** = x;
 
// x neuen Wert zuweisen, Array schnuppe

auch für Objekte != primitive Datentypen gilt:
wenn einer Variablen ein neuer Wert zugewiesen wird, dann muss das alle Verwender des vorherigen Wertes nicht interessieren[/quote]

Habe ich mir durchgelesen aber nicht genau verstanden was das nun wirklich meint.

[quote=SlaterB;140207]nötig ist wohl, nach dem Einlesen wieder manuell in der GUI etwas zu ändern,
eine statische Klasse kann das alleine nicht,
aber nach Auslösen der Aktion (GUI-Button?) könnte der ActionListener mit Zugriff auf GUI als auch statische Klasse das machen,

theoretisch wäre denkbar, bei der statischen Klasse eine Callback-Aktion zu hinterlassen, die von der GUI weiß,
von der GUI am Anfang dort abgelegt, und die dann in der statischen Klasse aufgerufen wird, aber so exotisch muss es ja nicht werden[/quote]

Ein JButton ruft den Aufruf alles neu einzulesen und dann die Werte neu zu setzen.

Hatte ich nur hinzugefügt um zu erläutern, das ich weiß wie man sie ändert nur das es ein spezielles Problem habe.^^
Nicht das jemand einfach ‚das geht mit panel.setBackground()‘ schreibt.

Mit freundlichem Gruß,
MrSmile07

*** Edit ***

Oh L-ectron-X habe grade erst beim verfassen die Nachricht gelesen.

Grober Quelltext
Datei 1 (Das zu ändernde Panel)

public class Options extends JPanel{
	
	private static final long serialVersionUID = 1L;
	
	private Color optionscolor = ReadSkin.optionscolor;
	
	public Options(final Main m) {
		setBackground(new Color(optionscolor.getRed(), optionscolor.getGreen(), optionscolor.getBlue(), 200));
	}
}

Datei 2 (Der Reader)

import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;


public class ReadSkin {
	
	private static String line[] = new String[10];
	
	public static Color optionscolor = Color.BLACK;
	public static Color browserpanelcolor = Color.BLACK;
	public static Color imagepanelcolor = Color.BLACK;
	public static Color menubarcolor = Color.BLACK;
	public static Color sidemenucolor = Color.BLACK;
	public static Color settingspanelcolor = Color.BLACK;
	public static Color manualpanelcolor = Color.BLACK;
	public static Color aboutpanelcolor = Color.BLACK;
	public static Color scrollbarColor = Color.WHITE;
	public static Color knobColor = Color.BLACK;
	
	static BufferedReader b;
	
	static int cline = 0;
	
	public static void read(){
		try {
			b = new BufferedReader(new FileReader(new File(System.getProperty("user.home") +"/LeafView/skins/" + ReadSettings.skin + ".skin")));
			while((line[cline] = b.readLine()) != null){
				if(line[cline].contains("ContextMenu ")){
					String[] arr = (line[cline].replace("ContextMenu ", "")).split(", ");
					optionscolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("Browser ")){
					String[] arr = (line[cline].replace("Browser ", "")).split(", ");
					browserpanelcolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("ImageList ")){
					String[] arr = (line[cline].replace("ImageList ", "")).split(", ");
					imagepanelcolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("TitleBar ")){
					String[] arr = (line[cline].replace("TitleBar ", "")).split(", ");
					menubarcolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("SideMenu ")){
					String[] arr = (line[cline].replace("SideMenu ", "")).split(", ");
					sidemenucolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("Settings ")){
					String[] arr = (line[cline].replace("Settings ", "")).split(", ");
					settingspanelcolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("Manual ")){
					String[] arr = (line[cline].replace("Manual ", "")).split(", ");
					manualpanelcolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("About ")){
					String[] arr = (line[cline].replace("About ", "")).split(", ");
					aboutpanelcolor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("Scrollbar ")){
					String[] arr = (line[cline].replace("Scrollbar ", "")).split(", ");
					scrollbarColor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else if(line[cline].contains("Knob ")){
					String[] arr = (line[cline].replace("Knob ", "")).split(", ");
					knobColor = new Color(Integer.parseInt(arr[0]),Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
				}else{
					cline++;
				}
  	  		}
        	b.close();
        	cline = 0;
        } catch (IOException e) {
			//e.printStackTrace();
		}
	}
}

Codewüsten zu vermeiden ist sehr wichtig,
brauchst du eigentlich ein 10er-Array für die Zeilen der Datei, zumal statisch gemerkt?

jedenfalls ginge etwa

  String l = line[cline]; // vielleicht zu kurz, aber line schon vergeben
  if(l.contains("ContextMenu ")){
       optionscolor = parse(l,"ContextMenu ");
  }else if(l.contains("Browser ")){
       browserpanelcolor = parse(l,"Browser ");
  }
usw.

mit einer Untermethode, die den Zerlegecode enthält


wie gesagt, ist wahrscheinlich der (nicht gepostete) ActionListener die richtige Adresse,
nach dem read() dort die Komponente aus der GUI holen, was natürlich nur geht wenn als Attribut irgendwo gemerkt (in Main etwa),
Background setzen, repaint() usw. mag helfen


Attribut optionscolor in Options-Klasse kann wiederum weg, bringt nichts,
Zugriff auf ReadSkin.optionscolor geht im Konstruktor auch so, bzw. wenn für Kurzschreibweise, dann reicht lokale Variable,

        Color oc = ReadSkin.optionscolor;
        setBackground(new Color(oc.getRed(), oc.getGreen(), oc.getBlue(), 200));
    }

diese zwei Zeilen bestimmt aus Konstruktor raus in eine Methode, welche im Konstruktur und dann auch später von ActionListener aufgerufen werden kann

manuell optionscolor in Options zu setzen wäre genausowenig Lösung wie optionscolor in ReadSkin zu setzen,
es muss schon ein setBackground()-Aufruf neu ausgeführt werden

[quote=SlaterB]Codewüsten zu vermeiden ist sehr wichtig,
brauchst du eigentlich ein 10er-Array für die Zeilen der Datei, zumal statisch gemerkt?[/quote]

Ja wollte das noch komprimieren.^^ Und nein die 10 Zeilen Grenze ist nicht notwendig habe sie aber trotzdem eingebaut.

[quote=SlaterB;140214]wie gesagt, ist wahrscheinlich der (nicht gepostete) ActionListener die richtige Adresse,
nach dem read() dort die Komponente aus der GUI holen, was natürlich nur geht wenn als Attribut irgendwo gemerkt (in Main etwa),
Background setzen, repaint() usw. mag helfen[/quote]

In Klasse SettingsPanel

b1.addMouseListener(new MouseListener(){
			@Override
			public void mouseClicked(MouseEvent e) {		
				new ChangeSetting(t1.getText(), "path");
				new ChangeSetting(t2.getText(), "skin");
				new ChangeSetting(t3.getText(), "fullscreenmode");
				for(Iterator<File> it8 = IgnorePanel.reig.iterator();it8.hasNext();){
		    		it8.next().delete();
		    	}
				ReadSettings.read();
				ReadSkin.read();
//				Main.frm.repaint();
//				Main.frm.revalidate();
//				MenuBar.restart();
//				System.out.println(ReadSettings.skin);
//				Main.frm.dispose();
//				new Main(new Filelocater());
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				b1.setBackground(Version.progColor);
				b1.setForeground(settingspanelcolor);
			}

			@Override
			public void mouseExited(MouseEvent e) {
				b1.setBackground(settingspanelcolor);
				b1.setForeground(Version.progColor);
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseReleased(MouseEvent e) {
			}
		});

Mit freundlichem Gruß,
MrSmile07

(EDIT: Hä, sorry, da war ich entweder zu langsam, oder hätte vor dem Antworten nochmal neu laden sollen. SlaterB hat das wohl schon so ähnlich geschrieben)

Der Code aus dem Reader ist grauslig. Hoffentlich nur ein suggestives Beispiel. Ansonsten scheint (ohne alles im Detail gelesen zu haben) das zuzutreffen, was SlaterB schon angedeutet hat:

public class Options extends JPanel{
   
    private static final long serialVersionUID = 1L;
   
    private Color optionscolor = ReadSkin.optionscolor;
   
    public Options(final Main m) {
        setBackground(new Color(optionscolor.getRed(), optionscolor.getGreen(), optionscolor.getBlue(), 200));
    }
}

Hier wird die optionscolor EINMAL initialisiert, mit dem Wert, den ReadSkin.optionscolor zu diesem Zeitpunkt hat. Wenn sich (durch einen Aufruf von read()) das ReadSkin.optionscolor später ändert, kriegt dieses optionscolor hier nichts davon mit. Das behält den wert, den es Anfangs hatte.

Es würde vielleicht schon ““funktionieren””, wenn man das optionscolor hier entfernen, und die Aktualisierung dann im Stil von


public void updateColorAfterReadHasBeenCalled()
{
    // Hole dir die Farbe, die "optionscolor" IN DER ReadSkin-KLASSE (!)
    // jetzt, nach dem Lesen, hat:
    Color c = ReadSkin.optionscolor;
    setBackground(new Color(c.getRed(), c.getGreen(), c.getBlue(), 200));
}

Aber nochmal: “Schön” ist was anderes. Das ganze static und hin-und-herreichen von Farben sieht HÖCHST suspekt aus. Jedes “public static” (ohne “final”) ist ein globaler, veränderbarer Zustand, und das führt früher oder später zu Problemen und in eine Wartungs-Hölle.

Beschreib’ vielleicht nochmal genauer, “abstrakter” und allgemeiner, was das Programm machen soll, dann kann man sicher geeignetere Lösungsansätze skizzieren.

[quote=Marco13]Es würde vielleicht schon „„funktionieren““, wenn man das optionscolor hier entfernen, und die Aktualisierung dann im Stil von
Java Code:

public void updateColorAfterReadHasBeenCalled()
{
    // Hole dir die Farbe, die "optionscolor" IN DER ReadSkin-KLASSE (!)
    // jetzt, nach dem Lesen, hat:
    Color c = ReadSkin.optionscolor;
    setBackground(new Color(c.getRed(), c.getGreen(), c.getBlue(), 200));
}[/quote]

Würde nicht funktionieren da der Reader Static ist und somit die Methode auch static seien müsste was .setBackground nicht unterstützt.

Ich benutze ja nur static für Werte die sich eigentlich fast nie ändern und immer leicht erreichbar seien sollen.
[Habe schon gelesen das man nicht soviel mit static arbeiten soll]

Ich arbeite an einem Bilder Program und da soll man Skins auswählen können.
Funktioniert auch beim neustarten, nur es wäre doof jedes mal das Program dann neustarten zu müssen.

Mit freundlichem Gruß,
MrSmile07

Diese angedeutete “updateColorAfterReadHasBeenCalled”-Methode müßte natürlich von dort aufgerufen werden, wo auch “read()” aufgerufen wird. Also nicht aus einem static-Kontext, sondern dort, wo die Instanz liegt:

private Options options = ...;

void someUpdateButtonWasPressed()
{
    ReadSkin.read();
    options.updateColorAfterReadHasBeenCalled();
}

(DASS das nicht schön ist, wird vielleicht schon daran ersichtlich).

In meiner Main Methode sind die gesamten Objekte erzeugt worden…
Das heißt also ich muss alles aus der Main übernehmen…
Mh…
Ich schaue mal grade.

Mit freundlichem Gruß,
MrSmile07

*** Edit ***

Die Main habe ich auch der Klasse mit dem ActionListener übergeben…
Moment probiere noch was

*** Edit ***

Ok, habe es ausprobiert,
Ich habe das jetzt so geschrieben aber es hilft nicht.

Aus der Main

	public MenuBar menuBarPanel = new MenuBar(this);
	public SideMenu sideMenuPanel = new SideMenu(this);
	public ManualPanel manualPanel = new ManualPanel(this);
	public AboutPanel aboutPanel = new AboutPanel(this);
	public SettingsPanel settingsPanel;
	public PowerUpsPanel powerUpsPanel;
	
	private Component lastVisited;
	
	public boolean somethingOpen;

	public Main(final Filelocater fl) {	
		settingsPanel = new SettingsPanel(this, fl);
		powerUpsPanel = new PowerUpsPanel(this, fl);
		
        SwingUtilities.invokeLater(new Runnable() {
            public void run(){
            	createFrame(fl);
            }
        });
	}

Aus der Settings Datei mit dem ActionListener [Main wird übergeben oben im Quelltext]

b1.addMouseListener(new MouseListener(){
			@Override
			public void mouseClicked(MouseEvent e) {
				new ChangeSetting(t1.getText(), "path");
				new ChangeSetting(t2.getText(), "skin");
				new ChangeSetting(t3.getText(), "fullscreenmode");
				for(Iterator<File> it8 = IgnorePanel.reig.iterator();it8.hasNext();){
		    		it8.next().delete();
		    	}
				
				ReadSettings.read();
				ReadSkin.read();
				
				m.aboutPanel.updateBackgroundColor();
				
//				Main.frm.repaint();
//				Main.frm.revalidate();
//				MenuBar.restart();
//				System.out.println(ReadSettings.skin);
//				Main.frm.dispose();
//				new Main(new Filelocater());
			}

			@Override
			public void mouseEntered(MouseEvent e) {
				b1.setBackground(Version.progColor);
				b1.setForeground(settingspanelcolor);
			}

			@Override
			public void mouseExited(MouseEvent e) {
				b1.setBackground(settingspanelcolor);
				b1.setForeground(Version.progColor);
			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseReleased(MouseEvent e) {
			}
		});

Und aus der Panel Datei About (Options hat einen komplett anderen Aufruf deswegen nehme ich jetzt die About Datei)

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.JEditorPane;
import javax.swing.JPanel;

public class AboutPanel extends JPanel{

	private static final long serialVersionUID = 1L;
		
	private JEditorPane t1 = new JEditorPane();
	
	private Color aboutpanelcolor = ReadSkin.aboutpanelcolor;
	
	public AboutPanel(final Main m) {
		setBackground(aboutpanelcolor);
		setLayout(new BorderLayout());
		t1.setEditable(false);
		t1.setBackground(aboutpanelcolor);
		t1.setForeground(Color.GREEN);
		t1.setText(Version.name + "
" + Version.right + "
Version " + Version.devNr+ "
" + Version.joke);
		t1.setFont(new Font("Arial", Font.PLAIN, 24));
		add(t1, BorderLayout.CENTER);
		addKeyListener(new KeyAdapter(){
			@Override
			public void keyPressed(KeyEvent arg0) {
				if(arg0.getKeyCode() == KeyEvent.VK_CONTROL){
					m.hideElement();
				}
			}
		});
	}
	
	public void updateBackgroundColor() {
	    Color c = ReadSkin.aboutpanelcolor;
	    setBackground(c);
	    repaint();
	    revalidate();
	}
}

Finde das Problem nur nicht… mhh…

Mit freundlichem Gruß,
MrSmile07

jetzt habe ich das ganze Programm zu lauffähig gebaut, was du dir eingespart hast…,
um dann erst zu sehen dass du auch dem JEditorPane die BackgroundColor gibst, in der Untermethode aber nicht…

daran nicht selber gedacht? für andere schwer, da nie hier erwähnt, was dann freilich auch dafür spricht dass nicht selber dran gedacht…


wie gesagt sowieso im Konstruktor auch die Untermethode fürs Color-Setzen aufrufen statt auf andere Weise zu setzen,
einheitlicher und das aktuelle Problem hätte es dann so auch nicht gegeben,
siehe mein Test-Konstrukt:

Code, nicht tot
[spoiler]

{
    public static void main(String[] args)
    {
        new Main();
    }
}


class Main
{

    public AboutPanel aboutPanel = new AboutPanel(this);
    public SettingsPanel settingsPanel;

    public Main()
    {
        settingsPanel = new SettingsPanel(this);
        SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    createFrame();
                }
            });
    }

    void createFrame()
    {
        JFrame f = new JFrame();
        f.add(BorderLayout.NORTH, settingsPanel);
        f.add(BorderLayout.CENTER, aboutPanel);

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(400, 400);
        f.setVisible(true);
    }
}


class SettingsPanel
    extends JPanel
{

    public SettingsPanel(Main m)
    {
        JButton b1 = new JButton("go");
        add(b1);
        b1.addMouseListener(new MouseListener()
            {
                @Override
                public void mouseClicked(MouseEvent e)
                {
                    ReadSkin.read();

                    m.aboutPanel.updateBackgroundColor();

                    // Main.frm.repaint();
                    // Main.frm.revalidate();
                    // MenuBar.restart();
                    // System.out.println(ReadSettings.skin);
                    // Main.frm.dispose();
                    // new Main(new Filelocater());
                }

                @Override
                public void mouseEntered(MouseEvent e)
                {

                }

                @Override
                public void mouseExited(MouseEvent e)
                {

                }

                @Override
                public void mousePressed(MouseEvent e)
                {
                }

                @Override
                public void mouseReleased(MouseEvent e)
                {
                }
            });
    }
}


class AboutPanel
    extends JPanel
{

    private static final long serialVersionUID = 1L;

    private JEditorPane t1 = new JEditorPane();

    public AboutPanel(final Main m)
    {
        updateBackgroundColor();

        setLayout(new BorderLayout());
        t1.setEditable(false);
        t1.setForeground(Color.GREEN);
        t1.setText("Test");
        t1.setFont(new Font("Arial", Font.PLAIN, 24));
        add(t1, BorderLayout.CENTER);

    }

    public void updateBackgroundColor()
    {
        Color c = ReadSkin.aboutpanelcolor;
        setBackground(c);
        t1.setBackground(c);
        repaint();
    }
}


class ReadSkin
{
    static Color aboutpanelcolor = Color.YELLOW;

    static void read()
    {
        aboutpanelcolor = Color.LIGHT_GRAY;
    }
}
```[/spoiler]

Oh… Da war der Fehler… :wut:
Der ist ja echt doof, ok es funktioniert jetzt danke.
Habe heute irgendwie das Brett vor dem Kopf gehabt.^^

Noch einmal herzlichen dank für das extra Zeit nehmen.
Wie gesagt es funktioniert jetzt, setzte es damit auf gelöst.

Mit freundlichem Gruß,
MrSmile07

EDIT: Notiz an mich: IMMER erst „reload“ drücken - der Trubel hier im Forum wird langsam zu groß :wink:

Anhand dieser Fetzen ist es schwer, das Problem einzugrenzen oder gar zu benennen. Ein bißchen Remote-Debugging:

public void updateBackgroundColor() {
    Color c = ReadSkin.aboutpanelcolor;

    System.out.println("Update, setting color "+c);

    setBackground(c);
}

Wird da was ausgegeben? Wenn ja, was? (Das richtige?)

Ja wird es.^^

gelöst

Vielleicht sollte noch mal erwähnt werden, dass für Buttons normalerweise [japi]ActionListener[/japi] und nicht [japi]MouseListener[/japi] vorgesehen sind.

hatte ich zwischendurch vergessen,
aber auch leicht entschärft dadurch, dass hier auch mouseEntered/ mouseExited genutzt wird

Ja hat design Gründe.^^

Mit feundlichem Gruß,
MrSmile07