JPanel problems with drawing ovals - java

I've created an application that draws a random number of ovals (with random sizes and colors) with JPanel and JFrame (Java 8 installed in Ubuntu 16.04). Everything seems to be right... but no oval is draw when I execute the code. I receave just a blank screen (JFrame appears, but only blank).
It have 3 classes: MyOval, DrawPanel and DrawTest.
MyOval Class
package drawingovals;
import java.awt.Color;
import java.awt.Graphics;
public class MyOval {
private int x1;
private int y1;
private int x2;
private int y2;
private Color myColor;
private boolean isFilled;
public MyOval(int x1, int y1, int x2, int y2, Color color, boolean isFilled) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.x2 = x2;
myColor = color;
this.isFilled = isFilled;
}
public int getUpperLeftX(){
return x1;
}
public int getUpperLeftY(){
return y1;
}
public int getWidth(){
return x2 - x1;
}
public int getHeight() {
return y2 - y1;
}
public String getColor() {
return myColor.toString();
}
public boolean getFilling(){
return isFilled;
}
public void setUpperLeftX(int value) {
x1 = value;
}
public void setUpperLeftY(int value) {
y1 = value;
}
public void setDownRightX(int value) {
x2 = value;
}
public void setDownRightY(int value) {
y2 = value;
}
public void drawNoFill(Graphics g) {
g.setColor(myColor);
g.drawOval(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
}
public void drawFill(Graphics g) {
g.setColor(myColor);
g.fillOval(getUpperLeftX(), getUpperLeftY(), getWidth(), getHeight());
}
}
DrawPanel Class
package drawingovals;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class DrawPanel extends JPanel{
private Random randomNumbers = new Random();
private MyOval[] ovals;
public DrawPanel() {
setBackground(Color.WHITE);
ovals = new MyOval[5 + randomNumbers.nextInt(5)];
for (int count = 0; count < ovals.length; count++) {
int x1 = randomNumbers.nextInt(300);
int y1 = randomNumbers.nextInt(300);
int x2 = randomNumbers.nextInt(300);
int y2 = randomNumbers.nextInt(300);
Color color = new Color(randomNumbers.nextInt(256),
randomNumbers.nextInt(256), randomNumbers.nextInt(256));
boolean fill = randomNumbers.nextBoolean();
ovals[count] = new MyOval(x1, y1, x2, y2, color, fill);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (int count = 0; count < ovals.length - 1; count++) {
ovals[count].drawFill(g);
}
}
}
DrawTest Class
package drawingovals;
import javax.swing.JFrame;
public class DrawTest {
public static void main(String[] args) {
DrawPanel panel = new DrawPanel();
JFrame application = new JFrame();
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(panel);
application.setSize(400, 400);
application.setVisible(true);
}
}

You need to take care that your oval heights and widths contain only positive values -- your code does not do this. Consider using Math.max, Math.min, or Math.abs when obtaining your oval properties to help you achieve this.
Also, this is wrong as you're duplicating setting x2 bug ignoring y2:
this.x1 = x1;
this.y1 = y1;
this.x2 = x2; // *** these are the same
this.x2 = x2; // *** these are the same
Something like this would work:
public MyOval(int x1, int y1, int x2, int y2, Color color, boolean isFilled) {
this.x1 = Math.min(x1, x2);
this.y1 = Math.min(y1, y2);
this.x2 = Math.max(x1, x2);
this.y2 = Math.max(y1, y2);;
myColor = color;
this.isFilled = isFilled;
}
In the future, the key to solving these types of issues is to use a debugger to check the fields of your program, here the oval properties, as the program runs, and then see if they don't make sense, and then why.

Related

DrawRect, DrawOval, DrawLine, FillRect and FillOval only draw a straight horizontal line in code provided

I am currently practising GUI in Java and have made a program that procedurally generates random shapes depending on the user input. However, it seems to not be working correctly.
The program currently looks like this (Lines instead of Rectangles and Ovals):
However, as suggested above the program should have some filled, some unfilled rectangles and ovals and lines. These horizontal lines are not representative of what the output should look like.
This is the code below.
DrawPanelTest.java (main file)
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import java.awt.BorderLayout;
public class DrawPanelTest {
public static void main(String[] args) {
String amount = JOptionPane.showInputDialog("How many shapes should exist?");
int intAmount = Integer.parseInt(amount);
DrawPanel drawPanel = new DrawPanel(intAmount);
JLabel text = new JLabel("Lines: " + drawPanel.getLineAmount() + ", Ovals: " + drawPanel.getOvalAmount()
+ ", Rectangles: " + drawPanel.getRectangleAmount());
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(3);
jFrame.add(drawPanel);
jFrame.add(text, BorderLayout.SOUTH);
jFrame.setSize(600, 600);
jFrame.setVisible(true);
}
}
DrawPanel.java
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
private Random random = new Random();
private Shape[] shapes;
private int lineAmount;
private int ovalAmount;
private int rectangleAmount;
public DrawPanel(int amount) {
shapes = new Shape[amount];
for (int i = 0; i < shapes.length; i++) {
Color color = new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
int choice = random.nextInt(3);
switch (choice) {
case 0:
shapes[i] = new Line(random.nextInt(300), random.nextInt(300), random.nextInt(300), random.nextInt(300),
color);
lineAmount++;
break;
case 1:
shapes[i] = new Oval(random.nextInt(300), random.nextInt(300), random.nextInt(300), random.nextInt(300),
color, random.nextBoolean());
ovalAmount++;
break;
case 2:
shapes[i] = new Rectangle(random.nextInt(300), random.nextInt(300), random.nextInt(300),
random.nextInt(300), color, random.nextBoolean());
rectangleAmount++;
break;
}
}
}
public int getLineAmount() {
return lineAmount;
}
public int getOvalAmount() {
return ovalAmount;
}
public int getRectangleAmount() {
return rectangleAmount;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Shape shape : shapes) {
shape.draw(g);
}
}
}
Shape.java
import java.awt.Color;
import java.awt.Graphics;
public abstract class Shape {
private int x1;
private int y1;
private int x2;
private int y2;
private Color color;
public Shape() {
setX1(0);
setY1(0);
setX2(100);
setY2(100);
setColor(0, 0, 0);
}
public Shape(int x1, int y1, int x2, int y2, Color color) {
setX1(x1);
setY1(y1);
setX2(x2);
setY2(y1);
setColor(color);
}
public void setX1(int newX1) {
if (newX1 >= 0) {
x1 = newX1;
} else {
x1 = 0;
}
}
public int getX1() {
return x1;
}
public void setY1(int newY1) {
if (newY1 >= 0) {
y1 = newY1;
} else {
y1 = 0;
}
}
public int getY1() {
return y1;
}
public void setX2(int newX2) {
if (newX2 >= 0) {
x2 = newX2;
} else {
x2 = 0;
}
}
public int getX2() {
return x2;
}
public void setY2(int newY2) {
if (newY2 >= 0) {
y2 = newY2;
} else {
y2 = 0;
}
}
public int getY2() {
return y2;
}
public void setColor(int r, int g, int b) {
color = new Color(r, g, b);
}
public void setColor(Color newColor) {
color = newColor;
}
public Color getColor() {
return color;
}
public abstract void draw(Graphics g);
}
BoundedShape.java
import java.awt.Color;
import java.math.*;
public abstract class BoundedShape extends Shape {
private boolean filled;
public BoundedShape() {
super();
setFill(false);
}
public BoundedShape(int x1, int y1, int x2, int y2, Color color, boolean fill) {
super(x1, y1, x2, y2, color);
setFill(fill);
}
public void setFill(boolean fill) {
if (fill == true || fill == false) {
filled = fill;
} else {
throw new IllegalArgumentException("fill has to be either true or false");
}
}
public boolean getFill() {
return filled;
}
public int getUpperLeftX() {
return Math.min(super.getX1(), super.getX2());
}
public int getUpperLeftY() {
return Math.min(super.getY1(), super.getY2());
}
public int getWidth() {
return Math.abs(super.getX2() - super.getX1());
}
public int getHeight() {
return Math.abs(super.getY2() - super.getY1());
}
}
Line.java
import java.awt.Color;
import java.awt.Graphics;
public class Line extends Shape {
public Line() {
super();
}
public Line(int x1, int y1, int x2, int y2, Color color) {
super(x1, y1, x2, y2, color);
}
#Override
public void draw(Graphics g) {
g.setColor(super.getColor());
g.drawLine(super.getX1(), super.getY1(), super.getX2(), super.getY2());
}
}
Rectangle.java
import java.awt.Color;
import java.awt.Graphics;
public class Rectangle extends BoundedShape {
public Rectangle() {
super();
}
public Rectangle(int x1, int y1, int x2, int y2, Color color, boolean filled) {
super(x1, y1, x2, y2, color, filled);
}
public void draw(Graphics g) {
g.setColor(super.getColor());
if (super.getFill() == false) {
g.drawRect(super.getUpperLeftX(), super.getUpperLeftY(), super.getWidth(), super.getHeight());
} else if (super.getFill() == true) {
g.fillRect(super.getUpperLeftX(), super.getUpperLeftY(), super.getWidth(), super.getHeight());
}
}
}
Oval.java
import java.awt.Color;
import java.awt.Graphics;
public class Oval extends BoundedShape {
public Oval() {
super();
}
public Oval(int x1, int y1, int x2, int y2, Color color, boolean filled) {
super(x1, y1, x2, y2, color, filled);
}
public void draw(Graphics g) {
g.setColor(super.getColor());
if (super.getFill() == false) {
g.drawOval(super.getUpperLeftX(), super.getUpperLeftY(), super.getWidth(), super.getHeight());
} else if (super.getFill() == true) {
g.fillOval(super.getUpperLeftX(), super.getUpperLeftY(), super.getWidth(), super.getHeight());
}
}
}
Thanks in advance,
mabdi36
Within your draw() method of Oval and Rectangle, you call super.getWidth() and super.getHeight(). But your height is always 0, because of a typo within your constructor in Shape:
You call setY2() and pass in y1, so y2 == y1, thus abs(y2 - y1) = 0.
public Shape(int x1, int y1, int x2, int y2, Color color) {
setX1(x1);
setY1(y1);
setX2(x2);
setY2(y1); // change this to setY2(y2)
setColor(color);
}
Now height won't be 0 and you'll see your shape in 2D.

Change contents of BufferedImage, then update JFrame to reflect it

I am trying to make a Mandelbrot Set renderer with a GUI where you can click and drag to zoom into a specific area. When run, it will do the initial calculations and rendering fine, but when you try to click and drag to zoom in, the console says it is doing the calculations, but the content of the JFrame is not updated.
However, I'm not even positive that it is recalculating, because the initial calculation takes about 8 seconds but when you click/drag to zoom it takes about 6 ms.
I have posted my code below.
Complex Numbers Class
public class Complex {
private double real, imag;
// Constructors
public Complex(){
real=0.0;
imag=0.0;
}
public Complex(double real, double imag) {
this.real=real;
this.imag=imag;
}
// add given complex number to this one, returning the Complex result
public Complex add(Complex other) {
return new Complex(this.real+other.real, this.imag+other.imag);
}
// multiply given complex number by this one, returning the Complex result
public Complex multiply(Complex other) {
return new Complex((this.real*other.real)-(this.imag*other.imag), (this.imag*other.real)+(this.real*other.imag));
}
// get the magnitude of this complex number
public double getMagnitude() {
return Math.sqrt((real*real)+(imag*imag));
}
}
Runnable MandelbrotTask Class
public class MandelbrotTask implements Runnable {
private double x1, y1, x2, y2;
private int startCol, endCol, startRow, endRow, maxIters;
private int[][] iterCounts;
public MandelbrotTask(int maxIters, double x1, double y1, double x2, double y2, int startCol, int endCol, int startRow, int endRow, int[][] iterCounts) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.startCol = startCol;
this.endCol = endCol;
this.startRow = startRow;
this.endRow = endRow;
this.iterCounts = iterCounts;
this.maxIters=maxIters;
}
#Override
public void run() {
for (int i = startRow; i < endRow; i++) {
for (int j = startCol; j < endCol; j++) {
Complex c = getComplex(i, j);
int iterCount = countIters(c);
iterCounts[i][j] = iterCount;
}
}
}
public Complex getComplex(int i, int j){
//output image is 600 X 600 pixels
double incrementX;
double incrementY;
if(x2!=x1){
incrementX=(Math.abs(x2-x1)/600);
}
else{
throw new ArithmeticException("Error: area=0");
}
if(y2!=y1){
incrementY=(Math.abs(y2-y1)/600);
}
else{
throw new ArithmeticException("Error: area=0");
}
return new Complex(x1+((double)i*incrementX), y1+((double)j*incrementY));
}
public int countIters(Complex c){
Complex z=new Complex(0, 0);
int iters=0;
while(z.getMagnitude()<2 && iters<=maxIters){
z=z.multiply(z).add(c);
iters++;
}
return iters;
}
}
Main Mandelbrot Class
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class Mandelbrot {
private static final int HEIGHT = 600;
private static final int WIDTH = 600;
private static final int maxIters=50000;
private static Rectangle zoomBox;
private static Point initialClick;
private static JLabel content; //bufferedImage will be put into this JLabel
private static int[][] iterCounts;
private static BufferedImage bufferedImage; //rendering will be written to this bufferedImage
private static JFrame frame;
public static void main(String[] args) throws IOException {
zoomBox=null;
Scanner keyboard = new Scanner(System.in);
double x1 = -2;
double y1 = -2;
double x2 = 2;
double y2 = 2;
/*System.out.print("Max iterations (16,581,375 supported): ");
int maxIters=50000;
if(maxIters>16581375){
throw new UnsupportedOperationException("Error: Max Iterations: Overflow.");
}
System.out.print("Output filename: ");
String fileName = keyboard.next();
if(!fileName.endsWith(".png") && !fileName.endsWith(".PNG")){
fileName=fileName + ".png";
}*/
// TODO: create the rendering, save it to a file
iterCounts=new int[WIDTH][HEIGHT];
recalculate(x1, y1, x2, y2, iterCounts);
bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
MouseAdapter listener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
handleMousePressed(e);
}
#Override
public void mouseDragged(MouseEvent e) {
handleMouseDragged(e);
}
#Override
public void mouseReleased(MouseEvent e) {
handleMouseReleased(e);
}
};
content=new JLabel(new ImageIcon(render(iterCounts, bufferedImage, zoomBox, true)));
content.addMouseListener(listener);
content.addMouseMotionListener(listener);
/*OutputStream os = new BufferedOutputStream(new FileOutputStream(fileName));
try {
ImageIO.write(bufferedImage, "PNG", os);
} finally {
os.close();
}*/
frame = new JFrame("Mandelbrot Viewer");
frame.getContentPane().add(content);
frame.pack();
frame.setSize(new Dimension(WIDTH, HEIGHT));
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static BufferedImage render(int[][] iterCounts, BufferedImage bufferedImage, Rectangle zoomBox, boolean updated){
bufferedImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);
Graphics g = bufferedImage.getGraphics();
Graphics2D g2=(Graphics2D) g;
if(updated){
for(int i=0; i<WIDTH; i++){
for(int j=0; j<HEIGHT; j++){
if(iterCounts[i][j]<maxIters){
String hexCode= String.format("#%06x", (0xFFFFFF & (32*iterCounts[i][j])));
g.setColor(Color.decode(hexCode));
}
else{
g.setColor(Color.CYAN);
}
g.drawLine(i, j, i, j);
}
}
}
else{
if(zoomBox!=null){
g2.setStroke(new BasicStroke(7));
g2.draw(zoomBox);
}
}
return bufferedImage;
}
public static int[][] recalculate(double x1, double y1, double x2, double y2, int[][] iterCounts){
MandelbrotTask[] tasks=new MandelbrotTask[4];
tasks[0]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, 0, HEIGHT/4, iterCounts);
tasks[1]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, HEIGHT/4, 2*(HEIGHT/4), iterCounts);
tasks[2]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, 2*(HEIGHT/4), 3*(HEIGHT/4), iterCounts);
tasks[3]=new MandelbrotTask(maxIters, x1, y1, x2, y2, 0, WIDTH, 3*(HEIGHT/4), 4*(HEIGHT/4), iterCounts);
//parallelize computation
Thread[] threads=new Thread[4];
for(int i=0; i<4; i++){
threads[i]=new Thread(tasks[i]);
}
System.out.println("Working...");
//start timer, start computation
long start=System.currentTimeMillis();
for(int i=0; i<4; i++){
threads[i].start();
}
for(int i=0; i<4; i++){
try {
threads[i].join();
} catch (InterruptedException e) {
System.err.println("A thread was interrupted.");
}
}
//end timer
long end=System.currentTimeMillis();
long elapsed=end-start;
System.out.println("Done.");
System.out.println("Took " + elapsed + " ms.");
return iterCounts;
}
protected static void handleMousePressed(MouseEvent e) {
initialClick=e.getPoint();
}
protected static void handleMouseDragged(MouseEvent e) {
if(e.getX()>e.getY()){
zoomBox=new Rectangle((int)initialClick.getX(), (int)initialClick.getY(), (int)(e.getX()-initialClick.getX()), (int)(e.getY()-initialClick.getX()));
}
else if(e.getY()>e.getX()){
zoomBox=new Rectangle((int)initialClick.getX(), (int)initialClick.getY(), (int)(e.getX()-initialClick.getY()), (int)(e.getY()-initialClick.getY()));
}
else{
zoomBox=new Rectangle((int)initialClick.getX(), (int)initialClick.getY(), (int)(e.getX()-initialClick.getX()), (int)(e.getY()-initialClick.getY()));
}
content=new JLabel(new ImageIcon(render(iterCounts, bufferedImage, zoomBox, false)));
content.repaint();
}
protected static void handleMouseReleased(MouseEvent e) {
recalculate(initialClick.getX(), initialClick.getY(), e.getX(), e.getY(), iterCounts);
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
zoomBox=null;
content=new JLabel(new ImageIcon(render(iterCounts, bufferedImage, zoomBox, false)));
content.repaint();
}
});
}
}
For one, you're creating a new JLabel with each re-iteration, and this JLabel is being added to nothing.
Instead use the same JLabel but rather create a new ImageIcon and set the viewed JLabel's Icon.
ImageIcon icon = new ImageIcon(render(iterCounts, bufferedImage, zoomBox, false));
content.setIcon(icon);
You also don't seem to be doing anything with the int arrays returned from recalculate.
Shouldn't your handleMouseReleased method have:
iterCounts = recalculate(initialClick.getX(), initialClick.getY(),
e.getX(), e.getY(), iterCounts);
Also, you still have bad threading -- you're calling join on your Threads from within the Swing event thread, something almost sure to freeze your GUI. Use a SwingWorker and then after getting notified from the worker when it's done, use its data. Also you're grossly over using static variables in your GUI. Make your GUI components instance fields, not static fields.
There are more logical errors that I've yet to find I'm afraid...
Second iteration of program -- With the Mandelbrot calculations:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
#SuppressWarnings("serial")
public class Mandel2 extends JPanel {
private static final int GUI_HEIGHT = 600;
private static final int GUI_WIDTH = 600;
private static final int MAX_ITERS = 50000;
private BufferedImage image = new BufferedImage(GUI_WIDTH, GUI_HEIGHT,
BufferedImage.TYPE_INT_ARGB);
private Rectangle zoomRect;
private double myX0 = -2.5;
private double myY0 = -2.0;
private double myX1 = 1.5;
private double myY1 = 2.0;
private JDialog waitDialog;
public Mandel2() {
final MyMouse myMouse = new MyMouse();
int delayStartingCalc = 2 * 1000; // 2 second delay
Timer timer = new Timer(delayStartingCalc, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
Rectangle myRect = new Rectangle(0, 0, GUI_WIDTH, GUI_HEIGHT);
createMandel(myRect);
}
});
timer.setRepeats(false);
timer.start();
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(GUI_WIDTH, GUI_HEIGHT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, this);
}
Graphics2D g2 = (Graphics2D) g;
if (zoomRect == null) {
return;
}
g2.setXORMode(Color.gray);
g2.draw(zoomRect);
}
private double screenToLogicalX(double screenX) {
return myX0 + (screenX * (myX1 - myX0)) / GUI_WIDTH;
}
private double screenToLogicalY(double screenY) {
return myY0 + ((GUI_HEIGHT - screenY) * (myY1 - myY0)) / GUI_HEIGHT;
}
private void createMandel(Rectangle myRect) {
double x0 = screenToLogicalX(myRect.x);
double y0 = screenToLogicalY(myRect.y + myRect.height);
double x1 = screenToLogicalX(myRect.x + myRect.width);
double y1 = screenToLogicalY(myRect.y);
myX0 = x0;
myY0 = y0;
myX1 = x1;
myY1 = y1;
MandelWorker mandelWorker = new MandelWorker(MAX_ITERS, x0, y0, x1, y1);
mandelWorker.addPropertyChangeListener(new MandelWorkerListener());
mandelWorker.execute();
if (waitDialog == null) {
Window win = SwingUtilities.getWindowAncestor(Mandel2.this);
JProgressBar jProgressBar = new JProgressBar();
jProgressBar.setIndeterminate(true);
waitDialog = new JDialog(win, "Please Wait", ModalityType.APPLICATION_MODAL);
waitDialog.add(jProgressBar);
waitDialog.pack();
waitDialog.setLocationRelativeTo(win);
}
waitDialog.setVisible(true);
}
private class MyMouse extends MouseAdapter {
private Point p;
#Override
public void mousePressed(MouseEvent e) {
p = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
zoomRect = createRect(e);
repaint();
};
#Override
public void mouseReleased(MouseEvent e) {
zoomRect = createRect(e);
repaint();
createMandel(zoomRect);
}
private Rectangle createRect(MouseEvent e) {
int x = Math.min(p.x, e.getX());
int y = Math.min(p.y, e.getY());
int width = Math.abs(p.x - e.getX());
int height = Math.abs(p.y - e.getY());
return new Rectangle(x, y, width, height);
}
}
private class MandelWorkerListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
waitDialog.setVisible(false);
waitDialog.dispose();
MandelWorker worker = (MandelWorker) evt.getSource();
try {
image = worker.get();
zoomRect = null;
repaint();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
private class MandelWorker extends SwingWorker<BufferedImage, Void> {
private int maxIters;
private double x1;
private double y1;
private double x2;
private double y2;
public MandelWorker(int maxIters, double x1, double y1, double x2, double y2) {
this.maxIters = maxIters;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
#Override
protected BufferedImage doInBackground() throws Exception {
int[][] iterGrid = new int[GUI_HEIGHT][GUI_WIDTH];
for (int i = 0; i < GUI_HEIGHT; i++) {
double y = y1 + i * (y2 - y1) / GUI_HEIGHT;
for (int j = 0; j < GUI_WIDTH; j++) {
double x = x1 + j * (x2 - x1) / GUI_WIDTH;
int iIndex = GUI_HEIGHT - i - 1;
iterGrid[iIndex][j] = calcMandel(x, y);
}
}
return render(iterGrid);
}
private BufferedImage render(int[][] iterGrid) {
int w = GUI_WIDTH;
int h = GUI_HEIGHT;
BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
if (iterGrid[i][j] < maxIters) {
String hexCode = String.format("#%06x", (0xFFFFFF & (32 * iterGrid[i][j])));
g2.setColor(Color.decode(hexCode));
} else {
g2.setColor(Color.CYAN);
}
g2.drawLine(j, i, j, i);
}
}
g2.dispose();
return img;
}
private int calcMandel(double x, double y) {
Complex c = new Complex(x, y);
Complex z = new Complex();
int iters = 0;
while (z.getMagnitude() < 2 && iters <= maxIters) {
z = z.multiply(z).add(c);
iters++;
}
return iters;
}
}
private class Complex {
private double real, imag;
// Constructors
public Complex() {
real = 0.0;
imag = 0.0;
}
public Complex(double real, double imag) {
this.real = real;
this.imag = imag;
}
// add given complex number to this one, returning the Complex result
public Complex add(Complex other) {
return new Complex(this.real + other.real, this.imag + other.imag);
}
// multiply given complex number by this one, returning the Complex
// result
public Complex multiply(Complex other) {
return new Complex((this.real * other.real) - (this.imag * other.imag),
(this.imag * other.real) + (this.real * other.imag));
}
// get the magnitude of this complex number
public double getMagnitude() {
return Math.sqrt((real * real) + (imag * imag));
}
}
private static void createAndShowGui() {
Mandel2 mainPanel = new Mandel2();
JFrame frame = new JFrame("Mandel2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.setResizable(false);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Second iteration -- it does the calculations, but is not very efficient at it.

creating a rectangle from 2 specific points

I am trying to create a rectangle in Java but only with awt package classes.
I can only click two points and the program must calculate the width and height and draw a rectangle between those exact two points.
The following doesn't work for me:
package ie.iact.shapes;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
public class Rect extends Shapes {``
private Point secondPoint;
public Rect(Point f, Point s) {
setFirstPoint(f);
setSecondPoint(s);
}
#Override
public void draw(Graphics g) {
int x1 = firstPoint.x;
int y1 = firstPoint.y;
int x2 = secondPoint.x;
int y2 = secondPoint.y;
int a;
int b;
if (x1 < x2) {
a = x1;
} else {
a = x2;
}
if (y1 < y2) {
b = y1;
} else {
b = y2;
}
int width = secondPoint.x - a;
int hight = secondPoint.y - b;
g.drawRect(getFirstPoint().x, getFirstPoint().y, secondPoint.x, secondPoint.y);
}
public Point getSecondPoint() {
return secondPoint;
}
public void setSecondPoint(Point secondPoint) {
this.secondPoint = secondPoint;
}
}
Rectangle class can already handle all of your calculations:
Rectangle rect= new Rectangle(point1);
rect.add(point2);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
Alternatively you can use setFrameFromDiagonal:
Rectangle rect= new Rectangle();
rect.setFrameFromDiagonal(point1, point2);
g.fillRect(rect.x, rect.y, rect.width, rect.height);

drawing shapes with mouse in java

I am working on a simple panting project that allow the user to select a shape from ComboBox then draw it on the panel. Problem is when user choose any type of shapes and try to draw it on panel no shape appears.
here is my panel class
import java.awt.Color;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.event.*;
public class Shapes extends JPanel {
private MyLine[] lines = new MyLine[100];
private MyRectangle[] recs;
private MyOval[] ovals;
int ShapeType = 0;
int LC = 0;// conter for number of lines
int RC = 0;// conter for number of rectable
int OC = 0;// conter for number of ovals
int x1;
int y1;
int x2;
int y2;
Shapes() {
this.setBackground(Color.WHITE);
this.setBounds(0, 100, 300, 300);
MouseHandler handler = new MouseHandler();
this.addMouseListener(handler);
this.addMouseMotionListener(handler);
}
public int getShapeType() {
return ShapeType;
}
public void setShapeType(int ShapeType) {
this.ShapeType = ShapeType;
}
private class MouseHandler extends MouseAdapter implements
MouseMotionListener {
#Override
public void mouseClicked(MouseEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
#Override
public void mousePressed(MouseEvent e) {
x1 = e.getX();
y1 = e.getX();
repaint();
System.out.println(x1 + " " + y1);
}
#Override
public void mouseReleased(MouseEvent e) {
x2 = e.getX();
y2 = e.getX();
lines[LC] = new MyLine(x1, y1, x2, y2);
LC++;
System.out.println(x2 + " " + y2);
repaint();
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseDragged(MouseEvent e) {
x2 = e.getX();
y2 = e.getX();
System.out.println(x2 + " dragged " + y2);
repaint();
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
if (ShapeType == 0) {
for (int i = 0; i < LC; i++) {
lines[i].draw(g);
}
}
if (ShapeType == 1) {
for (int i = 0; i < LC; i++) {
lines[i].draw(g);
}
}
if (ShapeType == 1) {
for (int i = 0; i < LC; i++) {
lines[i].draw(g);
}
}
}
}
MyLine Class
package painter;
import java.awt.Graphics;
import java.awt.Color;
public class MyLine extends MyShape {
MyLine(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.x2 = x2;
this.y1 = y1;
this.y2 = y2;
this.c = c;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.RED);
g.drawLine(500, 200, 300, 400);
}
}
Your panel is way too small: it's 300 by 300 pixels, but when you draw the line, you start it at (500,200) which is out of the bounds of your panel:
g.drawLine(500, 200, 300, 400);
Try drawing it closer to the upper-left corner:
g.drawLine(0, 0, 300, 400);

JComboBox gets stuck

I have a problem with a JComboBox. I have an upper JPanel with the JComboBox and another JPanel below with a BufferedImage where I can draw some ovals (it has a listener to the mouse clicks). The problem, as you will see in the video, is that sometimes when I change the option in the JComboBox it does not show that change.
For example, if I select 'ALL' and then I select 'L4', 'ALL' remains shown instead of changing to 'L4', but when I click on the JComboBox, in the other drawing JPanel or on another window of the desktop, it changes to 'L4' (it should have changed before). I think that the problem is something related with having a JPanel listening for mouse clicks below the JComboBox, but I'm not sure.
Can anyone tell me how can I fix that?
Here's the link to the video I made to show the problem: http://youtu.be/8Gg2Uq3SCYw
It is also important to say that when I record the video with the QuickTime Player, all is recorded working correctly even if it hasn't worked correctly (what I mean is that I see what is in the video (link) but QuickTime records it running correctly, very very weird...)
Here's the link to the Example eclipse project I made for you, try to select different options many times, you will see what I say: https://app.sugarsync.com/iris/wf/D6421069_60887018_228038
Look at LapPanel of CircuitTracePlotView.java, there is the JComboBox.
I'm running it on a MacBookPro 10.8 (Mountain Lion)
And here is the code for the view (it is also on the link of the Example):
package view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CircuitTracePlotView extends JFrame {
private static final long serialVersionUID = 5125304890914235274L;
private int numberOfLaps;
private CircuitTracePlot plot;
private LapPanel lapPanel;
public CircuitTracePlotView() {
this.setVisible(false);
this.plot = new CircuitTracePlot();
this.lapPanel = new LapPanel();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.getContentPane().add(this.plot, BorderLayout.CENTER);
this.getContentPane().add(this.lapPanel, BorderLayout.NORTH);
this.pack();
this.setLocationRelativeTo(null);
}
public void init(CircuitTracePlotViewController circuitTracePlotViewController, int numberOfLaps) {
this.setController(circuitTracePlotViewController);
this.setNumberOfLaps(numberOfLaps);
this.lapPanel.setLapSelection();
}
private void setController(CircuitTracePlotViewController circuitTracePlotViewController) {
this.plot.init(circuitTracePlotViewController);
}
private int getNumberOfLaps() {
return this.numberOfLaps;
}
public void setNumberOfLaps(int laps) {
this.numberOfLaps = laps;
System.out.println("NumberOfLaps" + this.numberOfLaps);
}
public void drawPoint(int x, int y) {
this.plot.drawPoint(x, y);
this.repaint();
}
public void drawLine(int x1, int y1, int x2, int y2) {
this.plot.drawLine(x1, y1, x2, y2);
}
public Dimension getPlotDimension() {
return this.plot.getPreferredSize();
}
//Drawing panel
private class CircuitTracePlot extends JPanel {
private static final long serialVersionUID = -7915054480476755069L;
private final static short LINE = 0;
private final static short OVAL = 1;
private final static int OVALHEIGHT = 10;
private final static int OVALWIDTH = 10;
BufferedImage plot;
Graphics2D plotGraphics;
private int x1;
private int x2;
private int y1;
private int y2;
private int paintType;
private CircuitTracePlot() {
this.setBackground(Color.WHITE);
}
private void init(CircuitTracePlotViewController circuitTracePlotViewController) {
this.addListeners(circuitTracePlotViewController);
this.plot = (BufferedImage)this.createImage(this.getPreferredSize().width, this.getPreferredSize().height);
this.plotGraphics = this.plot.createGraphics();
}
private void drawLine(int x1, int y1, int x2, int y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.paintType = LINE;
this.repaint();
}
private void drawPoint(int x1, int y1) {
this.x1 = x1;
this.y1 = y1;
this.paintType = OVAL;
this.repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
switch (this.paintType) {
case LINE:
plotGraphics.drawLine(x1, y1, x2, y2);
g.drawImage(this.plot,0,0, this);
break;
case OVAL:
plotGraphics.fillOval(x1 - OVALWIDTH/2, y1 - OVALHEIGHT/2, OVALWIDTH, OVALHEIGHT);
g.drawImage(this.plot,0,0, this);
break;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(700, 500);
}
private void addListeners(CircuitTracePlotViewController circuitTracePlotViewController) {
this.addMouseListener(circuitTracePlotViewController);
}
}
private class LapPanel extends JPanel{
private static final long serialVersionUID = -287427935273603789L;
//private LinkedList<JIDButton> list_LapButtons;
private JComboBox<String> JCB_Laps;
private LapPanel() {
this.setBorder(BorderFactory.createTitledBorder("Lap Selection"));
//this.list_LapButtons = new LinkedList<JIDButton>();
//JIDButton auxButton = new JIDButton(0, "<html><u>A</u>LL<html>");
//this.list_LapButtons.add(auxButton);
//this.add(auxButton);
System.out.println("NumberOfLaps" + CircuitTracePlotView.this.numberOfLaps);
}
private void setLapSelection() {
String[] auxLaps = new String[CircuitTracePlotView.this.getNumberOfLaps() + 1];
auxLaps[0] = "<html>" + "<u>" + "A" + "</u>" + "LL" + "<html>";
for (int i = 1; i <= CircuitTracePlotView.this.getNumberOfLaps(); i++) {
auxLaps[i] = "<html>" + "L" + "<u>" + i + "</u>" + "<html>";
}
this.JCB_Laps = new JComboBox<String>(auxLaps);
this.add(JCB_Laps);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(700, 65);
}
}
}
I've posted all the information that I think it's relevant, if someone needs more information just ask for it.

Categories

Resources