Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > BufferedImage на JPanel


Автор: DimonDimon 8.12.2010, 18:50
Программа - элементарный графический редактор на подобии Pait

Реализация процесса рисования: Есть BufferredImage. 

Код

public DrawPanel(int width, int height)
    {
        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2a = image.createGraphics();
        g2a.setColor(Color.WHITE);
        g2a.fillRect(0, 0, width, height);

    }


Для того что бы нарисовать линию необходимо нажать левую клавишу мыши (это будет первая точка прямой) и затем не отпуская клавиши протянуть мышь в нужное место. Там где клавишу отпустят будет вторая точка линии. Пока клавиша нажата обработчик событий MouseMotionHandler в методе mouseDragged(MouseEvent e) перерисовывает линию на JPanel. После того как пользователь отпустит клавишу мыши линя записывается в BufferredImage, а затем BufferedImage отрисовывается на панели. 
Код

@Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawImage(image, null, 0, 0);
        g2.setColor(Color.BLACK);
        currentDrawTool.draw(g2);
    }

Код

public void mouseReleased(MouseEvent e)
        {
            Graphics2D g2 = image.createGraphics();
            g2.setColor(Color.BLACK);
            currentDrawTool.draw(g2);
        }

Код

@Override
    public void draw(Graphics2D g2)
    {
        if(line != null) g2.draw(line);
    }


Проблемма в том что есть небольшая разница между тем как отрисовывается объект Line2D на панали, и этот же Line2D сохранённый в BuffererdImage. Начальные и конечные координаты одинаковые а вот промежуточные пиксели немного смещаются.  

Добавил картинку:

user posted image

Автор: Skipy 9.12.2010, 11:06
И чем это мешает? Поставьте Antialiasing и это перестанет Вас волновать.

Автор: DimonDimon 9.12.2010, 12:16
Изображение увеличено в 8 раз. Реальная толщина линий 1 пиксель. Нужно чтобы линии были одинаковыми и без  Antialiasing. Применение Antialiasing, в данном случае, не решение проблемы, а способ её не решать. 

Автор: mgarin 9.12.2010, 13:15
Покопал на данную тему - судя по всему проблемы (если их можно так назвать) закопаны глубоко в sun методах отвечающих за отрисовку стандартных форм (таких как например линия). Плюс, если вы посмотрите, Graphics2D у BufferedImage и в методе paint() компонента немного отличаются, например Surface'ом. Вобщем я не буду гадать, ибо точно не знаю.

На вашем месте, если вам просто до "немогу" критично поправить данное несхождение, сделал бы еще 1 BufferedImage для хранения рисуемых форм.
Я так сделал в своем редакторе, но по другим причинам (надо было рисовать новые элементы на экземпляре, а не на исходнике)

Вот как-то так:
Код
public class PaintTest
{
    public PaintTest ()
    {
        final JFrame jfrm = new JFrame ();

        jfrm.setLayout ( new BorderLayout () );
        jfrm.add ( new JLabel()
        {
            private int startX = -1;
            private int startY = -1;
            private int x = -1;
            private int y = -1;

            private BufferedImage bufferedImage;
            private BufferedImage buffer;

            {
                setPreferredSize ( new Dimension ( 500, 500 ) );
                bufferedImage = new BufferedImage ( 500, 500, BufferedImage.TYPE_INT_ARGB );
                buffer = new BufferedImage ( 500, 500, BufferedImage.TYPE_INT_ARGB );

                MouseAdapter mouseAdapter = new MouseAdapter()
                {
                    public void mouseReleased ( MouseEvent e )
                    {
                        x = e.getX ();
                        y = e.getY ();

                        updateImage ();
                        Graphics2D g2d = bufferedImage.createGraphics ();
                        g2d.drawImage ( buffer, 0, 0, null );
                        g2d.dispose ();

                        x = startX = -1;
                        y = startY = -1;
                        updateImage ();

                        repaint ();
                    }

                    public void mousePressed ( MouseEvent e )
                    {
                        x = startX = e.getX ();
                        y = startY = e.getY ();
                        updateImage ();
                        repaint ();
                    }

                    public void mouseDragged ( MouseEvent e )
                    {
                        x = e.getX ();
                        y = e.getY ();
                        updateImage ();
                        repaint ();
                    }

                    private void updateImage ()
                    {
                        Graphics2D g2d = buffer.createGraphics ();
                        g2d.setBackground ( new Color ( 0, 0, 0, 0 ) );
                        g2d.clearRect ( 0, 0, 500, 500 );
                        if ( startX != -1 && startY != -1 && x != -1 && y != -1 )
                        {
                            g2d.setPaint ( Color.BLACK );
                            g2d.draw ( new Line2D.Double ( startX, startY, x, y ) );
                        }
                        g2d.dispose ();
                    }
                };
                addMouseListener ( mouseAdapter );
                addMouseMotionListener ( mouseAdapter );
            }

            public void paint ( Graphics g )
            {
                super.paint ( g );

                Graphics2D g2d = ( Graphics2D ) g;
                if ( bufferedImage != null )
                {
                    g2d.drawImage ( bufferedImage, 0, 0, null );
                }
                if ( buffer != null )
                {
                    g2d.drawImage ( buffer, 0, 0, null );
                }
            }
        } );

        jfrm.pack ();
        jfrm.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
        jfrm.setLocationRelativeTo ( null );
        jfrm.setVisible ( true );
    }

    public static void main ( String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable()
        {
            public void run ()
            {
                new PaintTest ();
            }
        } );
    }
}

Автор: DimonDimon 9.12.2010, 16:03
mgarin thnx. 

В принципе что-то такое я и предполагал. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)