Drawing a Triangle Component using pen operation - java

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();
}
});
}
}

Related

JFrame graphics ignores the first few renders

Here is a minimal code to see the bug:
import javax.swing.*;
import java.awt.*;
public class Main1 extends JFrame {
static Main1 main;
public Main1() {
super("app");
}
public static void main(String[] args) {
main = new Main1();
main.setBounds(300, 300, 800, 500);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Graphics g = main.getGraphics();
for(int i = 0; i < 100; i++){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, 800, 500);
}
}
}
If i use 100 in the "for" cycle, the frame appears not to be colored, but 200 loops is enough to color it.
I want to make an application where frames change rarely, but this feature ruins the quality of code because I have to make a number of dummy frames.
public static void main(String[] args) {
main = new Main1();
main.setBounds(300, 300, 800, 500);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Graphics g = main.getGraphics();
for(int i = 0; i < 100; i++){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, 800, 500);
}
}
This is not how you do Swing graphics. Getting a Graphics object by calling .getGraphics() on a component gives you a short-lived unstable and sometimes null object. For instance, it takes some time for the created JFrame to render, and if you call getGraphics() and try to use it prior to rendering, the object may be null, and certainly won't wokr.
Instead paint within a JPanel's paintComponent method using the Graphics object given by the JVM as per the tutorials:
public class MainPanel extends JPanel {
public MainPanel {
setPreferredSize(new Dimension(800, 500)));
setBackground(new Color(255, 0, 0)); // if you just want to set background
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use g here do do your drawing
}
}
and then use it like so:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
Tutorial: Lesson: Performing Custom Painting
And yes, if you want to drive a simple animation, use a Swing Timer to help drive it like so:
public class MainPanel extends JPanel {
private int x = 0;
private int y = 0;
public MainPanel {
setPreferredSize(new Dimension(800, 500)));
setBackground(new Color(255, 0, 0)); // if you just want to set background
// timer code:
int timerDelay = 15;
new Timer(timerDelay, ()-> {
x += 4;
y += 4;
repaint();
}).start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use g here do do your drawing
g.setColor(Color.BLUE);
g.drawRect(x, y, 20, 20);
}
}

Draw a Rectangle in Java

I want to draw a rectangle in Java on a Swing application, but I don't know how. I have looked at similar questions, none containing the answer I need. I have tried the following:
private void paintComponent(Graphics graphics, Rectangle rect, Color color) {
contentPane.paintComponents(graphics);
Graphics2D graphics2D = (Graphics2D) graphics;
graphics2D.setColor(color);
graphics2D.draw(rect);
}
I call it like:
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(null);
paintComponent(contentPane.getGraphics(), new Rectangle(0, 0, 50, 50), Color.WHITE);
But it throws a NullPointerException on this line:
graphics2D.setColor(color);
I suspect it is the graphics2D being null. How can I fix this?
You're not even overriding the method correctly. paintComponent only takes a Graphics object as an argument, so you can't add your own.
import javax.swing.*;
import java.awt.*;
public class Test extends JPanel {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new Test());
frame.setVisible(true);
frame.pack();
}
});
}
public Dimension getPreferrdSize() {
return new Dimension(200, 200);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(10, 10, 150, 40);
}
}

Java JFrame draw

I'm currently working with JFrame and I'm trying to draw a rectangle but I don't know how to execute the code paint(Graphics g), how do I get the Graphics object?
package com.raggaer.frame;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Frame {
private JFrame frame;
public Frame() {
this.frame = new JFrame("Java Snake");
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.setSize(new Dimension(500, 500));
// DRAW??
this.frame.setVisible(true);
}
public void paint(Graphics g) {
g.drawRect(10, 10, 200, 200);
}
}
Just call frame.repaint() (which should be called once automatically) to make it repaint the graphics. No need to provide your own Graphics object.
Side note, you should be using a JPanel with paintComponent(Graphics) instead. This will make handling of events a lot easier, especially for a game like snake.
Here is a small code example on Stack Overflow: Java drawing on JPanel which on a JFrame
And one I made myself with usage of Java 8:
import javax.swing.*;
import java.awt.*;
/**
* #author Obicere
*/
public class PaintExample {
public PaintExample() {
final JFrame frame = new JFrame("Paint Example");
final MyPanel panel = new MyPanel();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(PaintExample::new);
}
public class MyPanel extends JPanel {
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.YELLOW);
g.fillOval(0, 0, 50, 50);
g.setColor(Color.BLACK);
g.drawOval(0, 0, 50, 50);
g.drawLine(20, 10, 20, 20);
g.drawLine(30, 10, 30, 20);
g.drawArc(15, 15, 20, 20, 180, 180);
g.drawString("Drawing with swing!", 10, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
As request of your comment, I also modified the program to display objects upon request:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
/**
* #author Obicere
*/
public class PaintExample {
public PaintExample() {
final JFrame frame = new JFrame("Paint Example");
final MyPanel panel = new MyPanel();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(PaintExample::new);
}
public class MyPanel extends JPanel {
private final LinkedList<SmileyFace> faces;
public MyPanel() {
faces = new LinkedList<>();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
faces.add(new SmileyFace(e.getX(), e.getY()));
MyPanel.this.repaint(); // Refresh the display on the screen
}
});
}
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
faces.stream().forEach((e) -> e.render(g));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class SmileyFace {
private final int x;
private final int y;
public SmileyFace(final int x, final int y) {
this.x = x;
this.y = y;
}
public void render(final Graphics g) {
g.setColor(Color.YELLOW);
g.fillOval(x, y, 50, 50);
g.setColor(Color.BLACK);
g.drawOval(x, y, 50, 50);
g.drawLine(x + 20, y + 10, x + 20, y + 20);
g.drawLine(x + 30, y + 10, x + 30, y + 20);
g.drawArc(x + 15, y + 15, 20, 20, 180, 180);
}
}
}

Pause before painting the panel in Java

I am trying to slow down the painting by adding a pause between two consecutive paints. Thread.sleep() apparently doesn't work. Here is the code:
import javax.swing.*;
import java.awt.*;
public class Sa {
int x = 70;
int y = 70;
public static void main(String[] args) {
Sa gui = new Sa();
gui.go();
}
public void go() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
for(int i=0; i<130; i++) {
x++;
y++;
drawPanel.repaint();
try {
Thread.sleep(1500);
} catch(Exception ex) {}
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
Thread.sleep(1500); // will not work!!
g.setColor(Color.green);
g.fillOval(x, y, 80, 40);
}
}
}
Remove Thread.sleep() inside paint() method, not need it, and second, you Thread.sleep() needs to be caught InterruptedException, it may give an error while compiling:
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
//Thread.sleep(1500); // will not work!! (DONT NEED this
g.setColor(Color.green);
g.fillOval(x, y, 80, 40);
Have you looked at Swing Timer ?

java JFrame graphics

I have the following simple code in a JFrame constructor
super(name);
setBounds(0,0,1100,750);
setLayout(null);
setVisible(true);
g = this.getGraphics();
int[] x =new int[]{65, 122, 77, 20, };
int[] y =new int[]{226, 258, 341, 310};
g.setColor(Color.RED);
g.drawPolygon (x, y, x.length);
System.out.println(g);
I get the output on console as:
sun.java2d.SunGraphics2D[font=java.awt.Font[family=Dialog,name=Dialog,style=plain,size=12],color=java.awt.Color[r=255,g=0,b=0]]
But no red polygon drawn on JFrame but just the blank JFrame.
Why ??
Dont overridepaint(..) in JFrame
Rather add custom JPanel with overridden paintComponent(Graphics g) to JFrame
Dont use Null/AbsoluteLayout use an appropriate LayoutManager
Dont call setBounds(..) on JFrame instance (not that its not allowed but cant see it being relevant in this application)
Dont forget to use EDT for creating and changing GUI components:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Test test = new Test();
}
});
you would then do something like this:
public class Test {
/**
* Default constructor for Test.class
*/
public Test() {
initComponents();
}
public static void main(String[] args) {
/**
* Create GUI and components on Event-Dispatch-Thread
*/
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Test test = new Test();
}
});
}
/**
* Initialize GUI and components (including ActionListeners etc)
*/
private void initComponents() {
JFrame jFrame = new JFrame();
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jFrame.add(new MyPanel());
//pack frame (size JFrame to match preferred sizes of added components and set visible
jFrame.pack();
jFrame.setVisible(true);
}
}
class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int[] x = new int[]{65, 122, 77, 20};
int[] y = new int[]{226, 258, 341, 310};
g.setColor(Color.RED);
g.drawPolygon(x, y, x.length);
}
//so our panel is the corerct size when pack() is called on Jframe
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
which produces:
You should better override paint(Graphics g) or paintComponent(Graphics g) than the approach you are trying. Add the lines below and remove the lines after setVisible in your code.
public void paint(Graphics g) {
int[] x =new int[]{65, 122, 77, 20};
int[] y =new int[]{226, 258, 341, 310};
g.setColor(Color.RED);
g.drawPolygon (x, y, x.length);
}

Categories

Resources