LazyWolf: Swing Formularelemente - Anzeigefehler?

Hallo.

Ich habe letztens mein AWT Fenster Spaßeshalber in SWING umgeandelt und habe jetzt folgedes Problem.

Ich setze ein paar Elemente, JTextField, JRadioButton etc.
Jedoch werden die erst angezeigt, wenn ich sie (im unsichtbaren Zustand) benutze.
Wenn ich dann das Fenster minimiere, oder von einem einem anderen verdecke o.ä. sind sie wieder weg - bis zum anclicken.

Woran könnte das liegen?

  1. Hallo,

    Woran könnte das liegen?

    Keine Ahnung.

    Poste bitte mal den relevanten Code. (Oder die ganze Klasse, falls sie
    noch nicht zu groß ist.)

    Gruß
    Slyh

    1. Hallo,

      Woran könnte das liegen?

      Keine Ahnung.

      Poste bitte mal den relevanten Code. (Oder die ganze Klasse, falls sie
      noch nicht zu groß ist.)

      Gruß
      Slyh

      public void displayForms()
        {
        getContentPane().setLayout(null);

      pl = new JLabel("Spieler 1:");
        pl.setBounds(20, 250, 100, 20);
        getContentPane().add(pl);

      tf = new JTextField("",20);
        tf.addActionListener(this);
        tf.setBounds(20, 270, 140, 20);
        getContentPane().add(tf);

      lb = new JLabel("");       // NAME SELECTION DISPLAY
        lb.setBounds(240, 270, 100, 20);
        getContentPane().add(lb);

      lb_ni = new JLabel("");       // CLASS SELECTION DISPLAY
        lb_ni.setBounds(240, 290, 100, 20);
        getContentPane().add(lb_ni);

      group = new ButtonGroup();

      check_ni = new JRadioButton("Mage", false);
        check_ni.addActionListener(this);
        check_ni.setBounds(20, 290, 80, 20);
        getContentPane().add(check_ni);
        group.add(check_ni);

      check_ichi = new JRadioButton("Warrior", false);
        check_ichi.addActionListener(this);
        check_ichi.setBounds(100, 290, 80, 20);
        getContentPane().add(check_ichi);
        group.add(check_ichi);

      ap = new JButton("apply");
        ap.addActionListener(this);
        ap.setBounds(330, 270, 70, 20);
        ap.setEnabled(false);
        getContentPane().add(ap);

      go = new JButton("> start >");
        go.addActionListener(this);
        go.setBounds(20, 380, 100, 20);
        go.setEnabled(false);
        getContentPane().add(go);

      saved_name_ichi = new JLabel("");    // NAME 1
        saved_name_ichi.setBounds(80, 320, 100, 20);
        getContentPane().add(saved_name_ichi);

      saved_class_ichi = new JLabel("");    // CLASS 1
        saved_class_ichi.setBounds(80, 340, 100, 20);
        getContentPane().add(saved_class_ichi);

      saved_name_ni = new JLabel("");     // NAME 2
        saved_name_ni.setBounds(280, 320, 100, 20);
        getContentPane().add(saved_name_ni);

      saved_class_ni = new JLabel("");    // CLASS 2
        saved_class_ni.setBounds(280, 340, 100, 20);
        getContentPane().add(saved_class_ni);
        }

      Das rufe ich auf mit displayForms();

      1. Hallo,

        Das rufe ich auf mit displayForms();

        Und displayForms() rufst du im Konstruktor oder einer der "Initalisierungs-
        methoden" auf, richtig? (Also nur einmal.)
        Sieht soweit ganz gut aus.

        Hast du vielleicht die paint()- oder die update()-Methode überschrieben?
        Der Fehler würde darauf hindeuten. Rufe in diesem Fall möglichst immer
        die überschriebene Methode auf. Dies machst du, indem du irgendwo
        in der "überschreibenden" Methode "super.paint();" (oder was auch immer
        gerade deine überschriebene Methode ist) aufrufst.

        Gruß
        Slyh

        1. Also bei mir sieht das so aus...
          Es gibt eine paint() Methode, diese enthält alle Methoden zum setzen von "statischen" Grafiken. Das garantiert, dass auch nach dem Minimieren etc. die Grafiken wieder angezeigt werden.
          Eine update() Methode kümmert sich um das Animieren von ein paar Gifs.

          Mein Problem ist jedoch, dass die Formularelemente nichtmal beim Aufruf der genannten Methode angezeigt werden. Sie werden gesetzt, aber man sieht sie nicht. Wenn ich sie anclicke, erscheinen sie. Wenn ein event z.B. setEnabled ändert, dann erscheinen sie auch.
          Minimiere und maximiere ich sie, sind sie wieder weg.
          Ich habe versucht, sie in die paint(); Methode zu setzen, aber irgendwie hilft das nicht.

          Ich verstehe es nicht.

          1. Hallo,

            Es gibt eine paint() Methode,

            Und darin rufst du bestimmt super.paint() auf, die wiederum eine Methode
            zur Anzeige der Swing-Dialogelemente aufruft, oder?

            diese enthält alle Methoden zum setzen von "statischen" Grafiken.

            Was sind statische Grafiken? Wieso machst du sowas in paint()?
            Was willst du damit erreichen?

            Das garantiert, dass auch nach dem Minimieren etc. die Grafiken wieder angezeigt werden.

            Was es ja scheinbar nicht tut. :-)

            Eine update() Methode kümmert sich um das Animieren von ein paar Gifs.

            Wieso sowas in update()? Und was heißt "kümmert sich um das Animieren"?

            Mein Problem ist jedoch, dass die Formularelemente nichtmal beim Aufruf der genannten Methode angezeigt werden.

            Welche meinst du jetzt? Die super-Methoden?

            Sie werden gesetzt, aber man sieht sie nicht. Wenn ich sie anclicke, erscheinen sie. Wenn ein event z.B. setEnabled ändert, dann erscheinen sie auch.

            Ja, weil sie sich dann selbst zeichnen, initiiert durch den Klick.
            Das erste mal werden sie aber von paint() gezeichnet.
            Und auch dann, wenn z.B. Teile durch ein anderes Fenster überdeckt
            wurden und diese Teile nun neu gezeichnet werden müsen.
            Wenn nun paint() nicht mehr die Methode zum Zeichnen der Komponenten
            aufruft, werden diese logischerweise auch nicht mehr angezeigt. Dann
            werden eben nur noch deine "statischen Grafiken" oder wasauchimmer
            angezeigt.

            Übrigens steht das, was ich dir gerade erzähle, auch in der API-Doku
            zu paint(): "Paints the container. This forwards the paint to any
            lightweight components that are children of this container. If this
            method is reimplemented, super.paint(g) should be called so that
            lightweight components are properly rendered."

            Hintergrund: JFrame ist ein Container, kann selbst also andere
            Components enthalten. (JFrame ist von java.awt.Container abgeleitet.)
            Damit diese Components gezeichnet werden, muß der Container allen
            enthaltenen Components sagen "Los, zeichne dich mal". Das erfolgt -
            wenn ich mich recht erinnere - in der Methode paintComponents().
            Genau diese Methode wird in paint() aufgerufen. Damit das auch noch
            dann erfolgt, wenn du paint() überschreibst, solltest du stets auch
            immer super.paint() aufrufen.

            Gruß
            Slyh

            1. Hoa...

              ...okay... *versuchnachzuvollziehen*

              1. Mit "statischen Grafiken" meine ich Bilder, die das "Design" ausmachen, also sich nicht bewegen, nicht erscheinen, nicht verschwinden, sondern einfach immer da sind.
              2. Wenn ich ein AniGif zeichnen lasse, dann ruft es sich selbst immer wieder selbst auf, um die Animationsteile anzuzeigen, habe ich festgestellt. Da das sich aber durch ein Flackern aller anderen Grafiken bemerkbar machte, habe ich die Anigifs in update(), alle anderen Grafiken in Methoden, die von paint() gerufen werden. Wenn ich minimiere etc. wird paint aufgerufen, oder durch einen direkten aufruf. Der Befehl repaint(); startet lediglich das update().
              3. Würde es dir etwas ausmachen, mir das mit dem super.paint() an einem kleinen Codebeispiel zu zeigen? Ich komme da nicht so ganz mit.

              Mach's gut.
              LazyWolf

              1. Nochmal kurz nachgeschoben:

                Wenn ich das zeichnen der Formulare in paint() oder update() setze, werden sie jedesmal überienandergezeichnet.
                Das wirkt sich darauf aus, dass mit setText der Inhalt eines Labels nicht ersetzt, sondern drübergepappt wird...

                Also irgendwie nicht so sinnig...

              2. Hallo,

                1. Mit "statischen Grafiken" meine ich Bilder, die das "Design" ausmachen, also sich nicht bewegen, nicht erscheinen, nicht verschwinden, sondern einfach immer da sind.

                Ja, das würde ich unter statisch verstehen.
                Nur: Wo sind die Bilder? Zeichnest du die direkt in das JFrame rein?
                Wieso so kompliziert? Wieso verwendest du nicht einfach z.B. ein Label,
                das dieses Bild anzeigen soll. Dann hast du auch das Problem nicht
                mehr. (Naja, gut, manchmal ist das nicht möglich.)

                1. Wenn ich ein AniGif zeichnen lasse, dann ruft es sich selbst immer wieder selbst auf, um die Animationsteile anzuzeigen, habe ich festgestellt. Da das sich aber durch ein Flackern aller anderen Grafiken bemerkbar machte, habe ich die Anigifs in update(), alle anderen Grafiken in Methoden, die von paint() gerufen werden. Wenn ich minimiere etc. wird paint aufgerufen, oder durch einen direkten aufruf. Der Befehl repaint(); startet lediglich das update().

                Das flackert deshalb, weil in update() normalerweise vorher die
                Zeichenfläche gelöscht wird. Wenn du update() überschreibst, also
                durch deinen eigenen Code ersetzt, passiert das natürlich nicht mehr.
                (Außer du würdest die Zeichenfläche wieder jedesmal löschen.)
                In der Regel reicht es übrigens, wenn du in update() einfach paint()
                aufrufst, also

                void update(Graphics g) {
                    paint(g);
                  }

                oder so ähnlich.

                1. Würde es dir etwas ausmachen, mir das mit dem super.paint() an einem kleinen Codebeispiel zu zeigen? Ich komme da nicht so ganz mit.

                Klar.

                void paint(Graphics g) {
                    // hier ist dein Grafik-Zeugs
                    // ...

                super.paint(g);
                  }

                Aber, nach meiner Erfahrung wirst du von deinen gerade gezeichneten
                Grafiken anschließend nichts mehr sehen, weil super.paint() (oder
                war's paintComponents(), das in super.paint() aufgerufen wird?) wohl
                doch wieder die Zeichenfläche löscht. Ich könnte mich aber täuschen.

                Ähm, ich will dich ja nicht entmutigen, aber vielleicht solltest du
                von deinen bisherigen Experimenten mal ein wenig Abstand gewinnen und
                dich erst einmal mit den Grundlagen der Java-Programmierung auseinander-
                setzen. Das http://www.javabuch.de von Guido Krüger finde ich
                ganz brauchbar. Dort steht auch was über die Grafikprogrammierung drin.
                Erst wenn du soweit in Java fit bist, solltest du dich mit der Grafik-
                programmierung beschäftigen - und auch wie diese ganzen Sachen bei
                Swing so zusammenhängen. Es ist nicht trivial!
                Am besten besorgst du dir noch eine anständigen Java-IDE, in der du
                dir die Klassenhierarchie angucken kannst und direkt im API-Code
                "rumsurfen" kannst. Eclipse (http://www.eclipse.org) ist da
                zu empfehlen, auch wenn das evtl. für Einsteiger nicht so gut
                verständlich ist. Am besten die Hilfe lesen.
                Und lies doch gelegentlich mal die API-Doku, die du bei Sun runterladen
                kannst. Da steht schon recht viel drin.

                Gruß
                Slyh

                1. Ah, es funktioniert!

                  Für das Archiv:
                  Ich habe jetzt am Ende der Methode, die die Formulare zeichnen soll, super.paint(g); aufgerufen und innerhalb der paint() Methode zu Beginn.
                  Tut man es nicht zu beginn, löscht es die anderen Grafiken.

                  Vielen Dank für die Hilfe!
                  LazyWolf