java - 我做错了什么导致此图表滚动不正确?
问题描述
我正在尝试创建一个简单的 Java 程序,该程序将数学函数作为输入并在 JPanel 中显示 2D(x 和 y)图。我的图表最初显示正确。我尝试向画布添加滚动(我调用了 JPanel 子类,我创建了一个 GraphCanvas),我的意思是当鼠标在画布上拖动时,2D 平面也会滚动,并且图形会针对新显示的区域进行更新。为了显示这个实际函数,我使用了一个 Path2D 对象,该对象由连接足够多点的线段组成,以便图形处于最大分辨率,并且我一直在使用 AffineTransforms 来转换路径。值得注意的是,到目前为止,我只使用 f(x) 形式的函数测试了程序,而不是参数,即使我 我们在 GraphedInstance 类中为参数函数创建了一个类和支持代码。我不想包含项目的所有代码,但我将其推送到 GitHub 存储库这里(我对 GitHub 的工作原理知之甚少,但这应该是正确的)。
我的问题是,目前,每当我尝试滚动图形时,该函数都会做自己的事情,并且无法与初始化的部分正确连接。它没有正确显示新生成的部分。
我已经对其进行了一些工作,并通过等待转换描述函数的路径,直到我向其中添加了新部分,显着改善了问题,但它仍然无法正确连接。
这是应该创建函数路径的新部分并将其缝合在一起的方法,我认为问题可能出在此处。这个和项目的其余部分也可以在 GitHub 存储库中找到。另外,对于任何乱七八糟的代码和/或缺少评论,我很抱歉,我只是大学一年级的学生,并没有真正接受过任何正式的 Java 培训,我只是在前进的过程中学会了它。我很乐意接受任何建议或更好的方法来做任何事情!
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
public class Minimal {
private static int[] lastPointer = new int[2];
private static double xMin, xMax, yMin, yMax;
private static double xScale, yScale;
private static double minXGraphed, maxXGraphed;
public static Path2D.Double function;
//The frame enclosing the graphing canvas
private static JFrame frame;
//The graphing canvas
private static JPanel canvas = new JPanel() {
private static final int DEFAULT_CANVAS_SIZE = 600;
//Ensures the frame initialized to the right size
@Override
public Dimension getPreferredSize() {
return new Dimension(DEFAULT_CANVAS_SIZE, DEFAULT_CANVAS_SIZE);
}
//Paints the graph whenever it needs updating
@Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paintComponent(g2);
xScale = getWidth() / (xMax - xMin);
yScale = getHeight() / (yMax - yMin);
g2.setColor(Color.BLUE);
try {
g2.draw(function);
} catch (NullPointerException e) {
e.printStackTrace();
}
}
};
/**
* I'm using the function y = exp(x) as an example. Feel free to replace it.
* @param x the x-value
* @return exp(x), the y-value
*/
private static double getYVal(double x) {
return Math.exp(x);
}
//Initializes the function path
public static void initPath() {
final double STEP_X = (xMax - xMin) / canvas.getWidth();
function = new Path2D.Double();
double x = xMin;
double y = getYVal(x);
function.moveTo(getGraphX(x), getGraphY(y));
for(x = xMin + STEP_X; x <= xMax; x += STEP_X) {
y = getYVal(x);
function.lineTo(getGraphX(x), getGraphY(y));
}
}
/**
* Gets the pixel x-coordinate on the canvas
* that corresponds to a given x-value of the function
* @param x the x-value of the function
* @return the adjusted x-coordinate
*/
private static int getGraphX(double x) {
return (int) (canvas.getWidth() * (x - xMin) / (xMax - xMin));
}
//Same thing as getGraphX except for y-coords
private static int getGraphY(double y) {
return (int) (canvas.getHeight() * (yMax - y) / (yMax - yMin));
}
/*
* This is probably where the problem is, this extends the path so that it
* covers the entire visible range
*/
public static void updateFunctionBounds(double dx) {
double newXMin = xMin - dx / xScale;
double newXMax = xMax - dx / xScale;
final int WIDTH = canvas.getWidth();
final double STEP_X = (xMax - xMin) / WIDTH;
double drawTo;
if((drawTo = newXMin) < xMin && drawTo < minXGraphed) {
minXGraphed = drawTo;
double x = drawTo;
function.moveTo(getGraphX(x), getGraphY(getYVal(x)));
for(x = drawTo + STEP_X; x < xMin; x += STEP_X) {
function.lineTo(getGraphX(x), getGraphY(getYVal(x)));
}
x = xMin;
function.lineTo(getGraphX(x), getGraphY(getYVal(x)));
} else if((drawTo = newXMax) > xMax && drawTo > maxXGraphed) {
maxXGraphed = drawTo;
double x = xMax;
function.moveTo(getGraphX(x), getGraphY(getYVal(x)));
for(x = xMax + STEP_X; x < drawTo; x += STEP_X) {
function.lineTo(getGraphX(x), getGraphY(getYVal(x)));
}
x = drawTo;
function.lineTo(getGraphX(x), getGraphY(getYVal(x)));
}
}
public static void main(String[] args) {
initBounds();
initFrame();
}
//Initializes the graph boundaries. Feel free to change this
private static void initBounds() {
xMin = yMin = minXGraphed = -10;
xMax = yMax = maxXGraphed = 10;
}
//Initializes the frame and a MouseAdapter that controls the scrolling
private static void initFrame() {
MouseAdapter adapter = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
super.mousePressed(e);
lastPointer[0] = e.getX();
lastPointer[1] = e.getY();
}
@Override
public void mouseDragged(MouseEvent e) {
super.mouseDragged(e);
AffineTransform t = new AffineTransform();
double dx = e.getX() - lastPointer[0];
double dy = e.getY() - lastPointer[1];
t.translate(dx, dy);
updateFunctionBounds(dx);
function.transform(t);
xMin -= dx / xScale;
xMax -= dx / xScale;
yMin -= dy / yScale;
yMax -= dy / yScale;
canvas.repaint();
lastPointer[0] = e.getX();
lastPointer[1] = e.getY();
}
};
canvas.addMouseListener(adapter);
canvas.addMouseMotionListener(adapter);
frame = new JFrame("Minimal Reproducible Approach");
frame.setContentPane(canvas);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
initPath();
canvas.repaint();
}
}
如果它工作正常,拼接将是无缝的,并且当鼠标指针在画布上拖动时,该功能将平滑滚动,有点像在 Desmos 中所做的那样。实际上,它不会保留正确的高度(y 值),并且在所有情况下都不会实际连接到先前的段。
感谢您的任何帮助!
编辑:我已将代码更新为我认为的最小可重现示例。
解决方案
推荐阅读
- flutter - 如何在底部导航栏颤动中制作矩形缺口曲线
- windows - Windows 机器上文件系统操作的真实定义
- spring-boot - 如何使用规范映射相关实体属性
- java - 重新启动应用程序后,Recyclerview 不会从 json 文件中更新数据
- java - Gson RuntimeTypeAdapterFactory 在反序列化后将我的 userType 转换为 null
- python - python合并dfs并转向字典
- angular - 用户关闭浏览器时的 Api 调用
- go - Golang中谷歌云功能部署错误
- javascript - npm 不下载 .d.ts 文件
- laravel - 如何使用 xampp 在本地运行多个 laravel 应用程序并使它们可供我本地网络上的其他 PC 访问