Java 如何画一条有方向和固定长度的线
当我提供2个点和一个角度(方向)时,我想画一条线直到屏幕边缘。例如,如果第一个鼠标点是4,4,下一个鼠标点是6,6,那么从这些点可以知道直线的方向是东北方向,那么应该从4,4到屏幕末端绘制一条直线,并穿过6,6。注意:当鼠标达到6,6时,应在鼠标仍处于6,6时,将线绘制到屏幕边缘Java 如何画一条有方向和固定长度的线,java,swing,awt,Java,Swing,Awt,当我提供2个点和一个角度(方向)时,我想画一条线直到屏幕边缘。例如,如果第一个鼠标点是4,4,下一个鼠标点是6,6,那么从这些点可以知道直线的方向是东北方向,那么应该从4,4到屏幕末端绘制一条直线,并穿过6,6。注意:当鼠标达到6,6时,应在鼠标仍处于6,6时,将线绘制到屏幕边缘 这也应该在MouseMoved中完成,最好不要点击,这意味着两个鼠标点都是从MouseMoved中获得的。我花了一整天的时间试图得到一个输出,但没有用。你需要把你的问题分解一下 首先,您需要能够计算两点之间的角度 d
这也应该在MouseMoved中完成,最好不要点击,这意味着两个鼠标点都是从MouseMoved中获得的。我花了一整天的时间试图得到一个输出,但没有用。你需要把你的问题分解一下 首先,您需要能够计算两点之间的角度
double angle = Math.atan2(toY - fromY, toX - fromX);
哇,那有点容易(谢谢)
接下来,我们需要能够计算圆半径上的一个点(好吧,这听起来可能很奇怪,但这是我能想到的最简单的解决方案…我知道我能解决它,谢谢)
我们要做的是,创建一个如此大的圆,它扩展到可见的帧边界之外,并将我们的线画出来!轻松点
与中心锚点。。。。
和MouseMotionListener
支持
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Point from;
private Point clickTo;
private Point to;
public TestPane() {
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
from = new Point(getWidth() / 2, getHeight() / 2);
to = e.getPoint();
clickTo = new Point(to);
double angle = Math.atan2(to.y - from.y, to.x - from.x);
int radius = Math.max(getWidth(), getHeight()) * 2;
to.x = (int) (Math.round(from.x + (radius * Math.cos(angle))));
to.y = (int) (Math.round(from.y + (radius * Math.sin(angle))));
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (from != null) {
g2d.setColor(Color.RED);
g2d.fillOval(from.x - 4, from.y - 4, 8, 8);
if (to != null) {
g2d.setColor(Color.GREEN);
g2d.fillOval(clickTo.x - 4, clickTo.y - 4, 8, 8);
g2d.setColor(Color.BLUE);
g2d.drawLine(from.x, from.y, to.x, to.y);
}
}
g2d.dispose();
}
}
}
还有一件小事,我需要线条有一个灵活的长度,我的意思是它应该在屏幕内,因为这是一个矩形,那么宽度和高度会不同,固定长度会带来问题,因为它在某些部分会长,而在其他部分会短,知道吗
因此,您需要知道直线与矩形边界的碰撞位置,这基本上归结为直线碰撞检测(因为矩形只有四条直线)
所以
我将这个想法稍微进一步,提出了一个方法,该方法使用了一个矩形和一个Line2D
,并返回冲突点所在的Point2D
,或者如果没有发生冲突,则返回null
(在这种情况下,我们应该保证99.9%的冲突)
因此,要知道这条线的投影超出了组件的可见边界(这对你的另一个问题很有帮助),还要知道这条线对内部边界感兴趣的地方,你需要把问题分解一下
首先,您需要能够计算两点之间的角度
double angle = Math.atan2(toY - fromY, toX - fromX);
哇,那有点容易(谢谢)
接下来,我们需要能够计算圆半径上的一个点(好吧,这听起来可能很奇怪,但这是我能想到的最简单的解决方案…我知道我能解决它,谢谢)
我们要做的是,创建一个如此大的圆,它扩展到可见的帧边界之外,并将我们的线画出来!轻松点
与中心锚点。。。。
和MouseMotionListener
支持
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Point from;
private Point clickTo;
private Point to;
public TestPane() {
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
from = new Point(getWidth() / 2, getHeight() / 2);
to = e.getPoint();
clickTo = new Point(to);
double angle = Math.atan2(to.y - from.y, to.x - from.x);
int radius = Math.max(getWidth(), getHeight()) * 2;
to.x = (int) (Math.round(from.x + (radius * Math.cos(angle))));
to.y = (int) (Math.round(from.y + (radius * Math.sin(angle))));
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (from != null) {
g2d.setColor(Color.RED);
g2d.fillOval(from.x - 4, from.y - 4, 8, 8);
if (to != null) {
g2d.setColor(Color.GREEN);
g2d.fillOval(clickTo.x - 4, clickTo.y - 4, 8, 8);
g2d.setColor(Color.BLUE);
g2d.drawLine(from.x, from.y, to.x, to.y);
}
}
g2d.dispose();
}
}
}
还有一件小事,我需要线条有一个灵活的长度,我的意思是它应该在屏幕内,因为这是一个矩形,那么宽度和高度会不同,固定长度会带来问题,因为它在某些部分会长,而在其他部分会短,知道吗
因此,您需要知道直线与矩形边界的碰撞位置,这基本上归结为直线碰撞检测(因为矩形只有四条直线)
所以
我将这个想法稍微进一步,提出了一个方法,该方法使用了一个矩形和一个Line2D
,并返回冲突点所在的Point2D
,或者如果没有发生冲突,则返回null
(在这种情况下,我们应该保证99.9%的冲突)
因此,要知道在组件的可见边界之外有一条线的投影(这对你的另一个问题很有帮助),并且要知道这条线对内部边界感兴趣的地方你能发布一些代码吗?你试过什么吗?你被困在哪里?为什么你需要两个点和一个角度?你需要一个点和一个角度,或者两个点来画一条线…所以基本上你有一个“给定角度的圆上的点是什么”的问题。从理解如何解决这个问题开始。当您知道如何操作时,创建一个半径为Math.max(width/2,height/2)
的虚拟圆,计算给定角度的圆上的点,并绘制一条直线it@elyashiv添加了一些代码你能发布一些代码吗?你试过什么吗?你被困在哪里?为什么你需要两个点和一个角度?你需要一个点和一个角度,或者两个点来画一条线…所以基本上你有一个“给定角度的圆上的点是什么”的问题。从理解如何解决这个问题开始。当您知道如何操作时,创建一个半径为Math.max(width/2,height/2)
的虚拟圆,计算给定角度的圆上的点,并绘制一条直线it@elyashiv添加了一些代码,非常感谢,很抱歉,当数学遇到java时,我迷路了。一个小问题。在我的代码中使用了它,它起了作用,但问题是跳跃时的角度,因此直线不准确,而且我从鼠标移动中获得鼠标点。如何使角度包含更多数字,我的意思是不跳跃,而不是90、45、270。但是,它可以像这样91,92,93…等等,那么有可能用一个矩形代替一个圆吗?用一个矩形代替一个圆,我想说可能不会,因为我基本上是相同的问题,除了现在你加入了一些碰撞检测。角度以弧度为单位,应该非常准确。非常感谢,很抱歉,当数学遇到java时,我迷路了。一个小问题。在我的代码中使用了它,它起了作用,但问题是跳跃时的角度,因此直线不准确,而且我从鼠标移动中获得鼠标点。如何使角度包含更多数字,我的意思是不跳跃,而不是90、45、270。但它却可以
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Point from;
private Point clickTo;
private Point to;
public TestPane() {
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
from = new Point(getWidth() / 2, getHeight() / 2);
to = e.getPoint();
clickTo = new Point(to);
double angle = Math.atan2(to.y - from.y, to.x - from.x);
int radius = Math.max(getWidth(), getHeight()) * 2;
to.x = (int) (Math.round(from.x + (radius * Math.cos(angle))));
to.y = (int) (Math.round(from.y + (radius * Math.sin(angle))));
repaint();
}
});
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public Point2D getIntersectionPoint(Line2D line1, Line2D line2) {
if (!line1.intersectsLine(line2)) {
return null;
}
double px = line1.getX1(),
py = line1.getY1(),
rx = line1.getX2() - px,
ry = line1.getY2() - py;
double qx = line2.getX1(),
qy = line2.getY1(),
sx = line2.getX2() - qx,
sy = line2.getY2() - qy;
double det = sx * ry - sy * rx;
if (det == 0) {
return null;
} else {
double z = (sx * (qy - py) + sy * (px - qx)) / det;
if (z == 0 || z == 1) {
return null; // intersection at end point!
}
return new Point2D.Float(
(float) (px + z * rx), (float) (py + z * ry));
}
} // end intersection line-line
public Point2D getIntersectionPoint(Line2D line, Rectangle bounds) {
Point2D top = getIntersectionPoint(line, new Line2D.Double(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y));
Point2D bottom = getIntersectionPoint(line, new Line2D.Double(bounds.x, bounds.y + bounds.height, bounds.x + bounds.width, bounds.y + bounds.height));
Point2D left = getIntersectionPoint(line, new Line2D.Double(bounds.x, bounds.y, bounds.x, bounds.y + bounds.height));
Point2D right = getIntersectionPoint(line, new Line2D.Double(bounds.x + bounds.width, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height));
return top != null ? top
: bottom != null ? bottom
: left != null ? left
: right != null ? right
: null;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
Rectangle bounds = new Rectangle(50, 50, getWidth() - 100, getHeight() - 100);
g2d.draw(bounds);
if (from != null) {
g2d.setColor(Color.RED);
g2d.fillOval(from.x - 4, from.y - 4, 8, 8);
if (to != null) {
g2d.setColor(Color.GREEN);
g2d.fillOval(clickTo.x - 4, clickTo.y - 4, 8, 8);
Line2D line = new Line2D.Double(from, to);
g2d.setColor(Color.BLUE);
g2d.draw(line);
Point2D intersectPoint = getIntersectionPoint(line, bounds);
g2d.setColor(Color.MAGENTA);
g2d.fill(new Ellipse2D.Double(intersectPoint.getX() - 4, intersectPoint.getY() - 4, 8, 8));
g2d.draw(new Line2D.Double(from, intersectPoint));
}
}
g2d.dispose();
}
}
}