Swing Startbild wird nicht gezeichnet

_qwertz

Mitglied
Hallo Leute, ich habe ein kleines Problem.
Und zwar folgendes: Wir beschäftigen uns in der Schule mit einem Projekt ("interner Wettbewerb") das einen Ski-Lauf verwalten soll.
Ich habe es zwar hinbekommen, dass ich zwischen 2 JPanels hin und her wechseln kann, und dann auch mein Bild gezeichnet wird, jedoch wird dieses Startbild nicht beim aller ersten Aufruf des Programms gezeichnet (wie ich es gerne hätte) 🙁
Wäre schön, wenn ihr mir helfen könntet 🙂

Hier der Starter (da wir mit BlueJ arbeiten):
Java:
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.Dimension;

public class Starter
{
    private Spiel meinSpiel;

    public static void main(String[] args)
    {
        new Starter();
    }
    
    public Starter()
    {
        meinSpiel = new Spiel();
        meinSpiel.setSize(1000, 800);
        centerWindow(meinSpiel);
        meinSpiel.setVisible(true);
        meinSpiel.setAnfangsPanel();
    }
    
    public void centerWindow(Window window)
    {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        Dimension frameSize = window.getSize();
        
        if (frameSize.height > screenSize.height)
        {
            frameSize.height = screenSize.height;
        }
        if (frameSize.width > screenSize.width)
        {
            frameSize.width = screenSize.width;
        }
        
        window.setLocation( (screenSize.width - frameSize.width) / 2,
                            (screenSize.height - frameSize.height) / 2
                          );
    }
}

Und hier die GUI:
Java:
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.awt.BorderLayout;

public class Spiel extends JFrame
{
    private AnfangsPanel anfangsPanel   = new AnfangsPanel(Toolkit.getDefaultToolkit().getImage("Bilder\\schnee.jpg"));
    private JPanel spielerPanel         = new JPanel();
    
    private BorderLayout myBorderLayout = new BorderLayout();
    
    private JMenuBar meineMenuBar       = new JMenuBar();
    
    private JMenu SpielMenu             = new JMenu("Spiel");
    private JMenu SpielerMenu           = new JMenu("Spieler");
    private JMenu RanglisteMenu         = new JMenu("Rangliste");
    
    private JMenuItem startMenuItem     = new JMenuItem("Lauf starten");    //Spiel-Menu
    private JMenuItem neustartMenuItem  = new JMenuItem("Neustart");        //Spiel-Menu
    private JMenuItem beendenMenuItem   = new JMenuItem("Beenden");         //Spiel-Menu
    private JMenuItem anmeldenMenuItem  = new JMenuItem("anmelden");        //Spieler-Menu
    private JMenuItem abmeldenMenuItem  = new JMenuItem("abmelden");        //Spieler-Menu
    private JMenuItem nextRunMenuItem   = new JMenuItem("nächster Lauf");   //Rangliste-Menu
    private JMenuItem gesamtMenuItem    = new JMenuItem("Platzierung");     //Rangliste-Menu
    
    private JLabel jLabelName           = new JLabel();
    private JTextField nameTF           = new JTextField();
    private JButton anmelden            = new JButton();
     
    public Spiel()
    {
        Controller myController = new Controller(this);

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(myBorderLayout);
        anfangsPanel.setLayout(null);
        spielerPanel.setLayout(null);
        
        setJMenuBar(meineMenuBar);
        meineMenuBar.add(SpielMenu);
        meineMenuBar.add(SpielerMenu);
        meineMenuBar.add(RanglisteMenu);
        
        SpielMenu.add(startMenuItem);
        SpielMenu.add(neustartMenuItem);
        SpielMenu.add(beendenMenuItem);
        SpielerMenu.add(anmeldenMenuItem);
        SpielerMenu.add(abmeldenMenuItem);
        RanglisteMenu.add(nextRunMenuItem);
        RanglisteMenu.add(gesamtMenuItem);
        
        startMenuItem.setActionCommand("start");            //Action Command
        startMenuItem.addActionListener(myController);
        neustartMenuItem.setActionCommand("neustart");      //Action Command
        neustartMenuItem.addActionListener(myController);
        beendenMenuItem.setActionCommand("beenden");        //Action Command
        beendenMenuItem.addActionListener(myController);
        anmeldenMenuItem.setActionCommand("switch anmelden");   //Action-Command
        anmeldenMenuItem.addActionListener(myController);
        abmeldenMenuItem.setActionCommand("abmelden");      //Action-Command
        abmeldenMenuItem.addActionListener(myController);
        nextRunMenuItem.setActionCommand("Liste next");     //Action-Command
        nextRunMenuItem.addActionListener(myController);
        gesamtMenuItem.setActionCommand("Liste gesamt");    //Action-Command
        gesamtMenuItem.addActionListener(myController);
        
        jLabelName.setText("Name");
        jLabelName.setBounds(new Rectangle(10, 80, 50, 20));
        
        nameTF.setBounds(new Rectangle(55, 75, 150, 30));
        
        anmelden.setBounds(new Rectangle(270, 75, 150, 30));
        anmelden.setText("Spieler anmelden");
        anmelden.setActionCommand("spieler anmelden");      //Action-Command
        anmelden.addActionListener(myController);
        
        spielerPanel.setBackground(Color.gray);
        spielerPanel.add(jLabelName, null);
        spielerPanel.add(nameTF, null);
        spielerPanel.add(anmelden, null);
    }
   
    public JTextField getNameTF()
    {
        return nameTF;      
    }
    
    public void setAnfangsPanel()
    {
        this.getContentPane().add(anfangsPanel, BorderLayout.CENTER);
        spielerPanel.setVisible(false);
        anfangsPanel.setVisible(true);
    }
    
    public void setSpielerPanel()
    {
        this.getContentPane().add(spielerPanel, BorderLayout.CENTER);
        anfangsPanel.setVisible(false);
        spielerPanel.setVisible(true);
    }
    
    class AnfangsPanel extends JPanel
    {
        private Image image;
        
        AnfangsPanel(Image image)
        {
            this.image = image;
            repaint();
        }
        
        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            g.drawImage(image, -100, -100, null);
        }
    }
}

Im Anhang noch das zu ladende Startbild -- wie gesagt, es klappt schon, jedoch erst, wenn ich 1-mal hin und her geschaltet habe 🙁
 

Anhänge

  • schnee.jpg
    schnee.jpg
    98,5 KB · Aufrufe: 25
Nur kurz überflogen: Die ganzen "pauschalen" irgendeineComponent.setVisible(true) sollten überflüssig sein. Dafür sollte aber das frame.setVisible(true) erst GANZ am Ende gemacht werden, wenn alle anderen Components schon richtig platziert sind und so (also speziell: NACH setAnfangsPanel)
 
Hey, schonmal danke für die schnelle Antwort.
Ich habe den Konstruktor im Starter geändert:

Java:
public Starter()
    {
        meinSpiel = new Spiel();
        meinSpiel.setSize(1000, 800);
        centerWindow(meinSpiel);
        meinSpiel.setAnfangsPanel();
        meinSpiel.setVisible(true);
    }

Klappt leider immer noch nicht mit dem AnfangsBild.
Ohne die setVisibles funktioniert das switchen nicht gescheit.

Edit: Ich schaue mir mal deinen Link an, danke 🙂
Hast du eine Idee, warum das Startbild am Anfang nicht gezeichnet wird?
 
verwende
> new ImageIcon("test.jpg").getImage()
zum Laden

und
> meinSpiel.setAnfangsPanel();
> meinSpiel.setVisible(true);
statt andersrum


falls die GUI schon zu sehen ist, schreibe bei Änderungen wie das Hinzufügen von Komponenten
validate();
repaint();
 
Vieleicht mal mit repaint() versuchen?

Ich meine im Grunde passiert ja, dass dein JPanel gezeichnet wird, aber das Bild darauf nicht.
Erst wenn du einmal umswitcht (2mal oder? hin und wieder zurück)
Das Programm zeichnet beim Switchen deine beiden Panels nochmal neu...
 
SlaterB: Danke, das mit dem ImageIcon war der entscheidende Tipp.
Habs geändert, jetzt klappts es. Kannst du mir auch erklären, warum?

@All: Danke für die Antworten, ich melde mich beim nächsten Problem 😉
 
Bilder müssen erst in Java geladen werden, da gibt es noch mehr als die zwei Wege, da gibt es verschiedene Bildformate die zu verstehen sind,
verschiede Image-Repräsentation in Java, Pixel für Pixel oder anderes,

vor allem werden aber Bilder teils nebenläufig geladen, sind erst nach einigen ms verfügbar, vorher ist das Objekt zwar schon da, liefert aber Höhe/Breite -1

lauter grausige Geschichten, eine Horror-Klasse für mich ist seit jeher
MediaTracker (Java Platform SE 6)

wahrscheinlich letztlich alles verständlich, wenn man es sich nur mal genauer anschauen würde,
solange bleibt mein Verständnis, dass new ImageIcon("test.jpg") am besten lädt, aber z.B. für gif nicht geeignet ist

edit:
ok, new ImageIcon() verwendet im Quellcode auch Toolkit.getDefaultToolkit() und dann einen MediaTracker und wartet,
im Grunde einfach, jaja
 
Zuletzt bearbeitet von einem Moderator:
Wenn man mit dem Toolkit ein Bild lädt, wird das Bild praktisch "im Hintergrund" geladen. D.h. das Programm läuft schon weiter (und baut das AnfangsPanel, und zeigt es an...) bevor das Bild fertig geladen ist.
Man kann das machen, was SlaterB geschrieben hat. Alternativ dazu könnte man mit einem MediaTracker (Java Platform SE 6) darauf warten, dass das Bild fertig geladen ist. Oder man lädt es mit ImageIO (Java Platform SE 6) ...

EDIT: Etwas zu langsam. Aber ja: Das mit dem MediaTracker ist (für ein einzelnes Bild) unnötig umständlich. Beim ImageIcon ist AFAIR der MediaTracker schon mit eingebaut. Aber ImageIO kann man sich auf jeden Fall mal ansehen.
 
Ok, das habe ich auch schon irgendwo gelesen, und habe deshalb einen Thread.sleep(2000) hinter dem Laden des Bildes gebaut. Hat aber auch nichts gebracht^^

-- Ich verstehe jetzt zwar, wo der Fehler lag, aber nicht, was sich Java dabei gedacht hat, die Bilder (ohne diesen Media Tracker) asynchron zu laden...-.-

jeden Falls: Nochmal Danke! 🙂
 
Zuletzt bearbeitet:
Synchron arbeiten ist ein schönes Stichwort in der Informatik.

Programmcode wird von oben nach unten gelesen und ausgeführt (einfach gesagt).

Ein einfacher Ein-Kern-Prozessor kann auch nicht mehrere Befehle gleichzeitig ausführen sondern immer hintereinander.
 
Eigentlich nur nebenbei, weil es ja jetzt erstmal wohl nicht darum gehen soll, wie man was Fertiges benutzt, aber: SplashScreen ist doch schnieke, oder?
 

Zurück
Oben