Avatar billede dark_sun Nybegynder
05. februar 2003 - 22:14 Der er 14 kommentarer og
1 løsning

Image(jPanel, jFrame)

Hejsa
Jeg har to problemer, og håber at der er nogle der kan hjælpe mig med at løse dem. Jeg vil gerne kunne sætte et image ind som baggrund i et jPanel, hvor man stædig skal kunne se de andre komponenter i det jPanel. Det anden ting er at jeg godt vil kunne sætte et image ind som baggrund  i min jFrame, og her skal man også kunne se de andre komponenter. Jeg vil godt have lidt kode, hvis der er en der er så rar. Jeg vil lige sige at jeg ikke vil bruge en jLabe, hvis der er en der kommer med det forslag. Jeg håber at der er en der kan hjælpe mig, med de to sprøgsmål. :-)
Avatar billede =maddog= Nybegynder
06. februar 2003 - 01:11 #1
Du bliver nød til at overskrive JPanel eller Panel. Jeg er beklageligvis selv flasket op med AWT, så her kommer koden til et Panel med et billede som baggrund. Den anvender en offscreen buffer. Bemærk at det er vigtigt at du kalder Component.prepareImage() før du sætter Image ind, da den ellers vil loade dit Panel selvom hele billedet ikke er indlæst.
Det er muligt at en venlig Swing haj vil hjælpe dig med et JPanel, ellers må jeg kigge på det. (Husk at kun lightweight componenter kan have tranparent pixels. Alle Swing komponenter og direkte underklasser af Component er lightweigtht).

class ImagePanel extends Panel {
    Image offscreen; //buffer
    Image image;

    public ImagePanel(LayoutManager lm, Image image) {
        super(lm);
        this.image = image;
    }
 
    public ImagePanel(Image image) { this(new FlowLayout(),image); }
 
    public ImagePanel(LayoutManager lm) { this(lm,null); }
 
    public ImagePanel() { this(new FlowLayout(),null); }

    public void invalidate() {
        super.invalidate();
        offscreen = null;
    }

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

    public void paint(Graphics g) {
        if(offscreen == null) {
            offscreen = createImage(getSize().width, getSize().height);
        }
        Graphics og = offscreen.getGraphics();
        og.setClip(0,0,getSize().width, getSize().height);
        if (image!=null) og.drawImage(image,0,0,getSize().width,getSize().height,this);
        super.paint(og);
        paintComponents(og);
        og.dispose();
        g.drawImage(offscreen, 0, 0, this);
    }
}
Avatar billede dark_sun Nybegynder
06. februar 2003 - 10:51 #2
Tak skal du have, for din hjælp. Men er der ikke en der kan hjælpe mig med JPanel og Panel, da det er det som jeg bruger i mit program. :-)
Avatar billede dark_sun Nybegynder
06. februar 2003 - 16:25 #3
ups, en fejl jeg mente altså JPanel og JFrame ;-}
Avatar billede =maddog= Nybegynder
06. februar 2003 - 16:58 #4
problemet mellem JPanel og Panel er jo at et JPanel allerede HAR en dobbelt-buffer, og den er jeg ikke sikker på man har tilgang til. Jeg mener at paint i JPanel tegner til denne buffer, og getGraphics() henter det Graphics objekt der tegner i bufferen. Et øjeblik og jeg vil kigge på det.
Avatar billede =maddog= Nybegynder
06. februar 2003 - 23:03 #5
Det lader ikke til at der er nogen venlige sjæle og jeg kan kun få det til at virke med JPanel hvis vinduet først bliver minimeret og får fokus igen!?! Tilgengæld virker det ikke som om at Panel giver de helt store problemer. Jeg havde frygtet at Panel ville blive heavyweight og derfor tegnet oven på swing komponenter, men det lader til at gå. Du kan jo prøve om det virker.
import java.awt.*;
import javax.swing.*;

public class ImageJFrame extends JFrame {
   
    private Container content;
   
    public ImageJFrame(String title, String filename) {
        super(title);
        content = new ImagePanel(getPreparedImage(filename));
        setContentPane(content);
    }
   
    public Image getPreparedImage(String filename) { // should be overwritten by
                                                    // subclasses used in JApplets
        Image i = getToolkit().getImage(getClass().getResource(filename));
        prepareImage(i,this);
        return i;
    }
   
    public void setVisible(boolean b) {
        super.setVisible(b);
        content.repaint();
    }
       

    protected class ImagePanel extends Panel {
        private Image offscreen; //buffer
        private Image image;

        public ImagePanel(LayoutManager lm, Image image) {
            super(lm);
            this.image = image;
        }
 
        public ImagePanel(Image image) { this(new BorderLayout(),image); }
 
        public ImagePanel(LayoutManager lm) { this(lm,null); }
 
        public ImagePanel() { this(new FlowLayout(),null); }

        public void invalidate() {
            super.invalidate();
            offscreen = null;
        }

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

        public void paint(Graphics g) {
            if(offscreen == null) {
                offscreen = createImage(getSize().width, getSize().height);
            }
            Graphics og = offscreen.getGraphics();
            og.setClip(0,0,getSize().width, getSize().height);
            if (image!=null) og.drawImage(image,0,0,getSize().width,getSize().height,this);
            super.paint(og);
            paintComponents(og);
            g.drawImage(offscreen, 0, 0, this);
            og.dispose();
        }
    }
    /*
    * En lille main metode til at prøve skidtet af.
    */
      public static void main(String[] args) {
          JFrame myFrame = new ImageJFrame("Test af ImageJPanel","alchemy/back.gif");
          myFrame.getContentPane().setLayout(new FlowLayout());
          myFrame.getContentPane().add(new JButton("bøh"));
          JButton b = new JButton("gennemsigtig");
          b.setContentAreaFilled(false);
          myFrame.getContentPane().add(b);
        myFrame.setSize(400,300);
        myFrame.addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent e) { System.exit(0); }
        });
        myFrame.setVisible(true);
    }
}
Avatar billede dark_sun Nybegynder
07. februar 2003 - 00:44 #6
Mange tak for din hjælp. Men jeg har dog et problem tilbage, som du måske kan løse. Hvordan kan det være at jeg ikke kan se mine knapper når der kommer et billede ind i min Frame. Det vil sig at jeg godt kan se dem, men først når jeg køre musen hen over dem. Det er det samme problem jeg har, hvis jeg bruger denne kode, som også sætte et billede ind i min Frame

Image baggrund = Toolkit.getDefaultToolkit().getImage("C:/O0803.gif");

public void paint(Graphics g)
  {
  g.drawImage(baggrund,0,0,this);

Ved ikke om du kan løse det, men jeg ville blive meget glad for det, hvis du kunne. Men igen tak for hjælpen. Du skal nok få de 60 points for din hjælp, også selvom at du ikke kan hjælpe mig med dette. :-)
Avatar billede =maddog= Nybegynder
07. februar 2003 - 02:47 #7
som du kan se kalder jeg både super.paint(Graphics)og paintComponents(Graphics). Hvis du ikke kalder disse metoder vil du ikke få tegnet komponenterne inden i Container objektet. (Grunden til at du skal bruge super. ved paint er naturligvis at du er i gang med at overskrive denne metode. Hvis du blot skrev paint(og) ville du få en uendelig recursiv løkke.)
Desværre vil super.paint(Graphics) altid bruge dobbelt bufferen (der vil starte med at tegne en grå baggrund med det samme) i en swing Container, så det er derfor Panel er blevet valgt. Det ser ikke ud til at have de store implikationer, men det kan jo være det ikke dur i dit program. Den stump der er i min forrige kommentar virker i hvert fald.
Det eneste AWT der duer sammen med Swing er lightweight komponenter, men de dur sådan set fint. Du kan læse mere om heavyweight/lightweight problematikken her
http://java.sun.com/products/jfc/tsc/articles/mixing/index.html
Der er er dødt link i denne artikel men den referer til dette dokument
http://java.sun.com/j2se/1.4.1/docs/guide/awt/1.3/designspec/lightweights.html
der indeholder en del fif til hvorledes man kan lave AWT lightweight (enten fordi man vil mixe med swing eller fordi man vil lave appletter til gamle platforme). Som du kan se vil et panel med buffer fint kunne håndtere lightweights, eneste forskel er at vi her tegner et baggrundsbillede ind i bufferen før vi tegner komponenterne.
Jeg har en hel del hjemmegjorte AWT kompatible lightweight komponenter, der bl.a. kan håndtere gennemsigtighed.
På dette punkt plejer jeg at vise den famøse dwemer potion machine alle morrowind spillere elsker at hade :-).
http://www.dsr.kvl.dk/~maddog/alchemy/
er 100% java1 kompatibelt og kan køre i NS4 (sidst jeg checkede).
Avatar billede =maddog= Nybegynder
07. februar 2003 - 02:52 #8
jeg vil ikke anbefale at gøre det som du har gjort.
1) Du bruger Image før du har kaldt prepareImage(Image, ImageObserver). Hvis du gør det er du ikke sikker på alle bits i billedet er hentet før det skal tegnes af Graphics objektet. Trust me on this one.
2) Du tegner billedet direkte ind i det Graphics objekt der bliver brugt til af paint. Det giver en utrolig gang flimmer fordi man kan se billedet blive tegnet byte for byte. Det er bedre at lave en buffer og tegne det hele på en gang.
Avatar billede =maddog= Nybegynder
07. februar 2003 - 03:01 #9
Jeg skulle måske lave et svar alt til trods.
Avatar billede dark_sun Nybegynder
09. februar 2003 - 20:06 #10
Det må du meget gerne gør for mig. Tak skal du have
Avatar billede =maddog= Nybegynder
09. februar 2003 - 23:50 #11
hvad mener du?
Avatar billede dark_sun Nybegynder
11. februar 2003 - 19:03 #12
Min fejl. Her er dine points. Jeg fik det ikke til at fungere, men du gav mig en ide, og så har jeg fået mulighed for at få hjælp fra en på min skole. :-)
Avatar billede =maddog= Nybegynder
11. februar 2003 - 19:27 #13
VIl du høre noget sjovt. Senere samme dag (den 7. Februar 2003) kom dette dokument online hos sun.
http://java.sun.com/products/jfc/tsc/articles/swing2d/
Det beskriver nøjagtigt og step-by-step hvordan man gør i Swing. Sådan kan man være heldig en gang i mellem. Jeg sidder selv og læser med iver lige nu (er selv AWT opdraget).
Avatar billede dark_sun Nybegynder
11. februar 2003 - 19:34 #14
Mage tak skal du have for det. Det skal læse ord for ord. :-)
Avatar billede =maddog= Nybegynder
11. februar 2003 - 19:38 #15
lader til at man skal bruge paintComponent() i stedet for ved Swing. Tak for point forresten.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester