我有一个使用Mandelbrot集生成图形图像的GUI。 我已经实现了一些缩放按钮,但我希望能够通过鼠标点击更改GUI的中心(让鼠标坐标为新的中心点)。 事实证明这很困难。有什么建议? 我的尝试可以在moveGraph方法中找到。
提前致谢!
package assn4_12mgs;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class MandelBrot extends JFrame{
MandelPanel mp;
double xMax = 2.26;
double xMin = -2.24;
double yMax = 2.26;
double yMin = -2.24;
double yMove, xMove;
static double ESCAPE_MODULUS = 2.0;
static int MAX_ITERATIONS = 32;
public MandelBrot(){
super();
setLayout(new BorderLayout());
setTitle("Graham's Mandelbrot GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600,700);
setResizable(false);
mp = new MandelPanel();
mp.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent evt) {
MoveGraph(evt);
}
});
JPanel panel = new JPanel(new FlowLayout());
JButton zoomIn = new JButton("+");
zoomIn.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent evt) {
ZoomIn(evt);
}
});
JButton zoomOut = new JButton("-");
zoomOut.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent evt) {
ZoomOut(evt);
}
});
JButton reset = new JButton("Reset");
reset.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent evt) {
reset(evt);
}
});
panel.add(reset, BorderLayout.WEST); ///How to change positioning?
panel.add(zoomOut, BorderLayout.EAST);
panel.add(zoomIn, BorderLayout.EAST);
add(panel, BorderLayout.SOUTH);
add(mp, BorderLayout.NORTH);
}
private void MoveGraph(MouseEvent evt){
int x = evt.getPoint().x;
int y = evt.getPoint().y;
xMove = x/100;
yMove = y/100;
mp.repaint();
}
private void ZoomIn(MouseEvent evt){
xMax /= 2;
xMin /= 2;
yMax /= 2;
yMin /= 2;
mp.repaint();
}
private void ZoomOut(MouseEvent evt){
xMax *= 2;
xMin *= 2;
yMax *= 2;
yMin *= 2;
mp.repaint();
}
private void reset(MouseEvent evt){
xMax = 2.26;
xMin = -2.24;
yMax = 2.26;
yMin = -2.24;
xMove = 0;
yMove = 0;
mp.repaint();
}
public class MandelPanel extends JPanel {
public MandelPanel() {
setPreferredSize(new Dimension(600,600));
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw here
int row, col;
ComplexNumber c, z;
double xPos, yPos;
double modulus = 0;
boolean escaped = false;
int iterations = 0;
int desiredColour;
// Calculate the scale factor to go from pixels to actual units
int height = mp.getHeight(); // drawingZone is the JPanel drawing area
int width = mp.getWidth();
double xScale = (xMax - xMin) / width; // These are min and max values in actual
double yScale = (yMax - yMin) / height; // coordinates.
Graphics2D g2D = (Graphics2D)g;
BufferedImage pretty = new BufferedImage(width, height,
BufferedImage.TYPE_3BYTE_BGR);
// Iterate through the entire panel, pixel by pixel
for (row = 0; row < height; row++) {
// Calculate the actual y position
yPos = yMax - row * yScale;// - yMove
for (col = 0; col < width; col++) {
// Calculate the actual x position
xPos = xMin + col * xScale;// + xMove;
// Create the complex number for this position
c = new ComplexNumber(xPos, yPos);
z = new ComplexNumber(0, 0);
iterations = 0;
// Iterate the fractal equation z = z*z + c
// until z either escapes or the maximum number of iterations
// is reached
do {
z = (z.multiply(z)).add(c);
modulus = z.abs();
escaped = modulus > ESCAPE_MODULUS;
iterations++;
} while (iterations < MAX_ITERATIONS && !escaped);
// Set the colour according to what stopped the above loop
if (escaped) {
desiredColour = setEscapeColour(iterations);
} else {
desiredColour = setColour(modulus);
}
pretty.setRGB(col, row, desiredColour);
} // end for
} // end for
g2D.drawImage(pretty, null, 0, 0);
//yMove = 0;
//xMove = 0;
}
}
// Sets gray level for escape situation
private static int setEscapeColour(int numIterations) {
float grayLevel = 0.5F - (float) numIterations / MAX_ITERATIONS;
grayLevel = Math.max(grayLevel, 0.1F);
return new Color(grayLevel, grayLevel, grayLevel).getRGB();
} // end setEscapeColour
// Sets colour level for interior situation
// The algorithm used here is *totally* empirical!
private static int setColour(double modulus) {
float factor = (float) (modulus / ESCAPE_MODULUS);
float incr = (float) Math.log10(factor * 5.5);
float r = Math.min(Math.abs(10.0F * incr) * factor, 1.0F);
float g = Math.min(Math.abs(6.0F * incr) * factor, 1.0F);
float b = Math.min(Math.abs(0.5F * factor + incr), 1.0F);
return new Color(r, g, b).getRGB();
} // end setColour
public static void main(String args[]){
MandelBrot manBrot = new MandelBrot();
manBrot.setVisible(true);
}
}
答案 0 :(得分:0)
我们将用户点击的点作为绘图的中心点,然后围绕该点计算窗口(上下左右一半的距离)。参见
/**
* Calculate real coordinates of the point we clicked.
*/
double xDist = Math.abs(xMax) + Math.abs(xMin);
double yDist = Math.abs(yMax) + Math.abs(yMin);
double xTr = xDist / 600.0 * ((double) e.getX());
double yTr = yDist / 700.0 * ((double) e.getY());
/**
* Calculate the window coordinates. It is relative to the point where the user clicked.
*/
xMax = xTr + xDist/2.0;
xMin = xTr - xDist/2.0;
yMax = yTr + yDist/2.0;
yMin = yTr - yDist/2.0;
**守则**
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.JOptionPane;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class MandelBrot
extends JFrame
{
public static class ComplexNumber
{
double re;
double im;
public void setRe(double re)
{
this.re = re;
}
public double re()
{
return re;
}
public void setIm(double im)
{
this.im = im;
}
public double im()
{
return im;
}
public ComplexNumber(double re, double im)
{
this.re = re;
this.im = im;
}
public ComplexNumber add(ComplexNumber c)
{
setRe(re() + c.re());
setIm(im() + c.im());
return this;
}
public ComplexNumber multiply(ComplexNumber z)
{
setRe(re()*z.re() - im()*z.im());
setIm(im()*z.re() - re()*z.im());
return this;
}
public double abs()
{
return Math.sqrt(re()*re() + im()*im());
}
}
MandelPanel mp;
double xMax = 2.26;
double xMin = -2.24;
double yMax = 2.26;
double yMin = -2.24;
double yMove, xMove;
static double ESCAPE_MODULUS = 2.0;
static int MAX_ITERATIONS = 32;
public MandelBrot()
{
super();
setLayout(new BorderLayout());
setTitle("Graham's Mandelbrot GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(600, 700);
setResizable(false);
mp = new MandelPanel();
mp.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
JOptionPane.showMessageDialog(
null,
"You clicked on a picture area (x,y): (" + e.getX() + "," + e.getY() + ")" ,
"Info",
JOptionPane.INFORMATION_MESSAGE);
double xDist = Math.abs(xMax) + Math.abs(xMin);
double yDist = Math.abs(yMax) + Math.abs(yMin);
double xTr = xDist / 600.0 * ((double) e.getX());
double yTr = yDist / 700.0 * ((double) e.getY());
xMax = xTr + xDist/2.0;
xMin = xTr - xDist/2.0;
yMax = yTr + yDist/2.0;
yMin = yTr - yDist/2.0;
System.out.format("%f %f %f %f %n", xDist, yDist, xTr, yTr);
System.out.format("%f %f %f %f %n", xMin, xMax, yMin, yMax);
mp.repaint();
}
public void mouseReleased(MouseEvent evt)
{
MoveGraph(evt);
}
});
JPanel panel = new JPanel(new FlowLayout());
JButton zoomIn = new JButton("+");
zoomIn.addMouseListener(new MouseAdapter()
{
public void mouseReleased(MouseEvent evt)
{
ZoomIn(evt);
}
});
JButton zoomOut = new JButton("-");
zoomOut.addMouseListener(new MouseAdapter()
{
public void mouseReleased(MouseEvent evt)
{
ZoomOut(evt);
}
});
JButton reset = new JButton("Reset");
reset.addMouseListener(new MouseAdapter()
{
public void mouseReleased(MouseEvent evt)
{
reset(evt);
}
});
panel.add(reset, BorderLayout.WEST); ///How to change positioning?
panel.add(zoomOut, BorderLayout.EAST);
panel.add(zoomIn, BorderLayout.EAST);
add(panel, BorderLayout.SOUTH);
add(mp, BorderLayout.NORTH);
}
private void MoveGraph(MouseEvent evt)
{
int x = evt.getPoint().x;
int y = evt.getPoint().y;
xMove = x / 100;
yMove = y / 100;
mp.repaint();
}
private void ZoomIn(MouseEvent evt)
{
xMax /= 2;
xMin /= 2;
yMax /= 2;
yMin /= 2;
mp.repaint();
}
private void ZoomOut(MouseEvent evt)
{
xMax *= 2;
xMin *= 2;
yMax *= 2;
yMin *= 2;
mp.repaint();
}
private void reset(MouseEvent evt)
{
xMax = 2.26;
xMin = -2.24;
yMax = 2.26;
yMin = -2.24;
xMove = 0;
yMove = 0;
mp.repaint();
}
public class MandelPanel
extends JPanel
{
public MandelPanel()
{
setPreferredSize(new Dimension(600, 600));
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// draw here
int row, col;
ComplexNumber c, z;
double xPos, yPos;
double modulus = 0;
boolean escaped = false;
int iterations = 0;
int desiredColour;
// Calculate the scale factor to go from pixels to actual units
int height = mp.getHeight(); // drawingZone is the JPanel drawing area
int width = mp.getWidth();
double xScale = (xMax - xMin) / width; // These are min and max values in actual
double yScale = (yMax - yMin) / height; // coordinates.
Graphics2D g2D = (Graphics2D) g;
BufferedImage pretty = new BufferedImage(width, height,
BufferedImage.TYPE_3BYTE_BGR);
// Iterate through the entire panel, pixel by pixel
for (row = 0; row < height; row++)
{
// Calculate the actual y position
yPos = yMax - row * yScale;// - yMove
for (col = 0; col < width; col++)
{
// Calculate the actual x position
xPos = xMin + col * xScale;// + xMove;
// Create the complex number for this position
c = new ComplexNumber(xPos, yPos);
z = new ComplexNumber(0, 0);
iterations = 0;
// Iterate the fractal equation z = z*z + c
// until z either escapes or the maximum number of iterations
// is reached
do
{
z = (z.multiply(z)).add(c);
modulus = z.abs();
escaped = modulus > ESCAPE_MODULUS;
iterations++;
}
while (iterations < MAX_ITERATIONS && !escaped);
// Set the colour according to what stopped the above loop
if (escaped)
{
desiredColour = setEscapeColour(iterations);
}
else
{
desiredColour = setColour(modulus);
}
pretty.setRGB(col, row, desiredColour);
} // end for
} // end for
g2D.drawImage(pretty, null, 0, 0);
//yMove = 0;
//xMove = 0;
}
}
// Sets gray level for escape situation
private static int setEscapeColour(int numIterations)
{
float grayLevel = 0.5F - (float) numIterations / MAX_ITERATIONS;
grayLevel = Math.max(grayLevel, 0.1F);
return new Color(grayLevel, grayLevel, grayLevel).getRGB();
} // end setEscapeColour
// Sets colour level for interior situation
// The algorithm used here is *totally* empirical!
private static int setColour(double modulus)
{
float factor = (float) (modulus / ESCAPE_MODULUS);
float incr = (float) Math.log10(factor * 5.5);
float r = Math.min(Math.abs(10.0F * incr) * factor, 1.0F);
float g = Math.min(Math.abs(6.0F * incr) * factor, 1.0F);
float b = Math.min(Math.abs(0.5F * factor + incr), 1.0F);
return new Color(r, g, b).getRGB();
} // end setColour
public static void main(String args[])
{
MandelBrot manBrot = new MandelBrot();
manBrot.setVisible(true);
}
}