Anzeige:
Ergebnis 1 bis 13 von 13

Thema: Hintergrundfarbe einer einfachen Komponente

  1. #1
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47

    Hintergrundfarbe einer einfachen Komponente

    Hallo zusammen!
    Ich habe eine Minimal-Komponente gebaut indem ich einfach von JComponent abgeleitet habe. Im Konstruktor habe ich mit setBackground(Color) versucht eine Farbe für die Fläche zu setzen. Geht nit. Gleiches habe ich aus einer Testanwendung heraus probiert. Geht auch nicht. Hätte ich nicht die Paint-Methode überschrieben und da einen Strich gezeichnet, würde man das Ding gar nicht sehen!

    Wie kann ich für eine eigene Komponente, die direkt von JComponent erbt, eine Hintergrundfarbe setzen???

    Danke für jegliche Inspiration!

  2. #2
    Registrierter Benutzer Avatar von mwanaheri
    Registriert seit
    28.10.2003
    Ort
    Bayreuth
    Beiträge
    569
    Poste doch mal ein Minimalbeispiel
    Das Ziel ist das Ziel.

  3. #3
    Registrierter Benutzer Avatar von Caveman
    Registriert seit
    03.11.2005
    Ort
    Geilsheim
    Beiträge
    308
    setBackground(Color) ist an sich schon richtig, man sollte nur dann darauf achten, dies nicht mit einem JPanel zu überdecken oder man gibt auch diesem eine Hintergrundfarbe.
    Auch JLabel, JList usw. überdecken den Hintergrund.
    Programmiere (wenn es denn mal wieder vorkommt) in C, C++, Java, Perl
    Bin kein Student (Elektrotechnik) mehr und habe die Seiten gewechselt von der Software weg hin zur Hardware

  4. #4
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Die kleinste Komponente der Welt:

    Code:
    public class EmptyComponent extends JComponent {
    	public EmptyComponent(){
    		super();
    		setBackground(Color.RED);
    		setPreferredSize(new Dimension(300,300));
    	}
    }
    Und eine kleine Testanwendung:
    Code:
    public class MainFrame extends JFrame{
    
    	private JScrollPane sp = null; 
    	private EmptyComponent comp = null;
    	private JSlider slider = null;
    
    	public MainFrame() {
    
    		comp = new EmptyComponent();
    		sp = new JScrollPane(comp);
    		getContentPane().add(sp, BorderLayout.CENTER);
    
    		slider = new JSlider(JSlider.HORIZONTAL,100, 800, 200);
    		getContentPane().add(slider, BorderLayout.NORTH);
    
    		pack();
    	}
    
    	public static void main(String[] args) {
    		MainFrame mainFrame = new MainFrame();
    		mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		mainFrame.setVisible(true);
    	}
    }
    Wo ist der Denkfehler?

  5. #5
    Registrierter Benutzer Avatar von Caveman
    Registriert seit
    03.11.2005
    Ort
    Geilsheim
    Beiträge
    308
    Füge in MainFrame() diese Zeile ein (aus EmptyComponent kann sie dann raus):

    Code:
    sp.setBackground(Color.RED);
    und in EmptyComponent() das:

    Code:
    setOpaque(true);
    Programmiere (wenn es denn mal wieder vorkommt) in C, C++, Java, Perl
    Bin kein Student (Elektrotechnik) mehr und habe die Seiten gewechselt von der Software weg hin zur Hardware

  6. #6
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Danke Caveman!

    Ich nun jedoch seltsame Erscheinungen beim Scrollen. "Reste" des Randes werden beim Scrollen der Komponente "mitgezogen". Ist jedoch nicht so wichtig, da diese Lösung leider nicht hinreichend für mein Problem ist. Mein Ziel ist ja nicht diese kleine Anwendung (habt ihr euch hoffentlich schon gedacht), sondern eine Komponente, die auch als solche flexibel überall eingesetzt werden soll. Und wenn der Hintergrund der Komponente rot sein soll, dann muss das die Komponent schon selbst erledigen und kann nicht den darüberliegenden Container bzw. Panel dafür heranziehen. Den sollte die Komponente gar nicht kennen müssen.

    Noch mehr Ideen?

  7. #7
    Registrierter Benutzer Avatar von Caveman
    Registriert seit
    03.11.2005
    Ort
    Geilsheim
    Beiträge
    308
    Das Problem beim Scrollen lässt sich z.B. damit beheben, dass man einen EventListener einbaut und folgende Zeile dort aufruft:
    Code:
    sp.repaint();
    Für das andere Problem habe ich gerade auch keine Idee. In der API von SUN gibt es aber ein nettes Tutorial; vielleicht hilft das weiter (hab's selbst nicht gelesen): http://java.sun.com/docs/books/tutor...crollpane.html

    Ansonsten könnte es auch damit zusammenhängen, dass die JScrollPane nur leichtgewichtig ist.
    Zitat aus der API: "Note that JScrollPane does not support heavyweight components."
    Programmiere (wenn es denn mal wieder vorkommt) in C, C++, Java, Perl
    Bin kein Student (Elektrotechnik) mehr und habe die Seiten gewechselt von der Software weg hin zur Hardware

  8. #8
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Hm, also das Problem ist von JScrollPane ja vollkommen unabhängig. Die Komponente soll prinzipiell beliebig untergebracht werden können. Es geht nur darum eine direkt von JComponent abgeleitete Komponente direkt einzufärben.
    Wegen Leichtgewichtigkeit: Meine Komponente ist ja leichtgewichtig! ist ja von JComponent abgeleitet! Wo soll da ein Problem mit Schwergewichtigkeit auftreten?

  9. #9
    Registrierter Benutzer Avatar von Caveman
    Registriert seit
    03.11.2005
    Ort
    Geilsheim
    Beiträge
    308
    Zitat Zitat von McFraggle
    Wegen Leichtgewichtigkeit: Meine Komponente ist ja leichtgewichtig! ist ja von JComponent abgeleitet! Wo soll da ein Problem mit Schwergewichtigkeit auftreten?
    Hab nicht genauer darüber nachgedacht.

    Zum eigentlichen Problem:
    Es sollen also JComponenten geschaffen werden, die selbst ihre Farbe bestimmen.
    Ich schreibe hier mal den verbesserten Code im Ganzen von EmptyComponent:
    Code:
    package test;
    
    import java.awt.*;
    import javax.swing.*;
    
    public class EmptyComponent extends JComponent
    {
        public EmptyComponent()
        {
            super();
            setBackground(Color.RED);
            setPreferredSize(new Dimension(300,300));
            setOpaque(true);
        }
    }
    Leider bewirkt die Zeile "setBackground(Color.RED);" nichts

    Mir gehen nun selbst die Ideen aus, aber vielleicht kann jemand anderes was dazu sagen. Die Lösung interessiert mich auch.
    Programmiere (wenn es denn mal wieder vorkommt) in C, C++, Java, Perl
    Bin kein Student (Elektrotechnik) mehr und habe die Seiten gewechselt von der Software weg hin zur Hardware

  10. #10
    Registrierter Benutzer Avatar von mwanaheri
    Registriert seit
    28.10.2003
    Ort
    Bayreuth
    Beiträge
    569
    Hm, ganz so einfach wird das wohl nichts. Ich zitiere mal aus "Handbuch der Java-Programmierung":

    "[...] Für die Darstellung der eigenen Komponente ist dagegen paintComponent zuständig.

    protected void paintComponent(Graphics g)

    In JComponent wird jeder Aufruf von paintComponent and das ComponentUI der Komponente delegiert. Instanzen dieser im Paket javax.swing.plaf liegenden Klasse spielen in dem von jeder Swing-Komponente implementierten Model-View-Controller-Konzept die Rolle des Views, sond also für die graphische Darstellung der Komponente zuständig. Jede Swing-Komponente besitzt ein ComponentUI, das je nach Looka-and-Feel untershiedlich sein kann. Eine selbstdefinierte Komponente muss also entweder für jedes unterstützte Look-and-Feel ein passendes ComponentUI zur Verfügung stellen oder für die Bildschirmdarstellung durch Überlagern von paintComponent selbst erledigen."

    Also: die Komponente selber malen. Dass der Farbwechsel angekommen ist, sieht man übrigens, wenn man die Komponente mit einer Border ausrüstest, z.B.
    this.setBorder(BorderFactory.createEtchedBorder()) ;
    Dann ist die Farbe plötzlich da, aber eben nur im Rahmen.
    Das Ziel ist das Ziel.

  11. #11
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Cool! Beim UI war ich mittlerweile auch angekommen. Habe in O'Reillys Swing Buch gerade über den Bau eigener Komponenten gelesen und wollte nachher mal ein Beispiel implementieren. Sollten mir noch Erkenntnisse aufsteigen, melde ich mich...

  12. #12
    Registrierter Benutzer Avatar von mwanaheri
    Registriert seit
    28.10.2003
    Ort
    Bayreuth
    Beiträge
    569
    Das wäre schön. Wie man nämlich paintComponent am besten überschreibt, habe ich keine Ahnung. Hätte ich aber gern.
    Das Ziel ist das Ziel.

  13. #13
    Registrierter Benutzer
    Registriert seit
    17.11.2005
    Beiträge
    47
    Also, ich habe mich heute mehrere Stunden mit dem Kram rumgeschlagen. Ich habe ein etwas umfanfreicheres Beispiel aus genanntem Buch implementiert. Saubere Trennung nach MVC und die UI-Klasse schön brav von ComponentUI abgeleitet. Auch hierbei gilt: setBackground hatte zuerst keinen Effekt. Nachdem hier jedoch nun die Opaque-Eigenschaft auf true gesetzt wurde, ließ sich der Hintergrund durch Setzen von setBackground einfärben.
    Langsam erscheint mir das alles durchaus logisch:

    - In Swing gilt das MVC-Modell und NICHT die Komponente ist für das Zeichnen zuständig, sondern die der Komponente zugehörige und von ComponentUI abgeleitete UI-Klasse.

    - Die Funktionalität des Hintergrund-Malen ist also in ComponentUI implementiert und nicht in JComponent. Möchte man also eine ordentliche Swing-Komponente bauen, sollte man sich an das MVC-Modell halten.

    - Das bedeutet wiederum, dass man zum Zeichnen der Komponente weder die paint-Methode noch die paintComponent-Methode von JComponent überschreiben sollte, sondern die paint-Methode der korrespondierenden UI-Klasse! Diese registriert sich in der überschriebenen "installUI"-Methode bei der Komponenten-Klasse als Listener für die relevanten Events, handelt diese und modifiziert das Modell. Die Komponente ist wiederum Listener für das ChangeEvent, welches das Modell dann auslöst. Hier ruft die Komponente "redraw()" auf. Die bei der Komponente gemeldete UI-Klasse wird daraufhin automatisch veranlasst, die Komponente neu zu zeichnen, also die paint()-Methode auszuführen.


    War das halbwegs verständlich? Ich bin etwas breiig im Kopf....

    Nachtrag:
    Der Hintergrund einer Komponente wird in der Methode ComponentUI.update() gezeichnet, falls wenn opaque = false gilt. Diese Methode wird von JComponent.paintComponent() aufgerufen und ruft ihrerseits ComponentUI.paint() auf.
    Geändert von McFraggle (20-12-2005 um 10:28 Uhr)

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •