8 Stimmen

Dynamisches Malen von Grafikobjekten

Ich versuche herauszufinden, wie ich das am besten anstellen kann (und zwar ohne irgendwelche spezifischen DO NOTs zu verletzen, von denen ich nichts weiß).

Ich arbeite an der visuellen Darstellung eines Graphen (verschiedene Knoten, mit Kanten, die sie verbinden) mit Kreisen und Linien, um diese darzustellen. Jeder Knoten wird während der Laufzeit hinzugefügt werden und ich kann nicht hardcode dies. Von dem, was ich verstehe, alle Malerei muss in der paint(Graphics g)-Methode getan werden - das ist nicht so hilfreich, da ich nicht sein kann, ändern Sie die Parameter und es scheint, dass dies nur während der ersten Erstellung aufgerufen wird?

Im Moment habe ich darüber nachgedacht, verschiedene andere Methoden aufzurufen, das Graphics-Objekt zu übergeben und von anderen Variablen abhängig zu machen - ich werde entscheiden, ob ich das überhaupt aufrufen möchte (da die paint()-Methode die einzige ist, die ich aufrufen kann).

Gehe ich das völlig falsch an? Ich habe mich noch nie damit befasst.

Um Ihnen eine bessere Vorstellung davon zu geben, was ich am Ende haben möchte: Ich möchte in der Lage sein, die Koordinaten der Form, die ich für den Knoten hinzufügen möchte, zu übergeben und sie dann zu dem hinzuzufügen, was ich bisher im Diagramm habe. Und dann dasselbe mit den Kanten, ich möchte in der Lage sein, den Anfangs- und Endpunkt der Linie zu übergeben, um sie über alles, was zu diesem Zeitpunkt vorhanden ist, neu zu malen.

Das ist nicht genau das, was ich im Moment will - aber Sie können sich ein Bild davon machen, was ich bisher zusammengeschustert habe:

import java.awt.*;
import javax.swing.*;
public class MyCanvas extends Canvas
{
    public MyCanvas()
    {
    }
    public void paint(Graphics graphics)
    {
        // Keep this until I figured out if it's painted on load or not.
        graphics.drawLine(10, 20, 350, 380);
    }
    public static void main(String[] args)
    {
        MyCanvas canvas = new MyCanvas();
        JFrame frame = new JFrame();
        int vertexes = 0;
        // Change this next part later to be dynamic.
        vertexes = 10;
        int canvasSize = vertexes * vertexes;
        frame.setSize(canvasSize, canvasSize);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(canvas);
        frame.setVisible(true);
    }
    public void drawNode(int x, int y, Graphics g)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5 
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            g.setColor(Color.white);
            g.fillOval(xLoc, yLoc, 8, 8);
            g.drawOval(xLoc, yLoc, 8, 8);
    }
    public void drawArc(int x, int y, int xx, int yy, Graphics g)
    {
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            int xxLoc = (xx*10) - 5;
            int yyLoc = (yy*10) - 5;
            g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
    }

}

Bearbeiten: (Antwort für Andrew)

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MyCanvas extends JPanel
{

    public MyCanvas() {

    }
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    }

    public static void main(String[] args)
    { 
        int vertexes = 0;
        // Change this next part later to be dynamic.
        vertexes = 10;
        int canvasSize = vertexes * vertexes;

        JFrame frame = new JFrame();
        JLabel label = new JLabel();
        BufferedImage bImage = new BufferedImage(canvasSize, canvasSize, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = bImage.createGraphics();
        g2d.drawLine(50, 50, 300, 300);
        ImageIcon iIcon = new ImageIcon(bImage); 
        label.setIcon(iIcon);
        frame.add(label);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        g2d = drawNode(1,1,g2d);
        label.repaint();
    }

    public static Graphics2D drawNode(int x, int y,Graphics2D g2d)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5 
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            g2d.setColor(Color.white);
            g2d.fillOval(xLoc, yLoc, 8, 8);
            g2d.drawOval(xLoc, yLoc, 8, 8);
            return g2d;
    }
    public static void drawArc(int x, int y, int xx, int yy)
    {
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            int xxLoc = (xx*10) - 5;
            int yyLoc = (yy*10) - 5;
           // g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
    }

}

18voto

Andrew Thompson Punkte 166383

Hierfür gibt es verschiedene Strategien, die Sie verfolgen können.

  1. Wenn die Objekte nach ihrer Fertigstellung nie aus der Zeichnung entfernt werden, verwenden Sie eine BufferedImage , in eine ( ImageIcon in a) JLabel . Wenn es Zeit für eine Aktualisierung ist:
    1. Holt die Grafikinstanz des Bildes und zeichnet das neue Element.
    2. Entsorgen Sie das Grafikobjekt.
    3. Rufen Sie an. repaint() auf dem Etikett.
  2. Führen Sie eine Liste der gezeichneten Elemente. In der Paint-Methode malen Sie sie alle. Wenn ein neues Element hinzugefügt wird, rufen Sie repaint() auf die Rendering-Komponente.

Hier ein Beispiel für die 1. Technik:

MyCanvas

import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;

public class MyCanvas
{
    JLabel view;
    BufferedImage surface;
    Random random = new Random();

    public MyCanvas()
    {
        surface = new BufferedImage(600,400,BufferedImage.TYPE_INT_RGB);
        view = new JLabel(new ImageIcon(surface));
        Graphics g = surface.getGraphics();
        g.setColor(Color.ORANGE);
        g.fillRect(0,0,600,400);
        g.setColor(Color.BLACK);
        // Keep this until I figured out if it's painted on load or not.
        g.drawLine(10, 20, 350, 380);
        g.dispose();

        ActionListener listener = new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                addNewElement();
            }
        };
        Timer timer = new Timer(200, listener);
        timer.start();
    }

    public void addNewElement() {
        boolean drawArc = random.nextBoolean();
        int x = random.nextInt(60);
        int y = random.nextInt(40);
        Graphics g = surface.getGraphics();
        if (drawArc) {
            g.setColor(Color.BLUE);
            int xx = random.nextInt(60);
            int yy = random.nextInt(40);
            drawArc(x,y,xx,yy,g);
        } else {
            drawNode(x,y,g);
        }
        g.dispose();
        view.repaint();
    }

    public static void main(String[] args)
    {
        MyCanvas canvas = new MyCanvas();
        JFrame frame = new JFrame();
        int vertexes = 0;
        // Change this next part later to be dynamic.
        vertexes = 10;
        int canvasSize = vertexes * vertexes;
        frame.setSize(canvasSize, canvasSize);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(canvas.view);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public void drawNode(int x, int y, Graphics g)
    {
            // Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            g.setColor(Color.white);
            g.fillOval(xLoc, yLoc, 8, 8);
            g.drawOval(xLoc, yLoc, 8, 8);
    }

    public void drawArc(int x, int y, int xx, int yy, Graphics g)
    {
            int xLoc = (x*10) - 5;
            int yLoc = (y*10) - 5;
            int xxLoc = (xx*10) - 5;
            int yyLoc = (yy*10) - 5;
            g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
    }
}

Weiterer Tipp

Sie werden feststellen, dass die Linien ziemlich "zackig" und hässlich aussehen. Sowohl die BufferedImage oder eine JComponent hat Zugang zu den nützlicheren Graphics2D Objekt (für das JComponent ist es notwendig, sie in paintComponent() ). A Graphics2D Instanz akzeptiert Rendering-Hinweise, die zum Glätten (Dithering) der gezeichneten Elemente verwendet werden können.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X