So if I use this code, I get a screen with nothing. I should display a green rectangle. Had this problem previously but couldn't solve it.
package _47b3n.squaregen;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Main extends Component {
private static final long serialVersionUID = 5547487570978675247L;
public static void main(String [] args) {
new Main();
}
public Main() {
JFrame frame = new JFrame();
frame.setSize(200, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setVisible(true);
repaint();
}
public void render(Graphics g) {
g.setColor(Color.GREEN);
g.drawRect(10,10,10,10);
}
}
Custom painting is done by overriding the paintComponent() method of a JPanel and then you add the panel to the frame.
Read the section from the Swing tutorial on Custom Painting for more information and working examples.
Related
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
class game extends JFrame {
public game(){ //this is constructor
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(500,500);
frame.setTitle("Hello world");
}
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Double(60,90,150,100);
g2.draw(line);
}
public static void main(String args[]) {
game l = new game();
}
}
The above code is compiling in java but on running the code it only displays the frame and its title, but does not include any of the lines being drawn using the Graphics2D and Line2D, what is the mistake that is being made??? The frame being displayed does not show any content, why is that???
First, you are creating and displaying a JFrame which is not an instance of game, so there is no chance that it paints what you have in the paint method of game .
You usually don't want to create a subclass of JFrame for custom painting anyway, just create a subclass of JPanel, and set it as the content pane of the frame.
Also don't override paint, but paintComponent, which is the method responsible for painting the current component.
You should also call the parent method of paintComponent, to make sure that all the usual cleaning takes place correctly.
Also by convention, class names should start with an upper case letter.
One last thing, make the frame visible only once you have added all your components, or you may encounter visual glitches some day.
Putting it all together :
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Game extends JPanel {
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.BLACK);
Line2D line = new Line2D.Double(60, 90, 150, 100);
g2.draw(line);
}
public static void main(final String args[]) {
Game l = new Game();
JFrame frame = new JFrame();
frame.setSize(500, 500);
frame.setTitle("Hello world");
frame.setContentPane(l);
frame.setVisible(true);
}
}
In your constructor call method of JFrame class using this keyword because you extends JFrame class in your class.
public game(){ //this is constructor
/*JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(500,500);
frame.setTitle("Hello world");*/
this.setVisible(true);
this.setSize(500,500);
this.setTitle("Hello world");
}
This solve your problem.
you dont need to create instance of JFrame class ,
modified you constructor as shown below
public game(){ //this is constructor
setVisible(true);
setSize(500,500);
setTitle("Hello world");
}
I've tried to research how Java's 2D rendering works, but I could never understand it. Here is the code in my main class:
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main{
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setSize(new Dimension(500,500));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("JFrame testing");
frame.setVisible(true);
Frame panel = new Frame();
frame.add(panel);
}
}
And then here is for the JPanel class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Frame extends JPanel{
private static final long serialVersionUID = 1L;
public Frame() {
Graphics g = this.getGraphics();
g.drawRect(0, 0, 100, 100);
this.paintComponent(g);
}
}
I am also getting this exception, but I'm not sure what it means:
Exception in thread "main" java.lang.NullPointerException
at Frame.<init>(Frame.java:10)
at Main.main(Main.java:18)
I'm basically just trying to draw a rectangle onto a panel to be shown on the frame I've created. I've heard about the paintComponent method, but I also don't fully understand that.
You should Never use getGraphics() of a Component.
Try below code
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(0, 0, 100, 100);
//this.paintComponent(g);
}
Edit
"why is super.paintComponent(g); called again inside the method?"
The documentation of paintComponent says it pretty well:
if you do not invoker super's implementation you must honor the opaque
property, that is if this component is opaque, you must completely
fill in the background in a non-opaque color. If you do not honor the
opaque property you will likely see visual artifacts.
I was working on this lab in class and when I tried changing the background color it would stay at its default of white can someone please explain where I my programming went wrong.
import javax.swing.*;
import java.awt.*;
public class DemoPoly extends JFrame {
// constructor
public DemoPoly() {
// defines Frame characteristics
int size = 300;
setSize(size,size);
setTitle("a random window");
getContentPane().setBackground(Color.red);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main (String[] args){
// instantiates a JFrame
// exits on close (opional)
JFrame object = new DemoPoly();
}
public void paint (Graphics g){
// This provides the Graphics object g, where
// you are going to use you graphics primitive
// to paint on the content pane of the frame.
int[] arr = {0,100,100,0};
int[] yarr = {0,0,100,100};
Square object = new Square(arr,yarr,Color.red);
AbstractPolygon randSquare = new Square(arr, yarr, Color.red);
}
I see a couple of problems in your code:
Extending JFrame is like saying your class is a JFrame, JFrame is a rigid container, instead create your GUI based on JPanels. See Java Swing extends JFrame vs calling it inside of class for more information.
You're breaking the paint chain by removing the super.paint(g) call on the paint(...) method. When changing your GUI to extend JPanel instead of JFrame you should use the paintComponent(...) method instead. Take the Lesson: Performing Custom Painting in Swing.
You forgot to add #Override notation on the paint(...) method.
You're not placing your program on the Event Dispatch Thread (EDT) which could cause threading issues.
You can solve this by changing your main() method like this:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
//Your constructor here
}
});
}
Instead of setting the JFrame size, override the getPreferredSize() method and call pack(). See Should I setPreferred|Maximum|MiniumSize in Java Swing?. The general consensus says yes.
Your problem gets solved by adding
super.paint(g);
on the paint(...) method:
#Override
public void paint(Graphics g) {
super.paint(g); //Never remove this
//Your code goes here
}
With all the above recommendations taken into account, your code should look like this now:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
public class DemoPoly {
private JFrame frame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new DemoPoly().createAndShowGui();
}
});
}
public void createAndShowGui() {
frame = new JFrame(getClass().getSimpleName());
CustomPanel cp = new CustomPanel();
cp.setBackground(Color.RED);
frame.add(cp);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
}
class CustomPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
}
Which produces this output (and is the same output that you'll get with your current code but better because it gives you more control over your components)
I'm don't understand your question. But here is code for change your background to RED;
public class DemoPoly extends JFrame {
public DemoPoly() {
// defines Frame characteristics
int size = 300;
setSize(size, size);
setTitle("a random window");
//change background here
getContentPane().setBackground(Color.red);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// instantiates a JFrame
// exits on close (opional)
JFrame object = new DemoPoly();
}
}
Your code is well. Maybe use #override in your paint method.
(I've seen the other 2 questions that are similar to mine in title, but they are different and do not provide a solution to my problem.)
Hi,
I have the below code of simple display of lines. I'm declaring a JFrame in the main, then calling on a new instance of the DrawGraph1 class, passing the JFrame as argument.
In the constructor, I'm invoking a thread (EventQueue.invokeLater). The constructor use the JFrame and use it to create some lines and string and whatever)
(Sorry about improper indentation, it has been tweaked a lot)
package test;
import java.awt.*;
import java.awt.geom.*;
import java.text.DateFormatSymbols;
import javax.swing.*;
public class test {
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.setVisible(true);
DrawGraph1 obj = new DrawGraph1(frame);
}
}
class DrawGraph1{
DrawGraph1(final JFrame frame){
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
frame.setTitle("LineDrawing");
frame.add(new JComponent()
{
#Override
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Double();
int decrement = 0, label = 0;
g2.setColor(Color.red);
g.drawString("Red Line ->> High temperatures", 330, 110);
g2.setColor(Color.green);
g.drawString("Green Line ->> Low temperatures", 330, 130);
} });}});}}
So According to my testing, the program reaches the constructor, passes the frame, and starts the thread, but apparently it stops at the line
frame.add(new JComponent()
With the NetBeans debugger underlining (or something) the add method. I also tried in which I invoke the thread at the main, pass the JFrame to the constructor, jump to it and it also stops at the same statement.
The display is simply the Frame itself with whatever settings prior to the add statement (i.e. in the main settings such as size).
I'm pretty sure it is very silly problem since it worked yesterday, not sure what I changed, but I just gave up.
I just changed the order of these two lines.
frame.setVisible(true);
DrawGraph1 obj = new DrawGraph1(frame);
to
DrawGraph1 obj = new DrawGraph1(frame);
frame.setVisible(true);
and the output:
Primarily, you passed the JFrame to the JPanel. You should create the JPanel, and pass it to the JFrame.
Here are the major changes I made.
All of the Swing GUI creation has to be on the Event Dispatch Thread. This includes the JFrame and the JPanel. I added a Runnable to the main method, and called the EventQueue invokeLater method to start the Swing GUI on the Event Dispatch Thread.
I moved all the JFrame code in the main method, and all of the JPanel drawing code in the DrawGraph1 class paintComponent method. The paintComponent method is for painting only. Do your other processing in other classes and / or other methods.
The JFrame methods have to be called in a specific order. Call the JFrame methods in the same order that I called them in your code.
I added a call to super.paintComponent to your paintComponent method. This maintains the Swing paint chain and clears the drawing panel.
I moved the sizing of the GUI from the JFrame to the JPanel. You're concerned with the size of the drawing panel, not the entire GUI.
Here's the revised code. I renamed the class so that it wouldn't conflict with other code in my testing package. You should change it back.
package com.ggl.testing;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SimpleJPanelTest {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
#Override
public void run() {
final JFrame frame = new JFrame("Line Drawing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DrawGraph1());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
};
EventQueue.invokeLater(runnable);
}
}
class DrawGraph1 extends JPanel {
private static final long serialVersionUID = 6733473371292195071L;
public DrawGraph1() {
setPreferredSize(new Dimension(800, 700));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Line2D line = new Line2D.Double();
int decrement = 0, label = 0;
g2.setColor(Color.red);
g.drawString("Red Line ->> High temperatures", 330, 110);
g2.setColor(Color.green);
g.drawString("Green Line ->> Low temperatures", 330, 130);
}
}
My program uses a Jframe, whenever I minimize the window and bring it back up, the program runs itself again. How can I cause it to not do this when minimized?
Code:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
import java.util.Random;
public class AB extends Component {
public void paint(Graphics g) {
Random r = new Random();
g.setColor(Color.black);
g.fillRect(r.nextInt(100), r.nextInt(100), 100, 100);
}
public static void main(String[] args) {
JFrame f = new JFrame("Load Image Sample");
f.getContentPane().setBackground(Color.white);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
f.setSize(dim.width, dim.height);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
f.add(new AB());
f.setVisible(true);
}
}
My guess: you have program logic present in your paint(...) or paintComponent(...) method override. If so, get the logic out of these methods, because as you're finding out, you do not have full control over when or even if they are called. The logic belongs elsewhere, perhaps in a Swing Timer, hard to say without code or a more detailed question.
If this doesn't help, then you'll need to show us the bugs in your code by creating and posting a minimal, runnable, example program as well as tell us more of the details of your program and its misbehavior.
After looking at your code, I see that my assumption/guess was correct: you are selecting your random numbers inside of the paint method, and so they will change with each repaint. You will want to
Create a class that extends JPanel.
Create your random numbers in this class's constructor, and use the random numbers to set class instance fields.
Override this class's paintComponent method
Don't forget to call the super's paintComponent method inside this method.
Use the numbers generated in the constructor in the paintComponent method override to draw your rectangle.
Place your JPanel into a JFrame.
e.g.,
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.*;
#SuppressWarnings("serial")
public class RandomRect extends JPanel {
private static final int MAX_INT = 100;
private static final Color RECT_COLOR = Color.black;
private Random random = new Random();
private int randomX;
private int randomY;
public RandomRect() {
randomX = random.nextInt(MAX_INT);
randomY = random.nextInt(MAX_INT);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(RECT_COLOR);
g.fillRect(randomX, randomY, MAX_INT, MAX_INT);
}
private static void createAndShowGui() {
JFrame frame = new JFrame("RandomRect");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new RandomRect());
//frame.pack();
// frame.setLocationRelativeTo(null);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}