Java уменьшить время между интервалами mouseMotionListener - PullRequest
0 голосов
/ 18 октября 2018

Я хочу создать простую программу рисования в Java, которая в настоящее время рисует только линию, используя Graphics.fillOval() и mouseMotionListener().Проблема в том, что при быстром перемещении мыши линия становится менее четкой, а овалы (в данном случае кружки) расходятся.

Вот код:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Drawing 
{
     private JFrame window;
     private Graphics g;
     public Drawing()
     {
        window=new JFrame();
        window.setTitle("Paint_window");
        window.setSize(1000,700);
        window.setVisible(true);
        window.setDefaultCloseOperation(window.EXIT_ON_CLOSE);
        g=window.getGraphics();
        window.addMouseMotionListener(new MouseMotionAdapter()
            {
                public void mouseDragged(MouseEvent e)
                {
                 if(SwingUtilities.isLeftMouseButton(e)
                {
                        g.fillOval((int)e.getX(),(int)e.getY(),10,10);
                    }
                }
            });
    }
}

Есть лиспособ улучшить это или лучший путь к этому?

1 Ответ

0 голосов
/ 18 октября 2018
g=window.getGraphics();

Прежде всего, вы не должны использовать getGraphics () компонента.Любая нарисованная вами картина будет временной и будет стерта в первый раз, когда Swing определит, что компонент необходимо перекрасить.В приведенном выше примере просто попробуйте изменить размер фрейма, чтобы увидеть это.

Правильный способ сделать пользовательское рисование - переопределить метод JPanel paintComponent(...) и добавить панель к фрейму.См. Custom Painting для получения дополнительной информации.

Проблема в том, что при быстром перемещении мыши линия становится менее точной, а овалы (в данном случае кружки) расходятся

Вы не сможете генерировать событие для каждого пикселя, на котором движется мышь.

Вместо этого вам нужно иметь возможность "рисовать линию" между последовательными точками, создаваемыми при перетаскивании.мышь.

Таким образом, вам нужно сохранить каждую точку в ArrayList и в пользовательском коде рисования перебрать все точки и нарисовать линию.

Базовый пример для начала:

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;

class DrawingPanel extends JPanel
{
    private ArrayList<ArrayList<Point>> previous = new ArrayList<ArrayList<Point>>();
    private ArrayList<Point> current = new ArrayList<Point>();
    private BasicStroke basicStroke;

    public DrawingPanel(int strokeSize)
    {
        basicStroke = new BasicStroke(strokeSize, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);

        MouseAdapter ma = new MouseAdapter()
        {
            @Override
            public void mousePressed(MouseEvent e)
            {
                current.add( new Point(e.getX(), e.getY()) );
            }

            @Override
            public void mouseDragged(MouseEvent e)
            {
                current.add( new Point(e.getX(), e.getY()) );
                repaint();
            }

            @Override
            public void mouseReleased(MouseEvent e)
            {
                if (current.size() > 1)
                {
                    previous.add( current );
                }

                current = new ArrayList<Point>();
            }
        };

        addMouseMotionListener( ma );
        addMouseListener( ma );
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke( basicStroke );

        //  Paint lines from previous drags

        for (int i = 0; i < previous.size(); i++)
        {
            drawLines(g, previous.get(i));
        }

        //  Paint line from current drag

        drawLines(g, current);
    }

    private void drawLines(Graphics g, ArrayList<Point> points)
    {
        for (int i = 0; i < points.size() - 1; i++)
        {
            int x = (int) points.get(i).getX();
            int y = (int) points.get(i).getY();
            int x2 = (int) points.get(i + 1).getX();
            int y2 = (int) points.get(i + 1).getY();
            g.drawLine(x, y, x2, y2);
        }
    }

    private static void createAndShowGUI()
    {
        JFrame frame = new JFrame("Drawing Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new DrawingPanel(15));
        frame.setSize(400, 400);
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args) throws Exception
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}

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

Другой подход - нарисовать BufferedImage, а затем нарисовать BufferedImage на панели.,Вы можете проверить Пользовательские подходы к рисованию для примера этого подхода.

...