JButton

Hallo,

nachdem Ihr mir dabei geholfen habt, einen JButton mit einem Icon zu erstellen, was mittlerweile auch funktioniert - besten Dank nochmal -, habe ich nun das Problem, dass mir der JButton nur angezeigt wird, nachdem ich darauf geklickt habe. Das ist natürlich nicht schön. Hat jemand eine Lösung für dieses Problem?
Vielen Dank.

könntest du bitte den quelltext posten? kann sein das schon ein repaint() hilft…

Na klar…

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

public class Test extends Applet implements ActionListener {

Image image_a,image_n,image,image1,image2,image3,image0;
URL path1,path2,path3;
ImageIcon starticon, stopicon;

URL pathx, pathstartbutton, pathstopbutton;
MediaTracker mt = new MediaTracker(this);
JButton startbutton, stopbutton1, stopbutton2;

public void init() {

try {
initialisieren();
}
catch (Exception e) {e.printStackTrace();}

}

public void initialisieren() throws Exception {

setLayout(null);
setSize(404,200);

pathx = new URL(getCodeBase(), „slotmaschine/images/start2.gif“);
pathstartbutton = new URL(getCodeBase(), „slotmaschine/images/start2.gif“);
starticon = new ImageIcon(pathstartbutton);
startbutton = new JButton(starticon);

pathstopbutton = new URL(getCodeBase(), „slotmaschine/images/stop_grau.gif“);
stopicon = new ImageIcon(pathstopbutton);
stopbutton1 = new JButton(stopicon);
stopbutton2 = new JButton(stopicon);

add(stopbutton1);
add(startbutton);
add(stopbutton2);
stopbutton1.addActionListener(this);
startbutton.addActionListener(this);
stopbutton2.addActionListener(this);

stopbutton1.setBounds(new Rectangle(35, 147, 60, 30));
startbutton.setBounds(new Rectangle(115, 147, 60, 30));
stopbutton2.setBounds(new Rectangle(195, 147, 60, 30));

repaint();

//dann noch ein bißl Quelltext…

public void update(Graphics g){

paint(g);
}

public void paint(Graphics g)
{
g.drawImage(image0, 10, 15, this);
try{
g.clipRect(15,13,300,85);
g.drawImage(image1,14,15,this);
g.drawImage(image2,104,15,this);
g.drawImage(image3,194,15,this);
}
catch(Exception e){e.printStackTrace();}

}
}

Und??? Hilft’s??? Das repaint() hab ich ja schon drin…

Und jetzt kommen wir zu den dummen Nebeeffekten:

der Konstrutor von ImageIcon erzeugt das Bild nicht ganz, er fängt nur mit dem Laden an. Wenn das Bild dann komplett ist kann man’s auch anzeigen.

Alternative 1:
du wartetes einfach 2-3 Sekunden. Dann ist das Bild i.d.R. fertig und kann angezeigt werden.

Alternative 2:
Du verstehts das Image-observer-Interfaces (ich raff’s nicht) und überredes das Frame dazu einen repaint zu machen wenn das Laden fertig ist.

Alternative 3, der MediaTracker:

tracker = new MediaTracker(this); //this ist ein Frame
Image bg = Toolkit.getDefaultToolkit().createImage(url);
tracker.addImage(bg, 0);
tracker.waitForID(0);
ImageIcon I = new ImageIcon (bg);

Das waitForID() blockiert bis das Bild komplett geladen wurde. Stoft man’s dann in ein ImageIcon muss das Icon nicht neu laden sondern übernimmt die Daten das Image-Objectes.

viel Glück.

Alternative 3, der MediaTracker:

tracker = new MediaTracker(this); //this ist ein Frame
Image bg = Toolkit.getDefaultToolkit().createImage(url);
tracker.addImage(bg, 0);
tracker.waitForID(0);
ImageIcon I = new ImageIcon (bg);

Also, ich habe es mitdem MediaTracker probiert, aber die Bilder werden trotzdem erst angezeigt, nachdem ich drauf geklickt hab…

Hallo,

ich kann dir zwar nicht genau sagen woher dein Problem kommt, aber eins hab ich in meiner Zeit mit Java schon gelernt: Es entstehen die seltsamsten Effekte, wenn man Swing-Komponenten mit AWT-Komponenten vermischt. So ists auch bei dir. Du leitest von Applet (=AWT) ab und benutzt JButton (=Swing). Wenn du Swing benutzen willst, dann leite die Klasse von JApplet ab, kann gut sein, das das dein Problem ist.

Gruß
Jodus

Moin

Also, ich habe es mitdem MediaTracker probiert, aber die
Bilder werden trotzdem erst angezeigt, nachdem ich drauf
geklickt hab…

Habs durchgetestet, bei mir gehts (sun-jsdk 1.4.1, X4.2.99) :

welches AWT-Object (swing) benutzt du für den Mediatracker ?
wie lange braucht das waitForID ?

cu

Ich habe versucht Dein Problem nachzuvollziehen. Ich habe das gleiche Problem mit deinem Quelltext, wenn ich jedoch public void paintComponents(Graphics g) statt public void paint(Graphics g) benutze geht es. Wie mein vorredner bereits sagte sollte man sich entscheiden, Swing oder AWT (ich empfehle dir swing). Mit dem ImageIcon hat das meines erachtens nichts zu tun, laut Doku:

An implementation of the Icon interface that paints Icons from Images. Images that are created from a URL or filename are preloaded using MediaTracker to monitor the loaded state of the image.

wird das Icon vorgeladen. Dieses Problem nicht geladener Bilder hat man bei Images(class Image).

Hoffe das hilft Dir

gruß
bonkers

Habs durchgetestet, bei mir gehts (sun-jsdk 1.4.1, X4.2.99) :

welches AWT-Object (swing) benutzt du für den Mediatracker ?
wie lange braucht das waitForID ?

cu

Hmm…also ich hab die 1.4.1_02…
Wie jetzt AWT-Object?? Ich hab’s einfach so:

MediaTracker mt = new MediaTracker(this);
mt.addImage(stopimage, 0);
mt.addImage(startimage, 1);
mt.waitForAll();

Das waitForAll() geht eigentlich recht fix, wenn man’s aber abfragt, ob alle Bilder geladen wurden, gibt’s ein true zurück…

Oh man, so langsam bin ich verwirrt… :smile:
Also, wenn ich paintComponents nehme, werden die JButtons mit den Icons angezeigt, dafür dann aber meine normalen Images (z.B. das Hintergrundbild) nicht mehr…
Gibt’s jetzt dafür auch noch ne schöne Lösung??? :wink:
Thx a lot.

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Moin

Hmm…also ich hab die 1.4.1_02…
Wie jetzt AWT-Object??

das „this“ aus dem Code muss ein (sichtbarers) Frame sein (wenn man auf Nummer sicher gehen will).

MediaTracker mt = new MediaTracker(this);
mt.addImage(stopimage, 0);
mt.addImage(startimage, 1);

da müsste doch ein try{-}catch() rum oder ?

mt.waitForAll();

Das waitForAll() geht eigentlich recht fix, wenn man’s aber
abfragt, ob alle Bilder geladen wurden, gibt’s ein true
zurück…

Macht’s du auch den Test auf „isErrorAny()“ ?

Nochwas: Werden die Bilder skaliert angezeigt ? Der Mediatracker, so eingesetzt wie oben beschrieben, erzeugt ein fertig gerendertes Bild für die Orginalgrösse. Wird das Bild verkleinert/vergrössert angezeigt so muss ein neues Bild gerendert werden. Alle gerenderten Bilder werden in Image gespeichert.

cu

Wie jetzt AWT-Object??

das „this“ aus dem Code muss ein (sichtbarers) Frame sein
(wenn man auf Nummer sicher gehen will).

MediaTracker mt = new MediaTracker(this);
mt.addImage(stopimage, 0);
mt.addImage(startimage, 1);

da müsste doch ein try{-}catch() rum oder ?

mt.waitForAll();

Das waitForAll() geht eigentlich recht fix, wenn man’s aber
abfragt, ob alle Bilder geladen wurden, gibt’s ein true
zurück…

Macht’s du auch den Test auf „isErrorAny()“ ?

Nochwas: Werden die Bilder skaliert angezeigt ? Der
Mediatracker, so eingesetzt wie oben beschrieben, erzeugt ein
fertig gerendertes Bild für die Orginalgrösse. Wird das Bild
verkleinert/vergrössert angezeigt so muss ein neues Bild
gerendert werden. Alle gerenderten Bilder werden in Image
gespeichert.

cu

Ähm, ich hab kein Frame sondern ein Applet…

Um den MediaTracker is schon ein try-catch drum herum, wollte bloß net den ganze Code aufschreiben…wird dann vielleicht doch ein bißl viel. :wink:

Das isErrorAny() gibt ein false zurück.

Die Buttons werden skaliert und damit die Icons doch auch, oder?

Ähm, ich hab kein Frame sondern ein Applet…

past schon.

Die Buttons werden skaliert und damit die Icons doch auch,
oder?

Jetzt kochen wir mit Gas.

Ein kleine Einführung in das Imageing-System von java:

Die Klasse Image enthält erstmal nur die Rohdaten für ein Bild, also z.b. den Inhalt der jpeg-Datei. Soll ein Image dargestellt werden so muss es gerendert werden. Da das rendern u.U. sehr lange dauern kann passiert das im Hintergrund und wird durch das erste „paint()“ von dem Image-Object angestossen. Beim allerersten Paint sind die Daten also NICHT verfügbar und man sieht NIX. Für jede Grösse muss einmal gerendert werden. Der MediaTracker (so aufgerufen wie bishar) weiss nicht welche Grösse er nehmen soll und mach erstmal Orginal-grösse. Wenn der Button nun per paint (image, x1,y1,x2,y2) versucht eine scalierte Version des Bilds zu malen wird das Orginal-Bild auf die richtige Grösse scaliert. Natürlich im Hintergrund, natürlich sieht man beim 1. Mal NIX.

Und genau da liegt der Hase im Pfeffer. Dein Image-Object hat beim 1. paint die raw-Daten und eine gerendertet 1:1-Version (vom Mediatracker angestossen und überwacht in waitForAll). Der Button fragt (in seiner paint-Mehtode) ImageIcon nach einer 1,123:0.987 Version. ImageIcon fragt Image nach der Version. Image meint „jetzt gerade nicht“ und fängt an mit rechnen. Beim 2. Durchlauf ist Image mit Scalieren durch und kann das Bild liefern.

Und deshalb gibt es im Mediatracker :
addImage(Image image, int id, int w, int h)

must nur noch die End-höhe und Breite rausfinden.

cu

Und deshalb gibt es im Mediatracker :
addImage(Image image, int id, int w, int h)

must nur noch die End-höhe und Breite rausfinden.

cu

Okay, soweit isses nu klar.
Funzt aber trotzdem nicht…

Oh man, so langsam bin ich verwirrt… :smile:

verständlich

Also, wenn ich paintComponents nehme, werden die JButtons mit
den Icons angezeigt, dafür dann aber meine normalen Images
(z.B. das Hintergrundbild) nicht mehr…
Gibt’s jetzt dafür auch noch ne schöne Lösung??? :wink:
Thx a lot.

aso, hintergrundbild hast du ja auch noch. da hätte ich nur das hier anzubieten:

http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.c…

das zweite codebeipiel scheint dein problem zu treffen. bei fragen wegen verständniss einfach hier posten.

gruß

Ok ok…nochmal langsam von vorne…
Also…ich hab ein Applet, das drei Buttons enthält, welche drei Threads anstoßen und alles liegt auf einem Hintergrundbild über setBounds(new Rectangle()) eingebunden…
Aus den Buttons habe ich mittlerweile JButtons aufgrund der Icons gemacht…
Die Threads kann ich aber trotzdem anstoßen. Kein Thema.
Bleibt noch die Frage nach dem setBounds()…

Ok ok…nochmal langsam von vorne…
Also…ich hab ein Applet, das drei Buttons enthält, welche
drei Threads anstoßen und alles liegt auf einem
Hintergrundbild über setBounds(new Rectangle())
eingebunden…

was dein eigentliches problem ist(soweit ich es verstanden habe). durch überschreiben der paint-Methode werden auch die Buttons überzeichnet(das bild drübergelegt). wenn du ein hintergrundbild für dein applet einbinden möchtest und außerdem die Button darauf haben willst, solltest du es angehen wie in dem Link den ich gepostet habe. Das Problem ist, das alles überzeichnet wird wenn die paint methode vom applet überschrieben wird, also alle komponenten auch die buttons. ich werde versuchen das mal als applet umzusetzen, leider hab ich gerad nicht so viel zeit.

Aus den Buttons habe ich mittlerweile JButtons aufgrund der
Icons gemacht…
Die Threads kann ich aber trotzdem anstoßen. Kein Thema.

Klar das ist auch unabhängig von der GUI. Die Threads haben in dem Sinne nichts mit dem Swing und AWT zu tun. Alle Komponeten die mit J… anfangen gehören zu den Swing Klassen.

Bleibt noch die Frage nach dem setBounds()…

Versteh ich nicht. setBounds() gibt die Größe der Buttons bzw die Position innerhalb des Applets an. Welche Frage hast Du da? setBounds() benutzt du weil du keinen LayoutManager hast. Sonst würde die Größe der Buttons von diesem festgelegt werden.

Gruß

hier mal mein quelltext, habe deinen etwas modifiziert. ich hoffe du erkennst alles wieder. bgImage ist das hintergrundbild

import java.awt.\*;
import java.awt.event.\*;
import java.net.\*;
import javax.swing.\*;
import java.awt.\*;

public class Test extends JApplet implements ActionListener {

 Image image\_a,image\_n,image,image1,image2,image3,image0;
 URL path1,path2,path3;
 ImageIcon starticon, stopicon, bgImage;

 URL pathx, pathstartbutton, pathstopbutton, bgPath;
 MediaTracker mt = new MediaTracker(this);
 JButton startbutton, stopbutton1, stopbutton2;
 Container c;

 public void init() {
 try {
 initialisieren();
 } catch (Exception e) {
 e.printStackTrace();
 }
 }

 public void initialisieren() throws Exception {
 setSize(404, 200);
 //create URLs
 pathx = new URL(getCodeBase(), "start2.gif");
 bgPath = new URL(getCodeBase(), "horoskop.gif");
 pathstartbutton = new URL(getCodeBase(), "start2.gif");
 pathstopbutton = new URL(getCodeBase(), "stop.gif");

 //create ImageIcons
 starticon = new ImageIcon(pathstartbutton);
 stopicon = new ImageIcon(pathstopbutton);
 bgImage = new ImageIcon(bgPath);

 //set Panel as contentPane for background image
 setContentPane(new MyContentPane(bgImage.getImage()));
 c = getContentPane();
 c.setLayout(null);

 //create buttons
 startbutton = new JButton(starticon);
 stopbutton1 = new JButton(stopicon);
 stopbutton2 = new JButton(stopicon);

 stopbutton1.setBounds(new Rectangle(35, 147, 60, 30));
 startbutton.setBounds(new Rectangle(115, 147, 60, 30));
 stopbutton2.setBounds(new Rectangle(195, 147, 60, 30));

 //add to contentPane
 c.add(stopbutton1);
 c.add(startbutton);
 c.add(stopbutton2);

 stopbutton1.addActionListener(this);
 startbutton.addActionListener(this);
 stopbutton2.addActionListener(this);
 }

 //dann noch ein bißl Quelltext...............

 public void actionPerformed(ActionEvent a) {
 }

 //panel with background image
 private class MyContentPane extends JPanel {
 private Image backgroundImage;

 public MyContentPane(Image i) {
 setOpaque(true);
 setBackground(Color.green);
 backgroundImage = i;
 }

 public void paintComponent(Graphics g) {
 super.paintComponent(g);
 if (backgroundImage != null) {
 g.drawImage(backgroundImage, 0, 0, this);
 }
 }
 }
}

Ok, besten Dank. Hab soweit durchgeblickt…
Probier’s dann nachher mal aus…