So I'm trying to draw a curve that has a taper profile like this : y=
Since I'm using awt.Graphics2D, I only have the ability to draw shapes.
One way to draw curves is to draw curves is use use BĀ“ezier curves. Is there a way convert this or a awt trick I'm not familiar with ?
One option to draw a curve is point by point :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Curve extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
for (int x = 1; x <= 100; x++) {
int y = getY(x);
//2g does not support drawing a point so you draw a line
g2d.drawLine(x, y, x, y);
}
}
/**
*#param x
*#return
*/
private int getY(int x) {
//change to the function you want
return 50+ (100/(1+ (3* x)));
}
public static void main(String[] args) {
Curve points = new Curve();
JFrame frame = new JFrame("Curve");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(points);
frame.setSize(350, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Related
I really need some help with that.
I'm trying to crop an image into a circle and it's fine but the pixels outside the circle stay white. How can I put them transparent?
My code it's:
static ColorImage Circulo(ColorImage img, int radius) {
for (int x=0; x < img.getWidth(); x++ ) {
for(int y=0; y < img.getHeight(); y++) {
if((x - (img.getWidth()/2)) * (x - (img.getWidth()/2)) + (y - (img.getHeight()/2) )* (y - (img.getHeight()/2)) <= (radius*radius)) {
img.setColor(x, y, img.getColor(x, y));
}else {
Color c = new Color (255, 255, 255);
img.setColor(x, y, c );
}
}
}
return img;
}
Try this. This will paint the image on the screen inside a circle. If you want to create a new image, get the Graphics context from a BufferedImage and write the image to that instead of the graphics context in paintComponent. Any image format will work as this does not rely on any transparency mode of the graphics image.
The main idea behind this is setting the clip region to that of a circle. Then whatever you paint will only appear in that region.
In this example, I made the diameter of the circle the minimum of the width and height of the image. This way, the entire circle will fit in a rectangle.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ImageInCircle extends JPanel {
JFrame f = new JFrame();
Image img;
int width;
int height;
static String imgFile =
"location/of/image/img.gif";
public static void main(String[] args) {
SwingUtilities.invokeLater(()->new ImageInCircle().start());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
public ImageInCircle () {
f.add(this);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void start() {
try {
img = ImageIO.read(new File(imgFile));
} catch (IOException fne) {
fne.printStackTrace();
}
width = img.getWidth(null);
height = img.getHeight(null);
revalidate();
f.setVisible(true);
f.pack();
f.setLocationRelativeTo(null);
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.white);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int circleDiameter = Math.min(width,height);
Ellipse2D.Double circle = new Ellipse2D.Double(0,0,circleDiameter,circleDiameter);
g2.setClip(circle);
g2.drawImage(img,0,0,this);
}
}
I have a GUI with a panel where I draw. Whatever mouse pattern I do is repeated in every sector which is divided by two lines. However, I am able to do this because my paintComponen method does not invoke super.paintComponent. If I actually do invoke the method I get only a single point whenever i drag my mouse. How should i go about it?
import java.awt.Color;
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.geom.Line2D;
import javax.swing.JPanel;
public final class DisplayPanel extends JPanel
{
private boolean dragging;
private Point draw;
private Line2D sectorLine;
private int sectors;
public void init()
{
DisplayListener listener = new DisplayListener();
addMouseListener(listener);
addMouseMotionListener(listener);
setOpaque(true);
setBackground(Color.BLACK);
setSize(900,900);
setVisible(true);
}
//performs the drawing on the display panel
public void paintComponent(Graphics g)
{
//super.paintComponent(g);
setBackground(Color.BLACK);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.RED);
sectorLine = new Line2D.Double(getWidth()/2, 0, getWidth()/2, getHeight());
sectors = 12;
//draws the sectors on the screen
for(int i=0; i<sectors; i++)
{
g2d.draw(sectorLine);
g2d.rotate(Math.toRadians(30),getWidth()/2,getHeight()/2);
}
//draws the doilie
if(dragging)
{
for(int i=0; i<sectors; i++)
{
g2d.fillOval((int) draw.getX(), (int) draw.getY(),20, 20);
g2d.rotate(Math.toRadians(30), getWidth()/2, getHeight()/2);
}
}
}
private class DisplayListener extends MouseAdapter
{
public void mouseDragged(MouseEvent event)
{
dragging = true;
draw = event.getPoint();
repaint();
}
public void mouseReleased(MouseEvent event)
{
dragging = false;
}
}
}
super.paintComponent() erases/clears the area before drawing, so you only see the point you current draw.
If you want to draw the line the mouse dragged, you would have to store each drawn coordinate in a List, and then in paintComponent(), draw all the points again. Please be aware that this list could get very big, and thus eat a lot of memory, so you should probably think about limiting it somehow.
After scouring the internet for days, I found a Question that seemed to address my goal. (I'm trying to draw/edit an individual pixel in an image, and render it.) In said question, The ask-er requested code for a Black BufferedImage. The top Answer provided that code, and appears to work beautifully, until you try to change it to something other than black. Here's the Code:
package myProjectPackage;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import javax.swing.*;
public class Copypasta {
public static JFrame frame;
BufferedImage img;
public static int WIDTH = 500;
public static int HEIGHT = 500;
public Copypasta() {
}
public static void main(String[] a){
Copypasta t=new Copypasta();
frame = new JFrame("WINDOW");
frame.setVisible(true);
t.start();
frame.add(new JLabel(new ImageIcon(t.getImage())));
frame.pack();
// Better to DISPOSE than EXIT
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public Image getImage() {
return img;
}
public void start(){
img = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
int[] pixels = ((DataBufferInt)img.getRaster().getDataBuffer()).getData();
boolean running=true;
while(running){
BufferStrategy bs=frame.getBufferStrategy();
if(bs==null){
frame.createBufferStrategy(4);
return;
}
for (int i = 0; i < WIDTH * HEIGHT; i++)
pixels[i] = 0; //This is what i've been trying to change.
Graphics g= bs.getDrawGraphics();
g.drawImage(img, 0, 0, WIDTH, HEIGHT, null);
g.dispose();
bs.show();
}
}
}
I Apologize for the indentation errors. I promise it looks right in the editor.
When set to BufferedImage type ARGB, the black background disappears, causing me to believe that the start function isn't drawing to the Image at all, or the drawn image is not being drawn on the screen. Either way, There is something that I don't understand. If you have the time, I would appreciate some help Identifying What is going wrong, if not an explanation of why. Thank you all,
-Navi.
Link to Original Question: drawing your own buffered image on frame
Several things jump out, the use of BufferStrategy is probably overkill. Unless you absolutely must have control over the paint process, you really don't need it. Using a BufferStrategy also precludes the use of Swing based components which might or might not be an issue.
Trying to manipulate the pixel data directly is probably also a little overkill, instead you can use BufferedImage.setRGB(int, int, int), which allows you to set the color of the pixel at the specified x/y position, for example...
img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
img.setRGB(x, y, Color.RED.getRGB());
}
}
But, even this is a little overkill, the same thing can be achieved by using the provided 2D Graphics API...
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.dispose();
Which you will probably find is faster (not just from a coding point of view).
Take a look at:
Performing Custom Painting
Painting in AWT and Swing
2D Graphics
For more details...
Working example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestImage1 {
public static void main(String[] args) {
new TestImage1();
}
public TestImage1() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private BufferedImage img;
public TestPane() {
img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
//for (int x = 0; x < img.getWidth(); x++) {
// for (int y = 0; y < img.getHeight(); y++) {
// img.setRGB(x, y, Color.RED.getRGB());
// }
//}
Graphics2D g2d = img.createGraphics();
g2d.setColor(Color.RED);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.dispose();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
}
}
How do I draw the unique rectangle(cube) inside the oval:
http://i.stack.imgur.com/pmHTl.jpg
For me it is tricky to use graphics to draw a rectangle such as the one shown. Any advice on what to do.
Ok. I will try to make myself as clear as I can. What I have so far are the orange ovals and the slim gray oval that is behind it. I only need to create one of these "dots" in a class and i will make many objects of them. The Task I need help in is drawing the "rectangle" shape you see that is in the orange dot using J Component possibly. By request I will add a picture of what I have so far if this edit does not fulfill the need for you to understand my problem.
Thanks
Edit : Here is the Code that I have for creating the ovals if that is of interest to you-
public void paint(Graphics g) {
Color c = (Color.orange);
g.setColor(Color.gray);
g.fillOval(3,3,60,60);
g.setColor(c);
g.fillOval(0,0,60,60);
}
Edit: My Attempt at an SSCCE -->
NanoBot Class(Where I am Creating the Bot in paint)
/**
* #author (Omar Ahmed)
*/
import javax.swing.*;
import java.awt.*;
public class NanoBot extends Image
{
public NanoBot(int x, int y, int w, int h)
{
super(x,y,w,h);
}
public void paint(Graphics g) {
Color c = (Color.orange);
g.setColor(Color.gray);
g.fillOval(3,3,60,60);
g.setColor(c);
g.fillOval(0,0,60,60);
//g.setColor(Color.black);
//g.fillOval(10,20,10,10);
//g.fillOval(40,20,10,10);
}
}
And The Driver:
/** Bot Swarm
* Date: May, 2013
* Author: Omar Ahmed
*/
import java.awt.*;
import javax.swing.*;
public class Driver {
private JFrame win;
private NanoBot bot1;
public Driver() {
win = new JFrame(" Swarm ");
win.setLayout(null);
win.setVisible(true);
win.setBounds( 20, 20, 800, 700);
win.getContentPane().setBackground(Color.white);
bot1=new NanoBot(50,50,70,70);
win.add(bot1,0);
}
Hope This Helps
Your first step is to break down your requirements...
You need to draw 3 shapes, front, top, side.
The front's y position is offset by 0.412 of the overall height. It's width is 0.77 of the overall width.
The top's height is 0.412 of the overall height, and it has a horizontal inset of 0.2 of the overall width...
The side's x position is offset by 0.77 of the overall width and has an inset of 0.47 of the over all width.
This is all very important, as you want to ensure that the shapes can resize reasonably well...
Now, you could simply use Graphics#drawLine and Graphics#drawRectangle to build the shape, but that, to me, is a lot of work...
Instead the 2D Graphics is very powerful and contains many wonderful things, the one of interest today is the Shape API, which allows you to define many different shapes, which can be drawn or filled.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Path2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestChip {
public static void main(String[] args) {
new TestChip();
}
public TestChip() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int width = 44;
int height = 17;
Front front = new Front(width, height);
Top top = new Top(width, height);
Side side = new Side(width, height);
draw(g2d, front, Color.BLACK, Color.YELLOW);
draw(g2d, top, Color.BLACK, Color.GRAY);
draw(g2d, side, Color.BLACK, Color.DARK_GRAY);
g2d.dispose();
}
protected void draw(Graphics2D g2d, Shape shape, Color foreground, Color background) {
g2d.setColor(background);
g2d.fill(shape);
g2d.setColor(foreground);
g2d.draw(shape);
}
}
public class Front extends Path2D.Float {
public Front(float width, float height) {
float frontWidth = width * 0.77f;
float yOffset = height * 0.412f;
moveTo(0, yOffset);
lineTo(frontWidth, yOffset);
lineTo(frontWidth, height);
lineTo(0, height);
closePath();
}
}
public class Side extends Path2D.Float {
public Side(float width, float height) {
float xOffset = width * 0.77f;
float inset = height * 0.47f;
moveTo(xOffset, inset);
lineTo(width, 0);
lineTo(width, inset);
lineTo(xOffset, height);
closePath();
}
}
public class Top extends Path2D.Float {
public Top(float width, float height) {
float inset = width * 0.2f;
float shapeHeight = height * 0.412f;
moveTo(inset, 0);
lineTo(width, 0);
lineTo(width - inset, shapeHeight);
lineTo(0, shapeHeight);
closePath();
}
}
}
Your job is to now go away, study the example, study the referenced tutorials, study the associated API docs and figure out how to align the above shape within you circle and draw it's legs...
A hint. Make a "Bug" class that knows how to renderer all this and simply translate the position of the Graphics as required...
I have already made this program able to draw an instance of a small ball bouncing around a screen using these two classes
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
import javax.swing.Timer;
public class move extends JPanel implements ActionListener
{
Timer t = new Timer(7, this);
int x = 10, y = 10, velX = 7, velY = 7;
public void paintComponent(Graphics g, Graphics h)
{
super.paintComponent(h);
super.paintComponent(g);
System.out.println(g);
Graphics2D g2 = (Graphics2D) g;
Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
g2.fill(circle);
t.start();
}
public void actionPerformed(ActionEvent e) {
if(x<0 || x > getWidth())
{
velX = -velX;
}
if(y < 0 || y > getHeight())
{
velY = -velY;
}
x += velX;
y += velY;
repaint();
}
}
This class just simply draws the ball and provides the logic for the timer and such
import java.awt.Color;
import javax.swing.JFrame;
public class Gui {
public static void main(String[] args)
{
move s = new move();
JFrame f = new JFrame("move");
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000, 1000);
f.setTitle("Moving Circle");
f.setBackground(Color.GREEN);
}
}
This next class just puts it all in a JFrame, very simple stuff I know but I'm just trying to draw multiple instances within the same JFrame. I'm just trying to experiment with my knowledge of code, some sample of code to implement would be great.
How to draw multiple moving graphics?
This code could have a class Ball class that knows its position & size and how to draw itself to a Graphics.
As each ball is created, they are added to a list. At time of paint, iterate the list and paint each Ball.