Как динамически обновлять холст Java?

Проблема: я пытаюсь обновить холст новыми объектами рисования на основе действий пользователя. Холст не обновляется.

Что я сделал: пользователь взаимодействует с действием DnD, передаваемый объект достигает холста, вызывает метод обновления графики, созданный мной. И метод просто использует уже созданный графический 2D-объект и рисует изображения с его помощью. Я проверил действие DnD, объект правильно получен в классе холста, и я смог распечатать их с помощью System.out.println.

Пример кода, который имеет функцию, аналогичную моей,

Класс краски:

    import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JPanel;


public class PaintPanel extends JPanel{

    private Graphics2D drawImage;

    public PaintPanel()
    {

    }

    @Override
    public void paint(Graphics g) {
         drawImage = (Graphics2D) g;
         drawImage.setColor(Color.WHITE);
         drawImage.fillRect(0, 0, getWidth(), getHeight());
    }

    public void updateGraphics(int length,int width)
    {
        drawImage.setColor(Color.black);
        drawImage.drawRect(100, 150, length, width);
        repaint();
    }

}

класс мейнфрейма:

       import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;


public class MainPaint extends JFrame{


    public MainPaint()
    {
        setTitle("test paint");
        setSize(400,400);
        setLayout(new BorderLayout());

        final PaintPanel paintPan = new PaintPanel();
        JButton testButon = new JButton("Display shape");
        add(paintPan,BorderLayout.CENTER);
        add(testButon,BorderLayout.PAGE_END);

        testButon.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                paintPan.updateGraphics(50,50);
                repaint();
            }
        });
        setVisible(true);
    }

    public static void main(String[] args)
    {
        new MainPaint();
    }

}

person Balaram26    schedule 26.12.2012    source источник
comment
Я опубликую рабочий код как можно скорее. Я подумал, что если я опубликую то, что я сделал, это может помочь обнаружить ошибку или неправильный подход, который я сделал здесь.   -  person Balaram26    schedule 26.12.2012
comment
Я только что опубликовал рабочий пример кода проблемы. Спасибо за ответы.   -  person Balaram26    schedule 26.12.2012
comment
то, что я разместил, не является реальным кодом, а просто образцом короткого исполняемого кода, который имеет ту же проблему.   -  person Balaram26    schedule 26.12.2012


Ответы (2)


Graphics2D drawImage;  //source of the problem!

Не пытайтесь кэшировать экземпляр Graphics (или Graphics2D)! Вместо:

  1. Добавить новые объекты в список
  2. Звоните repaint().
  3. В paintComponent(Graphics) нарисуйте список объектов.

Альтернативой этому является использование BufferedImage в качестве объекта рисования. См. этот ответ для примера.


Обновление — SSCCE на основе последнего кода.

MainPaint после нажатия кнопки

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MainPaint extends JFrame {

    public MainPaint() {
        setTitle("test paint");
        setSize(400, 400);
        setLayout(new BorderLayout());

        final PaintPanel paintPan = new PaintPanel();
        JButton testButon = new JButton("Display shape");
        add(paintPan, BorderLayout.CENTER);
        add(testButon, BorderLayout.PAGE_END);

        testButon.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                paintPan.updateGraphics(50, 50);
                repaint();
            }
        });
        setVisible(true);
    }

    public static void main(String[] args) {
        new MainPaint();
    }
}

class PaintPanel extends JPanel {

    private int x, y;
    private Color color = null;

    public PaintPanel() {
        setBackground(Color.ORANGE);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D drawImage = (Graphics2D) g;
        if (color != null) {
            drawImage.setColor(color);
            drawImage.drawRect(100, 150, x, y);
        }
    }

    public void updateGraphics(int length, int width) {
        color = Color.RED;
        x = length;
        y = width;
        repaint();
    }
}

Примечание

Есть еще ряд вещей в этом коде, которые нужно изменить. Я решил остановиться на самом раннем варианте, который работал для отображения прямоугольника при нажатии кнопки.

person Andrew Thompson    schedule 26.12.2012
comment
Спасибо за ответ. Я сомневаюсь, что мы можем создать, скажем, новый прямоугольник полностью, нажав кнопку отображения изображения? - person Balaram26; 26.12.2012

Я думаю, вам нужно вызвать метод validate().

person UVM    schedule 26.12.2012
comment
где вы назвали этот метод? - person UVM; 26.12.2012
comment
Ты не правильно думаешь. Это подходит только для добавления новых компонентов (например, JPanel или JLabel), в то время как это, кажется, полностью пользовательское рисование. - person Andrew Thompson; 26.12.2012
comment
@ Эндрю Томпсон, ты прав. Код я не проходил. Но дал предложение. Это может привести к логическому вопросу - person UVM; 26.12.2012
comment
Это может привести к логическому выводу ..и свиньи могут летать. - person Andrew Thompson; 26.12.2012