Вопрос по swing, java – Динамическая графика объекта Живопись

7

Попытка выяснить лучший способ сделать это (и без пересечения каких-либо особенностей НЕ делаю того, о чем я не знаю).

Я работаю над визуальным отображением графика (различные узлы, с ребрами, соединяющими их) с кругами и линиями, чтобы представить их. Каждый узел будет добавлен во время выполнения, и я не могу это жестко закодировать. Из того, что я понимаю, все рисование должно быть выполнено в методе paint (Graphics g) - что не очень полезно, поскольку я не могу изменить параметры, и кажется, что это вызывается только при первоначальном создании?

Прямо сейчас я думал о том, чтобы он вызывал различные другие методы, передавал объект Graphics и зависел от других переменных - я решу, является ли это тем, что я даже хочу вызывать (поскольку метод paint () является единственным, который я может позвонить).

Я иду по этому поводу совершенно неправильно? Никогда не беспокоился об этом раньше.

Чтобы дать вам лучшее представление о том, чем я хочу закончить: я хочу иметь возможность передать координаты фигуры, которую я хочу добавить для узла, а затем добавить ее к тому, что у меня есть на графике. И то же самое с краями, я хочу иметь возможность пройти начальную и конечную точки линии, чтобы перекрасить поверх того, что существует в то время.

Не совсем то, что я хочу сейчас - но вы получите представление о том, что я до сих пор исправлял:

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);
    }

}

Изменить: (Ответ для Андрея)

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);
    }

}
Не смешивайте Swing (например,JFrame) и AWT (например,Canvas) составные части. ВместоCanvas, использоватьJPanel & переопределитьpaintComponent(Graphics). Andrew Thompson

Ваш Ответ

1   ответ
15

Если объекты никогда не удаляются из чертежа, используйтеBufferedImage, положи в ImageIcon в)JLabel. Когда придет время обновлять: Получите графический экземпляр изображения и нарисуйте новый элемент. Утилизация графического объекта.Вызовrepaint() на этикетке. Сохранить список нарисованных элементов. В методе краски, нарисуйте их все. Когда добавляется новый элемент, звонитеrepaint() на компоненте рендеринга.

Вот пример 1-й техники:

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);
    }
}
Дальнейший совет

Вы можете заметить, что линии выглядят довольно «неровными» и безобразными. ОBufferedImage илиJComponent имеет доступ к более полезномуGraphics2D объект (дляJComponent необходимо привести его вpaintComponent()). AGraphics2D instance принимает подсказки рендеринга, которые можно использовать для сглаживания (сглаживания) нарисованных элементов.

Вау, ладно, ты буквально отредактировал его 12 секунд назад, но собирался спросить, действительно ли ты это имел в виду: Pastebin.com / tsgVeshn Я очень быстро прочитаю то, что ты сказал. TJ Biddle
Не буду переходить по ссылке. Если он достаточно короткий, добавьте его в качестве правки. Andrew Thompson
Edited. Из любопытства - есть ли причина, по которой вы не будете переходить по ссылке для вставки? TJ Biddle
@ trashgod - Вы комментируете размещение ссылки для вставки? Вы также можете скопировать необработанный код из pastebin (плюс получите немного симпатичной подсветки синтаксиса: p) TJ Biddle
Обычно, хотя сегодня мне лень. Тем не менее, в целом, люди считают, что если код достаточно короткий, чтобы публиковать его в SO - они будут смотреть на него, если нет .. Также a) некоторые люди боятся «внешних ссылок» (хорошо - не так уж много с pastebin) & b) Если pastebin исчезнет, у нас будет код для дальнейшего использования. Лучше, если вопрос будет «самодостаточным» без «внешних зависимостей». в) См. также точку зрения Трашго Andrew Thompson

Похожие вопросы