Swing BufferedImage neu laden

Hallo Leute,

Ich hab ein Problem mit BufferedImage, was ich bis jetzt noch nicht lösen konnte.

Mein Programm läuft (grob) so ab:

Ich lese ein Bild mit File ein und lese es dann mit ImageIO.read() als BufferedImage ein.
Anschließend wird das Bild in ein ImageIcon und dieses ImageIcon dann in ein JLabel, welches sich in einer verschachtelten JScrollPane befindet, übergeben.

JScrollPane sieht so aus: JScrollPane jsp = new JScrollPane(new JLabel(imageicon));

Ich zeichne dann eine Graphics2D-Line auf dieses BufferedImage.

Bis hierhin klappt alles wunderbar.

Nur nachdem ich den Vorgang wiederhole, wird erneut auf das BufferedImage gezeichnet, welches schon "beschrieben" wurde.

Wie kann ich das BufferedImage neu laden beziehungsweise die Linie löschen?

Haben schon versucht, kurz bevor ich zeichne, das Bild neu einzulesen, aber ohne Erfolg.
Ebenso wollte ich clearRect() verwenden, aber dadurch wird ja alles durch die Hintergrundfarbe ersetzt, was mir im Endeffekt auch nichts bringt.

Für Lösungen oder Ansätze, welche mir weiterhelfen bin ich sehr dankbar!

Vielen Dank schonmal!


Grüße,

Ruben K.
 
Warum benutzt du nicht einfach ein JPanel, indessen paintComponent - Methode du das Bild zeichnest?
Java:
private JPanel imagePanel(final Image image) {
	JPanel panel = new JPanel() {
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			if(image != null) {
				g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
			}
		}
	};
	return panel;
}

Und dann:
Java:
BufferedImage image = ImageIO.read(deinFile);
JPanel imgPanel = imagePanel(image);
deineScrollPane.setViewportView(imgPanel);

Graphics2d g2 = image.createGraphics();
g2.drawString("Hallo", 30, 30);
g2.dispose();
imgPanel.repaint();
 
Warum benutzt du nicht einfach ein JPanel, indessen paintComponent - Methode du das Bild zeichnest?
Java:
private JPanel imagePanel(final Image image) {
	JPanel panel = new JPanel() {
		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			if(image != null) {
				g.drawImage(image, 0, 0, getWidth(), getHeight(), this);
			}
		}
	};
	return panel;
}

Und dann:
Java:
BufferedImage image = ImageIO.read(deinFile);
JPanel imgPanel = imagePanel(image);
deineScrollPane.setViewportView(imgPanel);

Graphics2d g2 = image.createGraphics();
g2.drawString("Hallo", 30, 30);
g2.dispose();
imgPanel.repaint();


Ich habe es genau so gemacht, aber jetzt:

-Wird das Bild erstens unscrollbar
-Das Bild ist nun gestaucht
-Die Linie wird nur noch flackernd angezeigt
-Das Grundproblem ist immer noch vorhanden.

Also kehre ich doch zu meinem Ansatz zurück.
 
Ich habe mal ein KSKB erstellt und angehängt.
Das Bild für das BufferedImage ist ebenfalls im Anhang.
Das Bild wurde zugeschnitten und in schlechter Qualität gespeichert, damit es hochgeladen werden konnte, aber das dürfte ja nun nicht stören.

Es können im Textfeld die Werte "Raum 503" und "Raum 504" verwendet werden.
 
Zuletzt bearbeitet:
Hm... OK... Ich gehe davon aus, dass das durch die Umwandlung zum KSKB so... "unstrukturiert" aussieht. Eine Möglichkeit könnte (!) sein, sich das Bild am Anfang einmal zu speichern und zu verwenden, um das originalbild wiederherzustellen
Java:
class PaintingComponent
{
    BufferedImage image;

    private BufferedImage initialImage;

    int laenge = 0;

        //Hier wird das BufferedImage für das Zeichnen gesetzt
    public void bildSetzen(BufferedImage image)
    {
        this.image = image;
        initialImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = initialImage.createGraphics();
        g.drawImage(image, 0,0, null);
        g.dispose();

    }

        //Die Methode für's Zeichnen
    public void Zeichnen()
    {
            //Das Objekt 'g' vom Typ Graphics
            //wird initialisiert
        Graphics g = image.createGraphics();
            //Das Objekt 'g' wird in ein
            //Graphics2D-Objekt gecastet
        Graphics2D g2 = (Graphics2D)g;

        g.drawImage(initialImage,0,0,null);

            //Nun wird die Farbe gesetzt
        g2.setColor(Color.BLACK);

            //Zu Testzwecken habe ich dieses Verfahren gewählt
            //Nachdem entweder "Raum 503" oder "Raum 504"
            //eingegeben oder ausgewählt wurde, wird diese Methode
            //für's Zeichnen aufgerufen.
            //Hier wird auf das BufferedImage gezeichnet
        if(laenge==0)
        {
            g2.draw(new Line2D.Double(950,710,845,710));
            g2.draw(new Line2D.Double(845,710,802,710));
            g2.draw(new Line2D.Double(802,710,720,660));
            g2.draw(new Line2D.Double(720,660,720,385));
            g2.draw(new Line2D.Double(720,385,700,264));
            g2.draw(new Line2D.Double(700,264,640,224));
            g2.draw(new Line2D.Double(640,224,640,142));
            g2.draw(new Line2D.Double(640,142,625,116));
            laenge++;
        }

        else
        {
            g2.draw(new Line2D.Double(950,710,845,710));
            g2.draw(new Line2D.Double(845,710,802,710));
            g2.draw(new Line2D.Double(802,710,720,660));
            g2.draw(new Line2D.Double(720,660,720,385));
            g2.draw(new Line2D.Double(720,385,700,264));
            g2.draw(new Line2D.Double(700,264,640,224));
            g2.draw(new Line2D.Double(640,224,640,142));
            g2.draw(new Line2D.Double(640,142,654,116));
        }

        g2.dispose();

        System.out.println("Zeichnen beenden!");
    }
}

Viel eleganter wäre (vermutlich, auf basis des wenigen was man am KSKB so sieht) den Pfad gar nicht direkt ins Bild zu malen. Stattdessen könnte man
- die kompletten Pfade jeweils als einen Path2D.Double speichern
- eine Component erstellen, die das Bild zeichnet, und darüber (in der paintComponent einfach noch dazu) den aktuellen Path2D (das ist ein Shape, also g.draw(shape))
Ähnlich wie GUI-Programmer das schon angedeutet hat. Man würde sich dafür eine eigene Klasse erstellen, die von JPanel erbt, und bei der "getPreferredSize" so überschrieben ist, dass sie die größe des Bildes zurückliefert (dann klappt's auch mit den Scrollbalken). Wenn interesse besteht (und das bis dahin kein anderer macht) kann ich da mal was zusammenbasteln.
 
Hm... OK... Ich gehe davon aus, dass das durch die Umwandlung zum KSKB so... "unstrukturiert" aussieht. Eine Möglichkeit könnte (!) sein, sich das Bild am Anfang einmal zu speichern und zu verwenden, um das originalbild wiederherzustellen
Java:
class PaintingComponent
{
    BufferedImage image;

    private BufferedImage initialImage;

    int laenge = 0;

        //Hier wird das BufferedImage für das Zeichnen gesetzt
    public void bildSetzen(BufferedImage image)
    {
        this.image = image;
        initialImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = initialImage.createGraphics();
        g.drawImage(image, 0,0, null);
        g.dispose();

    }

        //Die Methode für's Zeichnen
    public void Zeichnen()
    {
            //Das Objekt 'g' vom Typ Graphics
            //wird initialisiert
        Graphics g = image.createGraphics();
            //Das Objekt 'g' wird in ein
            //Graphics2D-Objekt gecastet
        Graphics2D g2 = (Graphics2D)g;

        g.drawImage(initialImage,0,0,null);

            //Nun wird die Farbe gesetzt
        g2.setColor(Color.BLACK);

            //Zu Testzwecken habe ich dieses Verfahren gewählt
            //Nachdem entweder "Raum 503" oder "Raum 504"
            //eingegeben oder ausgewählt wurde, wird diese Methode
            //für's Zeichnen aufgerufen.
            //Hier wird auf das BufferedImage gezeichnet
        if(laenge==0)
        {
            g2.draw(new Line2D.Double(950,710,845,710));
            g2.draw(new Line2D.Double(845,710,802,710));
            g2.draw(new Line2D.Double(802,710,720,660));
            g2.draw(new Line2D.Double(720,660,720,385));
            g2.draw(new Line2D.Double(720,385,700,264));
            g2.draw(new Line2D.Double(700,264,640,224));
            g2.draw(new Line2D.Double(640,224,640,142));
            g2.draw(new Line2D.Double(640,142,625,116));
            laenge++;
        }

        else
        {
            g2.draw(new Line2D.Double(950,710,845,710));
            g2.draw(new Line2D.Double(845,710,802,710));
            g2.draw(new Line2D.Double(802,710,720,660));
            g2.draw(new Line2D.Double(720,660,720,385));
            g2.draw(new Line2D.Double(720,385,700,264));
            g2.draw(new Line2D.Double(700,264,640,224));
            g2.draw(new Line2D.Double(640,224,640,142));
            g2.draw(new Line2D.Double(640,142,654,116));
        }

        g2.dispose();

        System.out.println("Zeichnen beenden!");
    }
}

Viel eleganter wäre (vermutlich, auf basis des wenigen was man am KSKB so sieht) den Pfad gar nicht direkt ins Bild zu malen. Stattdessen könnte man
- die kompletten Pfade jeweils als einen Path2D.Double speichern
- eine Component erstellen, die das Bild zeichnet, und darüber (in der paintComponent einfach noch dazu) den aktuellen Path2D (das ist ein Shape, also g.draw(shape))
Ähnlich wie GUI-Programmer das schon angedeutet hat. Man würde sich dafür eine eigene Klasse erstellen, die von JPanel erbt, und bei der "getPreferredSize" so überschrieben ist, dass sie die größe des Bildes zurückliefert (dann klappt's auch mit den Scrollbalken). Wenn interesse besteht (und das bis dahin kein anderer macht) kann ich da mal was zusammenbasteln.

Um Gottes Willen, es klappt!
Und ich versuche mich daran schon seit 2 Wochen.
Nun ja, man lernt nie aus.

Ich werde mich morgen mal an Path2D setzen, da ich noch nie damit gearbeitet habe.
Es wäre nett, wenn du mal ein kleines Beispiel oder einen Ansatz demnächst hier posten könntest.

Aber ich bedanke mich schon Mal bei dir, da es jetzt genau so klappt, wie es soll! 🙂
 
Hmja, es wäre gut, wenn man mehr über die ... "Gesamtstruktur" wüßte... Wie gesagt: Das KSKB sah ziemlich zusammengewürfelt aus. Aber ich werd' morgen ggf. mal was basteln.
 
Hmja, es wäre gut, wenn man mehr über die ... "Gesamtstruktur" wüßte... Wie gesagt: Das KSKB sah ziemlich zusammengewürfelt aus. Aber ich werd' morgen ggf. mal was basteln.

Nun ja, ich kann wenig sagen, da es eben sehr viel ist.
Ich könnte gerne alles gezippt hochladen, denn nur dann würde man es wirklich verstehen.

Aber es sieht wahrscheinlich auch so "schlampig" aus, weil ich erst seit 1 1/2 Jahren programmiere.
 
Ein paar compilierbare Gedanken
Java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Path2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;


public class PathViewer
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().add(new PathViewerPanel());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}


class PathInfo
{
    private String name;
    private Shape shape;
    private Paint paint;

    public PathInfo(String name, Shape shape, Paint paint)
    {
        this.name = name;
        this.shape = shape;
        this.paint = paint;
    }
    
    public String getName()
    {
        return name;
    }
    public Shape getShape()
    {
        return shape;
    }
    public Paint getPaint()
    {
        return paint;
    }

    @Override
    public String toString()
    {
        return name;
    }
}


class PathInfoPaintPanel extends JPanel
{
    private BufferedImage image;
    private List<PathInfo> pathInfos = new ArrayList<PathInfo>();
    
    public PathInfoPaintPanel(BufferedImage image)
    {
        this.image = image;
    }
    
    public Dimension getPreferredSize()
    {
        if (isPreferredSizeSet())
        {
            return super.getPreferredSize();
        }
        return new Dimension(image.getWidth(), image.getHeight());
    }
   
    
    public void addPathInfo(PathInfo pathInfo)
    {
        pathInfos.add(pathInfo);
        repaint();
    }
    
    public void removePathInfo(PathInfo pathInfo)
    {
        pathInfos.remove(pathInfo);
        repaint();
    }
    
    public void clearPathInfos()
    {
        pathInfos.clear();
        repaint();
    }
    
    @Override
    protected void paintComponent(Graphics graphics)
    {
        super.paintComponent(graphics);
        Graphics2D g = (Graphics2D) graphics;
        g.drawImage(image, 0, 0, null);
        for (PathInfo pathInfo : pathInfos)
        {
            g.setPaint(pathInfo.getPaint());
            g.draw(pathInfo.getShape());
        }
    }
}
 
class PathViewerPanel extends JPanel
{
    private List<PathInfo> pathInfos = new ArrayList<PathInfo>();
    
    public PathViewerPanel()
    {
        createDummyPaths();
        
        setLayout(new BorderLayout());
        
        BufferedImage image = null;
        try
        {
            image = ImageIO.read(new File("01_Hauptebene.jpg"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        final PathInfoPaintPanel paintPanel = new PathInfoPaintPanel(image);
        
        JScrollPane scrollPane = new JScrollPane(paintPanel);
        add(scrollPane, BorderLayout.CENTER);
        
        JPanel p = new JPanel(new BorderLayout());
        final JComboBox roomComboBox = new JComboBox(pathInfos.toArray());
        roomComboBox.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                paintPanel.clearPathInfos();
                Object object = roomComboBox.getSelectedItem();
                PathInfo pathInfo = (PathInfo)object;
                paintPanel.addPathInfo(pathInfo);
            }
        });
        roomComboBox.setSelectedIndex(0);
        p.add(roomComboBox, BorderLayout.WEST);
        add(p, BorderLayout.NORTH);
    }
    
    private void createDummyPaths()
    {
        Path2D path0 = new Path2D.Double();
        path0.moveTo(950,710);
        path0.lineTo(845,710);
        path0.lineTo(802,710);
        path0.lineTo(720,660);
        path0.lineTo(720,385);
        path0.lineTo(700,264);
        path0.lineTo(640,224);
        path0.lineTo(640,142);
        path0.lineTo(625,116);
        pathInfos.add(new PathInfo("Raum 503", path0, Color.BLACK));

        Path2D path1 = new Path2D.Double();
        path1.moveTo(950,710);
        path1.lineTo(845,710);
        path1.lineTo(802,710);
        path1.lineTo(720,660);
        path1.lineTo(720,385);
        path1.lineTo(700,264);
        path1.lineTo(640,224);
        path1.lineTo(640,142);
        path1.lineTo(654,116);
        pathInfos.add(new PathInfo("Raum 504", path1, Color.BLACK));
    }
}
 

Zurück
Oben