I have this code:
import javax.swing.*;
import java.awt.*;
public class Test {
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 300, 300);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
}
class MyCanvas extends JComponent {
public void paint(Graphics g) {
g.drawRect (10, 10, 100, 100);
Polygon triangle = new Polygon(new int[] {100, 150, 200}, new int[] {200, 100, 200}, 3);
g.drawPolygon(triangle);
}
}
It draws this:
I want to scale only Triangle, so it becomes thrice is big:
I understand that I need to use AffiniteTransform, but I don't understand how.
I only know that I need the scaling instance:
AffineTransform at = AffineTransform.getScaleInstance(3, 3);
All answers I've seen were very confusing or just used g2d.setTransform(at) which doesn't seem to be what I need, seeing as the square is supposed to stay the same size.
EDIT: And how do I scale a Triagle, while keeping its leftmost coordinate at the same location? (leftmost (x,y) stays the same)
New code:
public class Test {
public static void main(String[] args) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 300, 300);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
}
class MyCanvas extends JComponent {
public void paint(Graphics g) {
g.drawRect (10, 10, 100, 100);
Polygon triangle = new Polygon(new int[] {100, 150, 200}, new int[] {200, 100, 200}, 3);
AffineTransform at = AffineTransform.getScaleInstance(1.5, 1.5);
((Graphics2D) g).setTransform(at);
g.drawPolygon(triangle);
((Graphics2D) g).setTransform(AffineTransform.getScaleInstance(1,1));
validate();
}
}
gives this:
The triangle shifts as it gets scaled.
Is it possible to keep the triangle at the same spot - that is to keep its leftmost bottom corner at the same spot?
Related
I have a task: draw a human figure (then it should start moving).
I draw it with primitive figures. When it came to drawing arms and legs, I realized that I needed to use Elipse2d instead of Oval and I need to position it at an angle relative to the body.
I found out that I need AffineTransform, but my attempts to apply it ended with nothing. "Arms" remain parallel to the coordinate axis.
Here is my code:
public class Main extends JFrame {
public static void main(String[] args) {
new Main("Human");
}
public Main(String title) {
super(title);
setBounds(300, 75, 1000,710);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
Color skin = new Color((int) 255, (int) 235, (int) 205);
g2.setColor(skin);
//body
g2.fillOval(85, 160, 120, 220);
//face
Ellipse2D face = new Ellipse2D.Double(100, 50, 90, 120);
g2.fill(face);
//arms
Ellipse2D armR = new Ellipse2D.Double(85, 180, 30, 240);
g2.fill(armR);
/* this part isn't working:
AffineTransform tx = new AffineTransform();
tx.getRotateInstance(Math.PI / 4)
.createTransformedShape(armR);
g2.setTransform(tx); */
Ellipse2D armL = new Ellipse2D.Double(175, 180, 30, 240);
g2.fill(armL);
/* this part isn't working:
AffineTransform tx = new AffineTransform();
tx.getRotateInstance(Math.PI / 4)
.createTransformedShape(armL);
g2.setTransform(tx); */
//legs
Ellipse2D legL = new Ellipse2D.Double(100, 365, 40, 280);
g2.fill(legL);
Ellipse2D legR = new Ellipse2D.Double(150, 365, 40, 280);
g2.fill(legR);
Please help me with code where the tilt will work :))
I am learning Java graphics. I am trying to draw simple figures. However I noticed that the following code won't draw properly:
public class Draw extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int[] xpoints = new int[] { 20, 50, 80 };
int[] ypoints = new int[] { 40, 10, 40 };
g.fillPolygon(xpoints, ypoints, 3);
int[] recXp = new int[] { 20, 80, 20, 80 };
int[] recYp = new int[] { 50, 60, 50, 60 };
g.fillPolygon(recXp, recYp, 4);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
Draw panel = new Draw();
frame.add(panel);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
}
}
In order to achieve what I want I have to use
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Draw extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
int[] xpoints = new int[] { 20, 50, 80 };
int[] ypoints = new int[] { 40, 10, 40 };
g.fillPolygon(xpoints, ypoints, 3);
g.fillRect(20, 50, 60, 10);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
Draw panel = new Draw();
frame.add(panel);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
}
}
Why is this happening? Am I missing something? Sorry if this is a trivial question, I am just trying to understand Java better.
int[] recXp = new int[] { 20, 80, 20, 80 };
int[] recYp = new int[] { 50, 60, 50, 60 };
You only have two sets of points.
You need 4 different sets of point. One for each corner of the Rectangle.
Something like:
top/left (20, 50)
top/right (x is different from above, y is the same)
bottom/right (x is same as above, y is different.
bottom/left (x is same as first, y is save as above)
How to do it? I mean, I can do it for Ellipse, but not sure about triangle.
You can use a Polygon.
int[] xPoints = {0, 0, 30};
int[] yPoints = {0, 30, 30};
Shape s = new Polygon(xPoints, yPoints, 3);
g2d.fill(s);
This doesn't answer your current question.
It demonstrates why you should NOT use panel.getGraphics() to do your painting. Painting done with the getGraphics() method is not permanent.
Try minimizing or maximizing the frame and see what happens to the painting:
import java.awt.*;
import javax.swing.*;
public class SSCCE2
{
private static void createAndShowGUI()
{
final JPanel panel = new JPanel()
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(0, 0, 50, 50);
}
};
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setLocationByPlatform( true );
frame.setSize(300, 300);
frame.setVisible( true );
Graphics g = panel.getGraphics();
g.setColor(Color.RED);
g.fillOval(100, 100, 50, 50);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Graphics g = panel.getGraphics();
g.setColor(Color.RED);
g.fillOval(100, 100, 50, 50);
}
});
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
I am creating a Towers of Hanoi game and have sucedded in printing the shapes with a time delay (that part of the code has been removed while I try to get all the ovals where they are supposed to be) I am wondering how I would go about removing the circle. As you can see I have tried the clearRect(); method but that doesn't work. Is there a way I can set if the method is visible on JPanel since each circle has its own method? I think that would be the easiest way but if anyone has a better idea go for it! Thanks for any help and I have attached my code
package towersofhanoi;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.Object;
/*g.fillOval(60 = horizontal distance , 540= vertical distance, 400 = width, 60 = height) */
public class TowersOfHanoi extends JPanel {
private int clock = 0;
private Color circles = new Color(176, 56, 251);
public static void main(String[] args) {
// Print the shapes and frame
TowersOfHanoi drawRectangle = new TowersOfHanoi();
JFrame frame = new JFrame("Towers of Hanoi");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(drawRectangle);
frame.setSize(1250, 800);
frame.setVisible(true);
Timer timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
drawRectangle.nextFrame();
drawRectangle.repaint();
}
});
timer.setRepeats(true);
timer.start();
}
public void nextFrame() {
clock++;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
frame1(g);
frame2(g);
frame3(g);
frame4(g);
frame5(g);
frame6(g);
frame7(g);
frame8(g);
frame9(g);
}
private Color frame1(Graphics g) {
Color pegs = new Color(251, 129, 56);
g.setColor(pegs);
// peg 1
g.fillRect(250, 300, 25, 450);
// peg 2
g.fillRect(600, 300, 25, 450);
// peg 3
g.fillRect(950, 300, 25, 450);
// bottom
g.fillRect(200, 700, 825, 50);
// create a color for circles
// cirle 7 (Labeled from bottom to top)
g.setColor(circles);
g.fillOval(60, 640, 400, 60);
g.setColor(Color.BLACK);
g.drawOval(60, 640, 400, 60);
return circles;
}
private void frame2(Graphics g) {
// circle 6
g.setColor(circles);
g.fillOval(85, 580, 350, 60);
g.setColor(Color.BLACK);
g.drawOval(85, 580, 350, 60);
}
private void frame3(Graphics g) {
// circle 5
g.setColor(circles);
g.fillOval(110, 520, 300, 60);
g.setColor(Color.BLACK);
g.drawOval(110, 520, 300, 60);
}
private void frame4(Graphics g) {
// circle 4
g.setColor(circles);
g.fillOval(135, 465, 250, 55);
g.setColor(Color.BLACK);
g.drawOval(135, 465, 250, 55);
}
private void frame5(Graphics g) {
// circle 3
g.setColor(circles);
g.fillOval(160, 420, 200, 45);
g.setColor(Color.BLACK);
g.drawOval(160, 420, 200, 45);
}
private void frame6(Graphics g) {
// circle 2
g.setColor(circles);
g.fillOval(185, 380, 150, 40);
g.setColor(Color.BLACK);
g.drawOval(185, 380, 150, 40);
}
private void frame7(Graphics g) {
// circle 1
g.setColor(circles);
g.fillOval(210, 345, 100, 35);
g.setColor(Color.BLACK);
g.drawOval(210, 345, 100, 35);
}
public void frame8(Graphics g) {
g.clearRect(210, 345, 100, 35);
g.setColor(circles);
g.fillOval(560, 665, 100, 35);
g.setColor(Color.BLACK);
g.drawOval(560, 665, 100, 35);
}
public void frame9(Graphics g) {
g.clearRect(185, 380, 150, 40);
g.setColor(circles);
g.fillOval(890, 660, 150, 40);
g.setColor(Color.BLACK);
g.drawOval(890, 660, 150, 40);
}
}
I am wondering how I would go about removing the circle.
The super.paintComponent(...) will clear the painting on the panel so that is all the is needed.
As you can see I have tried the clearRect();
It is not needed (see my comment above), but then you invoke the fillOval(...) and drawOval(...) methods again so the painting is redone. So the code is doing exactly as you asked it to do.
Is there a way I can set if the method is visible on JPanel
You need a Boolean indicator telling the paint method what to do. Something like:
if (paintOval1)
frame1(g);
if (paintOval2)
frame2(g);
Of course that is approach is very brute force and not a very good approach if for say you have 100 circles to paint. The code become too big.
So, instead you should create a custom class that contains four properties (x, y, width, height, isPainted). Then you create an instance of this class for each circle and add the class to an ArrayList. Something like:
ArrayList<CustomClass> circles = new ArrayList<CustomClass>();
circles.add( new CustomClass(60, 640, 400, 60, true) );
circles.add( new CustomClass(85, 580, 350, 60, true) );
Then in the paintCompnent() method your code becomes simpler:
for (CustomClass circle: circles.get)
{
if (circle.isPainted())
{
g.setColor(...);
g.fillOval(circle.getX(), circle,getY(), circle.getWidth(), circle.getHeight());
...
}
}
Finally you would need a method to change the state of painting a circle. Something like:
pubic void setCirclePainted(int circle, Boolean isPainted)
{
CustomClass circle = circles.get(circle);
circle.setPainted( isPainted );
}
So the key for you is to create your "CustomClass" and give it a proper name. Then you need to implement all the getter/setter methods of the class so you can access the properties of the class.
I actually found that the easiest way for me to understand and do was to use else and else if statements to display the shape based on time. Thanks for the other suggestions though!
public void paintComponent(Graphics g) {
super.paintComponent(g);
frame1(g);
frame2(g);
frame3(g);
frame4(g);
if (clock<= 5) {
frame5(g);
}
else if(clock >= 6) {
frame9(g);
}
frame6(g);
frame7(g);
frame8(g);
}
If i have a two-dimensional array, is it possible to print out the result as a rectangle?
Here is what i have come up with;
int[][] anArrayRectangle = {{0,0},{-2,0},{1,-2},
{0,1},{2,1},{2,0}};
Each point represents one out of six points which together create a rectangle in the unit circle.
The question is if it is possible to display the rectangle in lines, not exclusively using the print method. Perhaps in an applet?
All tips are welcome.
Maybe you could use drawPolygon
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Rectangle extends JPanel {
private int xPos[] = {100, 150, 200, 200, 150, 100};
private int yPos[] = {100, 100, 100, 150, 150, 150};
public void paint(Graphics g) {
super.paint(g);
int length = xPos.length;
g.drawPolygon(xPos, yPos, length);
}
private static JFrame frame = null;
public static void main(String[] args) {
frame = new JFrame("Graphics");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
Rectangle obj = new Rectangle();
frame.add(obj);
}
}