Есть ли метод в Java для рисования круга с двойными переменными для его центра? - PullRequest
0 голосов
/ 25 января 2019

здесь я пытаюсь нарисовать круг, используя метод drawOval, и я хочу переместить его на экран с определенной скоростью.но у меня есть проблема с двойными переменными для скорости. Например, когда vx = 0,25 и vy = 0, круг просто застрял на своем месте.извините за мой плохой английский, хотя.

вот код Java, который я использую

 int x=0 , y=0;
 @Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    move();
    g.drawOval(x, y, 10, 10);
    repaint();
}
public void move() {
    x+=0.25;
    y+=0.25;
}

Ответы [ 2 ]

0 голосов
/ 25 января 2019
  • Вы должны не вызывать move из метода paintComponent!Вы никогда не знаете, когда будет вызван этот метод, и, следовательно, вы не можете должным образом контролировать скорость движения.
  • Вы должны не вызывать repaint из метода paintComponent! Никогда .Это отправит систему рисования в бесконечный цикл операций перекраски!

По вопросу:

Существует метод рисования произвольных фигур, основанный на double координатах,Об этом также подробно рассказывается в Учебник по 2D-графике .Ключ должен использовать интерфейс Shape.Для вашего конкретного примера соответствующая часть кода выглядит так:

private double x = 0;
private double y = 0;

@Override
public void paintComponent(Graphics gr)
{
    super.paintComponent(gr);
    Graphics2D g = (Graphics2D)gr;

    double radius = 5;
    g.draw(new Ellipse2D.Double(
        x - radius, y - radius, radius * 2, radius * 2));
}

То есть вы создаете экземпляр Ellipse2D, а затем просто рисуете его.

Вот MVCE, показывающий, что вы, вероятно, пытаетесь выполнить:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;

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

public class PaintWithDouble
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        PaintWithDoublePanel p = new PaintWithDoublePanel();
        f.getContentPane().add(p);
        startMoveThread(p);

        f.setSize(500, 500);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static void startMoveThread(PaintWithDoublePanel p)
    {
        Thread t = new Thread(() -> {
            while (true)
            {
                p.move();
                p.repaint();
                try
                {
                    Thread.sleep(20);
                }
                catch (InterruptedException e)
                {
                    Thread.currentThread().interrupt();
                    return;
                }
            }
        });
        t.setDaemon(true);
        t.start();
    }
}

class PaintWithDoublePanel extends JPanel
{
    private double x = 0;
    private double y = 0;

    @Override
    public void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D) gr;
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);

        double radius = 5;
        g.draw(new Ellipse2D.Double(
            x - radius, y - radius, radius * 2, radius * 2));

        g.drawString("At " + x + ", " + y, 10, 30);
    }

    public void move()
    {
        x += 0.05;
        y += 0.05;
    }

}

Отредактировано в ответ на комментарий (и прояснить некоторые вещи, которые были сказаны в других ответах):

Хотя технически правильно говорить, что «есть только целые пиксели» и «нет пикселя с координатами (0,3, 1,8)», это не означает, что дробные координаты не влияют на окончательный вид визуализированного вывода.Каждая тема становится наукой, когда вы изучаете ее достаточно долго.В частности, много исследований было посвящено вопросу о том, как улучшить визуальный внешний вид визуализируемой продукции, выходя за рамки того, что вы можете достичь с помощью тривиального Брезенхема или около того.Отправной точкой для дальнейших исследований могла бы стать статья о субпиксельном рендеринге .

Во многих случаях, как обычно, существуют компромиссы между внешним видом и производительностью рисования.Что касается Java и его возможностей 2D-рисования, эти компромиссы в основном контролируются с помощью класса RenderingHints.Например, есть RenderingHints#VALUE_STROKE_PURE, который включает субпиксельный рендеринг.Эффект показан на следующем снимке экрана:

Subpixel

Ползунок используется для изменения смещения по оси y самой правой точки горизонтальной линии с помощью -От 3 до +3 пикселей.В левом верхнем углу вы видите линию, представленную как есть.Посередине вы видите линию, увеличенную в 8 раз, чтобы лучше показать эффект: пиксели заполнены различными непрозрачностями, в зависимости от , сколько пикселей покрыто идеализированной линией шириной 1 пиксель .

Хотя, безусловно, это не относится к большинству случаев применения, здесь стоит отметить это.

Ниже приведен MCVE, который использовался для захвата экрана:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;

public class PaintWithDoubleMagnified
{
    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }

    private static void createAndShowGui()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().setLayout(new BorderLayout());

        PaintWithDoubleMagnifiedPanel p = new PaintWithDoubleMagnifiedPanel();
        f.getContentPane().add(p, BorderLayout.CENTER);

        JSlider slider = new JSlider(0, 100, 50);
        slider.addChangeListener(e -> {
            int value = slider.getValue();
            double relative = -0.5 + value / 100.0;
            p.setY(relative * 6);
        });
        f.getContentPane().add(slider, BorderLayout.SOUTH);

        f.setSize(500, 500);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

class PaintWithDoubleMagnifiedPanel extends JPanel
{
    private double y = 0;

    @Override
    public void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D) gr;

        g.drawString("At " + y, 10, 20);
        paintLine(g);

        BufferedImage image = paintIntoImage();
        g.setRenderingHint(
            RenderingHints.KEY_INTERPOLATION,
            RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
        g.scale(8.0, 8.0);
        g.drawImage(image, 0, 0, null);

    }

    public void setY(double y)
    {
        this.y = y;
        repaint();
    }

    private void paintLine(Graphics2D g)
    {
        g.setColor(Color.BLACK);
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(
            RenderingHints.KEY_STROKE_CONTROL,
            RenderingHints.VALUE_STROKE_PURE);

        Line2D line = new Line2D.Double(
            10, 30, 50, 30 + y);
        g.draw(line);

    }

    private BufferedImage paintIntoImage()
    {
        BufferedImage image = new BufferedImage(
            100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        paintLine(g);
        g.dispose();
        return image;
    }

}
0 голосов
/ 25 января 2019

Сначала обратите внимание, что система рендеринга использует int в качестве аргументов для каждого пикселя.
Так что, если p1 близко к p2 по оси x, то p1(x,y) и p2(x+1,y)
например: (0,0) и (1,0) У вас нет чего-то посередине, как (0,5,1), так как нет пикселей.
Вот почему Graphics api использует int для (x, y) координат. Графика API

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


Например. скажем хочу разместить x_points: 0, 0.5, 1
Итак 0->0, 0.5(double)->1(int), 1->2
Другие пиксели могут отображаться как 0.2->1, 0.7->2, -0.9->0
Одна карта правил учитывает весь двойной диапазон (лучше скажем in (-0.5,1]) может быть
-0.5<d<=0 -> 0, 0<d<=0.5 -> 1, 0.5<d<=1 -> 2, где d=input_x (двойной)
Это означает, что вы настраиваете системы координат в соответствии со своими потребностями

есть ли в java метод для рисования круга с двойными переменными для его центра?


НЕТ (с использованием стандартных графических интерфейсов API). Иметь только то, что предоставляется API, но вы можете визуализировать любой ввод, который вы хотели (даже на основе двойной), отрегулировав систему координат.

class MyPaint extends JPanel
{

private double x = 0, y=0;
private int width = 30, height = 30;

//adjust coordinates system
//for x in [0,1] have [0,0.1,0.2,0.3 ..] 
//from no pixel between (0,1) to 9 pixels (0,0.1, ..,1)
//0->0,0.1->1,0.2->2,0.9->9,1->10
//in that way you have full control of rendering
private double scale_x = 0.1;
//same on y as x 
private double scale_y = 0.1;
//pixel scaled on x,y
//drawing with
private int xs,ys;

@Override
public void paintComponent(Graphics g)
{
    super.paintComponent(g);
    xs = (int) (x/scale_x);
    ys = (int) (y/scale_y);
    g.drawString("Draw At: " + xs + ", " + ys + " From:" + x+","+y, 10, 30);
    g.drawOval(xs, ys, (int) (width/scale_x), (int) (height/scale_y));
}

public void move()
{
     //adjustments is better to be >= then scale(x or y) seen as absolute value
     //if need 0.01 to be display on individual pixel on x 
     //then modify scale_x = 0.01 (or even 0.001)
     x+=0.1;
     y+=0.5;
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...