Hoe voeg je een afbeelding toe aan een JPanel?

Ik heb een JPanelwaaraan ik JPEG- en PNG-afbeeldingen wil toevoegen die ik direct genereer.

Alle voorbeelden die ik tot nu toe heb gezien in de Swing Tutorials, speciaal in de Swing-voorbeeldengebruik ImageIcons.

Ik genereer deze afbeeldingen als byte-arrays, en ze zijn meestal groter dan het algemene pictogram dat ze in de voorbeelden gebruiken, op 640×480.

  1. Is er een (prestatie- of ander) probleem bij het gebruik van de ImageIcon-klasse om een afbeelding van dat formaat in een JPanel weer te geven?
  2. Wat is de gebruikelijkemanier om dit te doen?
  3. Hoe voeg je een afbeelding toe aan een JPanel zonder de ImageIcon-klasse te gebruiken?

Bewerken: Een nauwkeuriger onderzoek van de tutorials en de API laat zien dat je een ImageIcon niet rechtstreeks aan een JPanel kunt toevoegen. In plaats daarvan bereiken ze hetzelfde effect door de afbeelding in te stellen als een pictogram van een JLabel. Dit voelt gewoon niet goed…


Antwoord 1, autoriteit 100%

Dit is hoe ik het doe (met wat meer informatie over het laden van een afbeelding):

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel{
    private BufferedImage image;
    public ImagePanel() {
       try {                
          image = ImageIO.read(new File("image name and path"));
       } catch (IOException ex) {
            // handle exception...
       }
    }
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, this); // see javadoc for more info on the parameters            
    }
}

Antwoord 2, autoriteit 95%

Als je JPanels gebruikt, werk je waarschijnlijk met Swing. Probeer dit:

BufferedImage myPicture = ImageIO.read(new File("path-to-file"));
JLabel picLabel = new JLabel(new ImageIcon(myPicture));
add(picLabel);

De afbeelding is nu een swingcomponent. Het wordt onderworpen aan lay-outvoorwaarden zoals elk ander onderdeel.


Antwoord 3, autoriteit 16%

De manier van Fred Haslam werkt prima. Ik had echter problemen met het bestandspad, omdat ik naar een afbeelding in mijn jar wil verwijzen. Om dit te doen, gebruikte ik:

BufferedImage wPic = ImageIO.read(this.getClass().getResource("snow.png"));
JLabel wIcon = new JLabel(new ImageIcon(wPic));

Omdat ik maar een eindig aantal (ongeveer 10) afbeeldingen heb die ik met deze methode moet laden, werkt het redelijk goed. Het krijgt een bestand zonder het juiste relatieve bestandspad te hebben.


Antwoord 4, autoriteit 13%

Ik denk dat het niet nodig is om iets te subclasseren. Gebruik gewoon een Jlabel. U kunt een afbeelding in een Jlabel zetten. Verklein dus het Jlabel en vul het met een afbeelding. Het is ok. Dit is de manier waarop ik het doe.


Antwoord 5, autoriteit 7%

U kunt voorkomen dat u uw eigen Component-subklasse volledig uitrolt door de JXImagePanel-klasse uit de gratis SwingX-bibliotheken te gebruiken.

Downloaden


Antwoord 6, autoriteit 4%

JLabel imgLabel = new JLabel(new ImageIcon("path_to_image.png"));

7, Autoriteit 3%

U kunt Subclass JPANEL – hier is een uittreksel uit mijn beeldpanel, dat een afbeelding plaatst in een van de 5 locaties, boven / links, boven / rechts, midden / midden, onder / links of onderaan / rechts:

protected void paintComponent(Graphics gc) {
    super.paintComponent(gc);
    Dimension                           cs=getSize();                           // component size
    gc=gc.create();
    gc.clipRect(insets.left,insets.top,(cs.width-insets.left-insets.right),(cs.height-insets.top-insets.bottom));
    if(mmImage!=null) { gc.drawImage(mmImage,(((cs.width-mmSize.width)/2)       +mmHrzShift),(((cs.height-mmSize.height)/2)        +mmVrtShift),null); }
    if(tlImage!=null) { gc.drawImage(tlImage,(insets.left                       +tlHrzShift),(insets.top                           +tlVrtShift),null); }
    if(trImage!=null) { gc.drawImage(trImage,(cs.width-insets.right-trSize.width+trHrzShift),(insets.top                           +trVrtShift),null); }
    if(blImage!=null) { gc.drawImage(blImage,(insets.left                       +blHrzShift),(cs.height-insets.bottom-blSize.height+blVrtShift),null); }
    if(brImage!=null) { gc.drawImage(brImage,(cs.width-insets.right-brSize.width+brHrzShift),(cs.height-insets.bottom-brSize.height+brVrtShift),null); }
    }

8, Autoriteit 3%

  1. Er mogen geen enkel probleem zijn (anders dan alle algemene problemen die u mogelijk hebt met zeer grote afbeeldingen).
  2. Als je het hebt over het toevoegen van meerdere afbeeldingen aan een enkel paneel, zou ik ImageIcons gebruiken. Voor een enkele afbeelding zou ik denken aan het maken van een aangepaste subklasse van JPanelen het negeren van de paintComponent-methode om de afbeelding te tekenen.
  3. (zie 2)

Antwoord 9, autoriteit 2%

JPanelis bijna altijd de verkeerde klasse om te subklassen. Waarom zou je JComponentniet onderklassen?

Er is een klein probleem met ImageIcondoordat de constructor het lezen van de afbeelding blokkeert. Niet echt een probleem bij het laden vanuit de applicatie-jar, maar misschien als je mogelijk via een netwerkverbinding leest. Er zijn tal van voorbeelden uit het AWT-tijdperk van het gebruik van MediaTracker, ImageObserveren vrienden, zelfs in de JDK-demo’s.


Antwoord 10, autoriteit 2%

Ik doe iets soortgelijks in een privéproject waar ik aan werk. Tot nu toe heb ik zonder problemen afbeeldingen tot 1024×1024 gegenereerd (behalve geheugen) en kan ze zeer snel en zonder prestatieproblemen weergeven.

Het overschrijven van de verfmethode van de JPanel-subklasse is overdreven en vereist meer werk dan nodig is.

De manier waarop ik het doe is:

Class MapIcon implements Icon {...}

OF

Class MapIcon extends ImageIcon {...}

De code die u gebruikt om de afbeelding te genereren, bevindt zich in deze klasse. Ik gebruik een BufferedImage om op te tekenen wanneer de paintIcon() wordt aangeroepen, gebruik g.drawImvge(bufferedImage); Dit vermindert de hoeveelheid flitsen die wordt gedaan terwijl u uw afbeeldingen genereert, en u kunt het inrijgen.

Vervolgens verleng ik JLabel:

Class MapLabel extends Scrollable, MouseMotionListener {...}

Dit komt omdat ik mijn afbeelding op een scroll-paneel wil plaatsen, d.w.z. Het gedeelte van de afbeelding weergeven en laat de gebruiker zo nodig scrollen.

Dus ik gebruik een JSCrollPane om de MapLabel te houden, die alleen de Mapicon bevat.

MapIcon map = new MapIcon (); 
MapLabel mapLabel = new MapLabel (map);
JScrollPane scrollPane = new JScrollPane();
scrollPane.getViewport ().add (mapLabel);

Maar voor uw scenario (toon gewoon elke keer de hele afbeelding). U moet de MapLabel toevoegen aan de bovenste JPANEL en zorg ervoor dat u ze allemaal op de volledige grootte van de afbeelding formaat (door de GetPRFECTESIVERSIZE ()) te overschrijven.


11, Autoriteit 2%

Dit antwoord is een aanvulling op @ Shawalli’s antwoord …

Ik wilde ook een afbeelding binnen mijn pot verwijzen, maar in plaats van een bufferedimage, deed ik dit eenvoudig:

JPanel jPanel = new JPanel();      
 jPanel.add(new JLabel(new ImageIcon(getClass().getClassLoader().getResource("resource/images/polygon.jpg"))));

12, Autoriteit 2%

Maak een bronmap in uw projectdirectory, in dit geval noemde ik IT-afbeeldingen.

JFrame snakeFrame = new JFrame();
snakeFrame.setBounds(100, 200, 800, 800);
snakeFrame.setVisible(true);
snakeFrame.add(new JLabel(new ImageIcon("Images/Snake.png")));
snakeFrame.pack();

13, Autoriteit 2%

U kunt vermijden met behulp van eigen ComponentS en Swingx Library en ImageIOKlasse:

File f = new File("hello.jpg");
JLabel imgLabel = new JLabel(new ImageIcon(file.getName()));

Other episodes