(JAVA) How to differentiate 2d object - java

one simple question. I try to use graphic 2d to make objects . My question is how can we differentiate the variable between 2 object.
For example the below code;
public void paintComponent(Graphics g) {
super.paintComponent(g);
r1 = new Rectangle(10, 10, 50, 30);
r2 = new Rectangle(450, 10, 50, 30);
g.setColor(Color.BLUE);
g.fillRect(10, 10, 50, 30);
g.setColor(Color.RED);
g.fillRect(450, 10, 50, 30);
}
public void actionPerformed(ActionEvent e) {
if (r1.intersects(r2)) {..............
}
from above code,i have 2 rectangle variable r1 and r2, and i can do "if (r1.intersects(r2))"
in the actionPerformed method.
But how about below code when using Graphic2d, how can i differentiate between these 2 triangle, so that it can fit into "if (r1.intersects(r2))", as only one variable "lukis" only exist and it is used to make 2 triangle. Thank you.
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D lukis = (Graphics2D) g;
int[] x = {100, 200, 300};
int[] y = {300, 100, 300};
lukis.setColor(Color.RED);
lukis.drawPolygon(x, y, 3);
int[] x1 = {600, 700, 800};
int[] y1 = {300, 100, 300};
lukis.setColor(Color.RED);
lukis.drawPolygon(x1, y1, 3);
}

Related

How to draw both graphics and buttons properly in Jframe?

I am having a hard time figuring out how to set up both graphics and buttons at thee same time without the buttons flickering.
I am trying to make a navigation program for my robot. I tried to add buttons to my program for the last week or two and nothing works out for me, thanks in advance!
Here is my code:
public static void main (String [] args) throws IOException{
image = ImageIO.read(new File("images/2020.jpg"));
double ratio = (double) image.getHeight() / (double) image.getWidth();
double Yscaled = (int) (Xscaled*ratio);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize((int) Xscaled+15 + 2*ButtonSpace + ButtonWidth,(int) Yscaled+34);
JButton clear = new JButton("Clear");
clear.setBounds((int)Xscaled+ButtonSpace, (int)Yscaled/4 - ButtonHeight/2, ButtonWidth, ButtonHeight);
window.add(clear);
cordList.add((int) Xs);
cordList.add((int) Ys);
JPanel painting = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
y1 = Math.sin(Math.toRadians(a))*c;
x1 = Math.cos(Math.toRadians(a))*c;
y2 = -Math.cos(Math.toRadians(a))*h;
x2 = -Math.sin(Math.toRadians(a))*h;
g.drawImage(image, 0, 0, (int) Xscaled, (int) Yscaled, null);
if (cordList.size() > 0){
if (cordList.get(cordList.size()-2) > Xscaled || cordList.get(cordList.size()-1) > Yscaled){
cordList.remove(cordList.size()-2);
cordList.remove(cordList.size()-1);
}
}
for (int i = 0; i < cordList.size(); i+=2){
int size = 5;
g.setColor(new Color(220, 242, 19));
g.fillOval(cordList.get(i)-size/2, cordList.get(i+1)-size/2, size, size);
g.setColor(new Color(0, 0, 0));
g.drawOval(cordList.get(i)-size/2, cordList.get(i+1)-size/2, size, size);
if(i < cordList.size()-2){
g.drawLine(cordList.get(i), cordList.get(i+1), cordList.get(i+2), cordList.get(i+3));
}
}
Triangle_Shape triangleShape = new Triangle_Shape(new Point2D.Double(Xs - x1, Ys - y1),
new Point2D.Double(Xs + x1, Ys + y1), new Point2D.Double(Xs - x2, Ys + y2));
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(triangleShape);
g2.setColor(new Color(19, 191, 15));
g2.fill(triangleShape);
repaint();
}
};
painting.setBounds(0, 0 ,(int) Xscaled ,(int) Yscaled);
window.add(painting);
window.getContentPane().addMouseListener(new Field());
window.setVisible(true);
}
I had the same problem a few years ago. JPanels can be pretty helpful, but drawing on your JFrame and adding buttons without flickering only works with JLabels for some reason. Just try replacing the JPanel with a JLabel as shown:
public static void main(String[] args) {
// init Frame
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(800, 600);
// !! add Buttons before you add the JLabel to the Frame !!!!
JButton clear = new JButton("Clear");
window.add(clear);
clear.setBounds(100, 100, 100, 100);
// !! change to JLabel!!
JLabel painting = new JLabel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// adds Antialising for rounded edges when adding text
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// test draw
g.setColor(Color.green);
g.fillRect(0, 0, 500, 500);
g.setColor(Color.black);
g.setFont(new Font("Consolas", 0, 100));
g.drawString("Test123'*#", 100, 300);
repaint();
}
};
window.add(painting);
window.setVisible(true);
}
Working Window without flickering
SIDENOTE: You need to add the buttons and other Components before you add the JLabel to the JFrame!
Also added Antialising as a small trick you can use for better visuals.
I Hope it'll help you!

Java - Trouble Passing Variables Between Main Method and Drawing Method

I'm creating a dots and boxes program and I am trying to feed the coordinate values from the main method where the user inputs them to the paintComponent method in the JFrame class. However I have to throw in the (Graphics g) parameter, and I don't see a way around it to feed in the values. It's probably big cringe because I'm still starting out but any help would be great.
import javax.swing.*;
import java.awt.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
JFrame f = new JFrame("Dots & Boxes");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Drawing a = new Drawing();
f.add(a);
f.setSize(1440,990);
f.setVisible(true);
Scanner input = new Scanner(System.in);
System.out.println("You will choose two coordinates on the dot grid to place a line between.");
System.out.println("Make sure that they are right next to each other, either vertically or horizontally (not diagonal)");
int xOne;
int yOne;
int xTwo;
int yTwo;
boolean playerOneTurn = true;
for (int i = 0; i <= 760; i++){
System.out.println("Pick Your First X-Coordinate: ");
xOne = input.nextInt();
System.out.println("Pick Your First Y-Coordinate: ");
yOne = input.nextInt();
System.out.println("Pick Your Second X-Coordinate: ");
xTwo = input.nextInt();
System.out.println("Pick Your Second Y-Coordinate: ");
yTwo = input.nextInt();
playerOneTurn = !playerOneTurn;
}
}
}
class Drawing extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.WHITE);
setFont(new Font("TimesRoman", Font.PLAIN, 20));
g.drawString("0", 75, 45);
g.drawString("1", 110, 45);
g.drawString("2", 145, 45);
g.drawString("3", 180, 45);
g.drawString("4", 215, 45);
g.drawString("5", 250, 45);
g.drawString("6", 285, 45);
g.drawString("7", 320, 45);
g.drawString("8", 355, 45);
g.drawString("9", 390, 45);
g.drawString("10", 417, 45);
g.drawString("11", 452, 45);
g.drawString("12", 487, 45);
g.drawString("13", 522, 45);
g.drawString("14", 557, 45);
g.drawString("15", 592, 45);
g.drawString("16", 627, 45);
g.drawString("17", 662, 45);
g.drawString("18", 697, 45);
g.drawString("19", 732, 45);
g.drawString("0", 40, 75);
g.drawString("1", 40, 110);
g.drawString("2", 40, 145);
g.drawString("3", 40, 180);
g.drawString("4", 40, 215);
g.drawString("5", 40, 250);
g.drawString("6", 40, 285);
g.drawString("7", 40, 320);
g.drawString("8", 40, 355);
g.drawString("9", 40, 390);
g.drawString("10", 35, 425);
g.drawString("11", 35, 460);
g.drawString("12", 35, 495);
g.drawString("13", 35, 530);
g.drawString("14", 35, 565);
g.drawString("15", 35, 600);
g.drawString("16", 35, 635);
g.drawString("17", 35, 670);
g.drawString("18", 35, 705);
g.drawString("19", 35, 740);
int dotx1 = 80;
int doty1 = 70;
((Graphics2D) g).setStroke(new BasicStroke(5));
for (int h = 0; h <= 19; h++) {
for (int i = 0; i <= 19; i++) {
g.drawLine(dotx1, doty1, dotx1, doty1);
dotx1 = dotx1 + 35;
}
dotx1 = 80;
doty1 = doty1 + 35;
}
}
}
You shouldn't call paintComponent by yourself. The method is called when Java is drawing the window.
The reason is that the user shouldn't care about re-drawing, most of the time. Java will decide when to redraw, for example on window minimize/maximize or resizing or when an element is clicked.
To draw animated shapes you must ask Java to redraw your window. You can add f.revalidate() to force components to redraw. Take a look at the documentation here.
Be really careful when using this. Never call this inside a loop without waiting between frames, because your CPU will go crazy if not !
If you want animated shapes, call revalidate() at fixed rate, for example 60fps.
In your case, you could simple put your Scanner inside the loop, ask the user for input, process it and then redraw the window.
Also, revalidate() is not blocking, it will just tell Java that the components tree has changed and must be redraw. But it will do it when he will have the time to do it.
Edit : As we are discussing in commentary, to feed your Drawing with the data to draw you must give him the informations.
First, create your graphical elements, let start with points :
class Point {
public float x, y;
Point(float x, float y) {
this.x = x;
this.y = y;
}
}
In your Drawing (who is in fact your Scene, let rename it), add setters and List
class Scene {
private List<Point> mPoints = new LinkedList<Point>();
public addPoint(Point p) {
mPoints.add(p);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
....
for (Point p : mPoints) {
// draw your points here
}
....
}
}
There several way to improve this simple example. First, you could add a paint(Graphics g) method on Point class.
When you will add another kind of component, you should create a base class Item and extend it in your graphical items (Point, Box...) and put the paint method in this new base class.
It's the way to don't have one list for each kind of element, and then you can just iterate over items and call paint without worrying about the kind behind it (Point, Box...)

How to make tetris blocks fall down every second?

I am making a Tetris clone and I am using a tick method for the game loop (not sure if this is necessary). I want to increase the y value of the block object by 50 pixels every second or so. Can I add some type of delay in my tick method, or is there an easier way?
public class SquareBlock extends GameObject{
public SquareBlock(int x, int y, ID id){
super(x,y,id);
}
public void tick(){
y += 50;
}
public void render(Graphics g){
g.setColor(Color.red);
g.fillRect(x, y, 50, 50);
g.fillRect(x, y + 50, 50, 50);
g.fillRect(x + 50, y, 50, 50);
g.fillRect(x + 50, y + 50, 50, 50);
}
}
Thanks

Animating a painted object [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I've gone through and made classes for my objects and calls to them in my paint component, but I cant actually get them to move. Here is my move and check walls program that is in the object class:
public void move()
{
ballX += dx;
ballY += dy;
checkWalls();
}
//bounce of top/bottom, pass through left/right
public void checkWalls() {
//left-right
if(ballX > w) {
ballX = -diam;
}
else if(ballX < -diam) {
ballX = w;
}
//top-bottom
if(ballY < 0) {
dy *= -1;
}
else if(ballY + diam > h) {
dy *= -1;
}
}
And here is my call to them:
while(true) // infinite loop
{
jelly1.move();
frame.repaint();
try
{
Thread.sleep(10);
}
catch(Exception e){}
}
Also i feel the need to mention i have a background and a background component. The while(true) is in the background component because that's where the objects are created. And the frame is set visible in the background where the main method is.
Paint component is as follows:
public class BackgroundComponent extends JComponent {
Jellyfish jelly1;
Jellyfish jelly2;
Jellyfish jelly3;
Diver diver;
public BackgroundComponent() {
diver = new Diver(100, 300);
jelly1 = new Jellyfish(450, 450);
jelly2 = new Jellyfish(150, 300);
jelly3 = new Jellyfish(350, 75);
diver = new Diver(100, 300);
}
public void paintComponent(Graphics g){
//Drawing instructions go here
//Recover Graphics2D
Graphics2D g2 = (Graphics2D)g;
//Make gradient
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
int w = getWidth();
int h = getHeight();
Color color1 = Color.CYAN;
Color color2 = Color.BLACK;
GradientPaint gp = new GradientPaint(0, 0, color1, 0, h, color2);
g2.setPaint(gp);
g2.fillRect(0, 0, w, h);
//Constructs rectangles on edge of screen and draws them
Rectangle box = new Rectangle(0,0,75,700);
g.setColor(Color.LIGHT_GRAY);
g2.fill(box);
Rectangle box2 = new Rectangle(625, 0, 75, 700);
g.setColor(Color.LIGHT_GRAY);
g2.fill(box2);
//Draws lines, with a stroke of 5, over rectangles
Line2D.Double segment = new Line2D.Double(10, 0, 10, 700);
g2.setStroke(new BasicStroke(5));
g.setColor(Color.GRAY);
g2.draw(segment);
Line2D.Double segment2 = new Line2D.Double(30, 0, 30, 700);
g.setColor(Color.GRAY);
g2.draw(segment2);
Line2D.Double segment3 = new Line2D.Double(50, 0, 50, 700);
g.setColor(Color.GRAY);
g2.draw(segment3);
Line2D.Double segment4 = new Line2D.Double(70, 0, 70, 700);
g.setColor(Color.GRAY);
g2.draw(segment4);
Line2D.Double segment5 = new Line2D.Double(690, 0, 690, 700);
g.setColor(Color.GRAY);
g2.draw(segment5);
Line2D.Double segment6 = new Line2D.Double(670, 0, 670, 700);
g.setColor(Color.GRAY);
g2.draw(segment6);
Line2D.Double segment7 = new Line2D.Double(650, 0, 650, 700);
g.setColor(Color.GRAY);
g2.draw(segment7);
Line2D.Double segment8 = new Line2D.Double(630, 0, 630, 700);
g.setColor(Color.GRAY);
g2.draw(segment8);
//Draws rectangle around title with thick boarder
Rectangle box3 = new Rectangle(40,40,620,75);
g.setColor(Color.WHITE);
g2.setStroke(new BasicStroke(5));
g2.draw(box3);
//Drawing text
String title = "Through the Depths";
//Sets font, font size, and color
g.setFont(new Font("Purisa", Font.BOLD, 50));
g.setColor(Color.DARK_GRAY);
g2.drawString(title, (50), 100);
//Places same text slightly up and over
g.setFont(new Font("Purisa", Font.BOLD, 50));
g.setColor(Color.WHITE);
g2.drawString(title, 53, 97);
//Draws ellipses with a stroke of 2 (these are the bubbles)
Ellipse2D.Double ellipse = new Ellipse2D.Double(450, 200, 150, 150);
g2.setStroke(new BasicStroke(2));
g2.draw(ellipse);
Ellipse2D.Double ellipse2 = new Ellipse2D.Double(510, 375, 90, 90);
g2.draw(ellipse2);
Ellipse2D.Double ellipse3 = new Ellipse2D.Double(470, 485, 70, 70);
g2.draw(ellipse3);
Ellipse2D.Double ellipse4 = new Ellipse2D.Double(510, 580, 45, 45);
g2.draw(ellipse4);
// Draws curves for bubbles
QuadCurve2D q = new QuadCurve2D.Float();
q.setCurve(548, 210, 607, 240, 590, 295);
g2.setStroke(new BasicStroke(3));
g2.draw(q);
QuadCurve2D q2 = new QuadCurve2D.Float();
q2.setCurve(575, 387, 607, 415, 585, 445);
g2.draw(q2);
QuadCurve2D q3 = new QuadCurve2D.Float();
g2.setStroke(new BasicStroke(2));
q3.setCurve(515, 493, 545, 511, 528, 540);
g2.draw(q3);
QuadCurve2D q4 = new QuadCurve2D.Float();
g2.setStroke(new BasicStroke(1));
q4.setCurve(538, 585, 558, 595, 545, 617);
g2.draw(q4);
// Sets color to pink before drawing jellyfish
g.setColor(Color.PINK);
//draws jellyfish
jelly1.draw(g);
jelly2.draw(g);
jelly3.draw(g);
// Draws diver
diver.draw(g);
while(true) // infinite loop
{
jelly1.move();
repaint();
try
{
Thread.sleep(10);
}
catch(Exception e){}
}
}
}
while(true){ ... } and Thread.Sleep inside a paintComponent implementation is completely the wrong way of doing things. By doing this, you are blocking the Event Dispatching Thread completely which means that your UI will no longer be updated properly and the UI will no longer be responsive.
What you should do:
Remove the while(true){ ... } loop from the paintComponent override
Create a javax.swing.Timer, set it to run every 10 milliseconds
In the ActionListener.actionPerformed implementation - the action that will be performed each 10 ms - move the jelly and call for a repaint
Start this timer after initialization is done, eg at the end of your constructor or initialization method (not paintComponent).
Stop the timer when it is no longer needed
Simplified example for this Timer, based on your snippet:
new javax.swing.Timer( 10, new ActionListener( ) {
#override
public void actionPerformed( ActionEvent e ) {
jelly1.move();
repaint();
}
}).start();

Rectangle thickness java

I need to outline in blue 1 rectangle at a time when selected. The code works but I cant see the blue outline very well. what is the easiest way to make the outline thicker. Wither that be drawing another shape over it or something else.
private void displayBlock(Graphics g)
{
for(int i = 0; i < 10; i++)
{
if (occupant[i].equals("Empty"))
{
//Sets the rectangle red to show the room is occupied
g.setColor(emptyColor);
g.fillRect(150+(i*50), 120, aptWidth, aptHeight);
}
else
{
//Sets the rectangle green to show the room is free
g.setColor(Color.red);
g.fillRect(150+(i*50), 120, aptWidth, aptHeight);
}
if (i == selectedApartment)
{
g.setColor(Color.blue);
g.drawRect(150+(i*50), 120, aptWidth, aptHeight);
}
else
{
g.setColor(Color.black);
g.drawRect(150+(i*50), 120, aptWidth, aptHeight);
}
// Draws the numbers in the Corresponding boxes
g.setColor(Color.black);
g.drawString(Integer.toString(i+1), 150+(i*50)+15, 120+25);
}
//Drawing the key allowing the user to see what the colours refer to
g.setFont(new Font("TimesRoman", Font.PLAIN, 14));
g.drawString("Key", 20,120);
g.drawString("Occupied",60,150);
g.drawString("Empty", 60, 170);
// Drawing the boxes to show what the colours mean in the key
g.setColor(Color.red);
g.fillRect(20, 130, 25, 25);
g.setColor(Color.black);
g.drawRect(20, 130, 25, 25);
g.setColor(Color.green);
g.fillRect(20,150,25,25);
g.setColor(Color.black);
g.drawRect(20,150,25,25);
} // End of displayBlock
You can set the thickness of the rectangle by creating a Graphics2D object and setting its stroke.
java.awt.Graphics2D g2 = (java.awt.Graphics2D) g.create();
g2.setStroke(new java.awt.BasicStroke(3)); // thickness of 3.0f
g2.setColor(Color.blue);
g2.drawRect(10,10,50,100); // for example
Maybe you could draw a second rectangle immediately inside the first one. Or multiple of them.
public static void drawRectangle(Graphics g, int x, int y, int width, int height, int thickness) {
g.drawRect(x, y, width, height);
if (thickness > 1) {
drawRectangle(g, x + 1, y + 1, width - 2. height - 2, thickness - 1);
}
}

Categories