package donut;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import javax.swing.JPanel;
public class Board extends JPanel{
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2 = (Graphics2D) g;
RenderingHints rh =
new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHints(rh);
Dimension size = getSize();
double w = size.getWidth();
double h = size.getHeight();
Ellipse2D e = new Ellipse2D.Double(0, 0, 80, 130);
g2.setStroke(new BasicStroke(1));
g2.setColor(Color.gray);
for (double deg = 0; deg < 360; deg += 5) {
AffineTransform at =
AffineTransform.getTranslateInstance(w / 2, h / 2);
at.rotate(Math.toRadians(deg));
g2.draw(at.createTransformedShape(e));
}
}
}
Then The JFrame Extended Class Where Board Object is instantiated
package donut;
import javax.swing.JFrame;
public class Donut extends JFrame {
public Donut() {
add(new Board());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(360, 310);
setLocationRelativeTo(null);
setTitle("Donut");
setVisible(true);
}
public static void main(String[] args) {
new Donut();
}
}
I was expecting to See Line Like this : new Board().paint(graphicsObject) So Where Actually This Line is executed Or in a proper way Where actually paint(Graphics g) function is called ?!
If you want to follow the invocation stack to paint(), simply write new Throwable().printStackTrace() or Thread.dumpStack(), this will allow you to follow the calling-stack.
Otherwise, have a look at RepaintManager.addDirtyRegion(JComponent, int, int, int, int);
Anyway, when you are painting to the screen, you should never call paint/paintComponent/paintXXX methods. Only call repaint().
You cannot rely on "when" your method paintComponent(Graphics) or paint(Graphics) will be invoked.
paint is automatically called by Swing whenever it is needed, for example when the component becomes visible (for the first time, or after a minimize of the window, etc), or when the window is resized, basically whenever the contents of a component need to be painted. You should never explicitly call paint in your code, if you wish to force paint then you should call repaint instead.
This link might be helpful
P.S. The code of paint method that is called by super.paint(g) resides in JComponent class, which is extended by JPanel (which is extended by your Board class).
Related
I need help here. I want to give a parameter to the drawLine() method which I get from getSize(). I want to draw a line throughout the whole window by using the getSize() method.
package PROG2;
import java.awt.*;
import javax.swing.*;
class MyComponent extends JComponent {
#Override
public void paintComponent(Graphics g) {
g.drawLine(100, 100, 200, 200);
}
}
public class Übung1 extends JFrame{
public static void berechnen() {
int height = frame.getHeight(); //Here it says it doesn't know "frame" variable but I don't know how to declare it here.
int width = frame.getWidth();
}
public static void main(String[] args){
JFrame frame = new JFrame("First window");
berechnen();
frame.add(new MyComponent());
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
Graphics g = frame.getGraphics();
// int width = frame.getWidth();
// int height = frame.getHeight();
System.out.println("Größe:" + frame.getSize());
//System.out.println(width);
}
}
As Andrew already stated,
you don't want to get the dimensions or size of the JFrame but rather the component that is being displayed within the JFrame's contentPane, here your MyComponent instance.
The best place to get that information is inside of the paintComponent method itself, just prior to drawing the line.
And always call the super's painting method first
I also recommend:
Draw within a JPanel's paintComponent method, not a JComponent, if you want an opaque image
Avoid static methods and fields unless absolutely needed
Note that in the code below, the red line draws through the JPanel's diagonal, and continues to draw the diagonal, even when the JFrame is manually resized:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import javax.swing.*;
public class DrawLine extends JPanel {
private static final Stroke LINE_STROKE = new BasicStroke(15f);
private static final Dimension PREF_SIZE = new Dimension(800, 650);
public DrawLine() {
setPreferredSize(PREF_SIZE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// code to make the line smooth (antialias the line to remove jaggies)
// and to make the line thick, using a wider "stroke"
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setStroke(LINE_STROKE);
// if we want a red line
g2.setColor(Color.RED);
// this is the key code here:
int width = getWidth();
int height = getHeight();
// draw along the main diagonal:
g2.drawLine(0, 0, width, height);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
DrawLine mainPanel = new DrawLine();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
I'm making 2D drawing on Eclipse Oxygen, there are no error in my code but why it does not show any output. I mean when I click run there are no progress.
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
public class HOUSE1 extends Frame {
public void paint(Graphics2D g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawString("HOME SWEET HOME",80,60);
setBackground(Color.white);
Arc2D arc1 = new Arc2D.Double(250,50,500,300,225,90,Arc2D.Double.PIE);
g2d.draw(arc1);
g2d.setColor(Color.red);
g2d.fill(arc1);
Rectangle2D rect = new Rectangle2D.Double(325,300,350,300);
g2d.draw(rect);
g2d.setColor(Color.blue);
g2d.fill(rect);
Rectangle2D rect1 = new Rectangle2D.Double(325,300,350,300);
g2d.draw(rect1);
g2d.setColor(Color.black);
g2d.fill(rect1);
}
public static void main(String[]args){
HOUSE1 f = new HOUSE1();
f.setTitle("HOUSE");
f.setSize(300,100);
}
}
1st: In your main void you need to set your frame (f) to visible --> f.setVisible(true)
2nd: Also you might want to f.pack(); right before you set it to visible to to make sure your components are behaving like expected.
3th: In java we use a capital first letter in class like this "House", fully capital words are used for final's.
Your window is blank because your paint method is never called. Your method
public void paint(Graphics2D g) // DOESN'T WORK
needs to be changed to
public void paint(Graphics g) // Correct
so that it overrides the paint method in Frame. The graphics system will only call paint(Graphics); if your method called paint isn't overriding the method paint(Graphics) in Frame, the one in Frame gets called instead of yours.
You forgot to make your frame visible.
Just add :
f.setVisible(true);
You have to fix your paint method declaration to :
#override
public void paint(Graphics g) {
// your code
}
I am currently working on a project, I get this error Java.lang.NullPointerException, I undrestand that this error happen when you try to refer to a null object instance, but what I do not know, is how I can fix it.
This is my code:
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawOval(150, 150, 10, 10);
}
/** Main Method **/
public static void main(String [] args) {
Run run = new Run();
run.paint(null);
}
Please help me with a solution and also explain it, so that I learn it. Many thanks in advance. Andre
You may not pass null to your paint method! Here is a small example how to do it:
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
class MyCanvas extends JComponent {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval (10, 10, 200, 200);
}
}
public class DrawOval {
public static void main(String[] a) {
JFrame window = new JFrame();
window.setBounds(30, 30, 300, 300);
window.getContentPane().add(new MyCanvas());
window.setVisible(true);
}
}
You almost never call paint methods (including paintComponent) directly as this is what the JVM should be doing.
Don't override the paint(Graphics g) method of a JComponent or JComponent derived class such as a JPanel if you can avoid it. This method, paint, is responsible for not only painting the component but also its borders and its child components, and if not done carefully, overriding this method will not infrequently result in unwanted side effects.
Later when you want to do graphics animation, overriding paint(Graphics g) will result in jerky graphics since it does not do double buffering by default.
By overriding the paintComponent(Graphics g) method instead you fix these issues.
Don't forget to call the super's paintComponent(g) method in your override to erase any unwanted previously drawn images.
Read the Swing Graphics tutorials, both the basic and advanced tutorials. Links at the bottom.
Better code:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class MyBetterCanvas extends JComponent {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(10, 10, 200, 200);
}
public static void main(String[] a) {
MyBetterCanvas canvas = new MyBetterCanvas();
canvas.setPreferredSize(new Dimension(300, 300));
JFrame window = new JFrame("My Better Canvas");
window.getContentPane().add(canvas);
window.setLocationByPlatform(true);
window.pack();
window.setVisible(true);
}
}
Better Still:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class MyBetterStillCanvas extends JComponent {
private static final int PREF_W = 500;
private static final int PREF_H = 500;
private static final int OVAL_X = 10;
private static final int OVAL_Y = OVAL_X;
private static final Paint BG_PAINT = new GradientPaint(0, 20,
Color.black, 20, 0, Color.darkGray, true);
private static final Paint FILL_PAINT = new GradientPaint(0, 0,
Color.blue, 20, 20, Color.red, true);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
// to smooth out graphics
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// let's draw something funky
g2.setPaint(BG_PAINT);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.setPaint(FILL_PAINT);
// avoid use of "magic" numbers
g.fillOval(OVAL_X, OVAL_Y, getWidth() - 2 * OVAL_X, getHeight() - 2
* OVAL_Y);
}
// a cleaner way to set the preferred size of a component
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public static void main(String[] a) {
JFrame window = new JFrame("My Better Canvas");
window.getContentPane().add(new MyBetterStillCanvas());
window.setLocationByPlatform(true);
window.pack();
window.setVisible(true);
}
}
Which displays as:
Tutorials:
Java Tutorials, Really Big Index
Java Swing Tutorials
Basic Swing Graphics Tutorial: Lesson: Performing Custom Painting
More Advanced Graphics Article: Painting in AWT and Swing
You are not doing it the right way. In order to use graphics in java you need to build upon Swing/AWT components. Currently you are passing Graphics as null.
run.paint(null);
You need to implement this using JFrame and other swing components.
Since you are sending null to paint, Graphics g contains null (points to nowhere).
Then inside paint(...) you call setColor(...) on g, which is null. null.setColor(...) causes NullPointerException.
I'm just going through some basic tutorials at the moment. The current one wants a graphics program that draws your name in red. I've tried to make a NameComponent Class which extends JComponent, and uses the drawString() method to do this:
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.Color;
import javax.swing.JComponent;
public class NameComponent extends JComponent {
public void paintMessage(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
g2.drawString("John", 5, 175);
}
}
and use a NameViewer Class which makes use of JFrame to display the name:
import javax.swing.JFrame;
public class NameViewer {
public static void main (String[] args) {
JFrame myFrame = new JFrame();
myFrame.setSize(400, 200);
myFrame.setTitle("Name Viewer");
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
NameComponent myName = new NameComponent();
myFrame.add(myName);
myFrame.setVisible(true);
}
}
...but when I run it, the frame comes up blank! Could anyone let me know what I'm doing wrong here?
Thanks a lot!
You need to override the method paintComponent rather than paintMessage. Adding the #Override annotation over the method will show that paintMessage is not a standard method of JComponent. Also you may want to reduce the y-coordinate in your drawString as the text is currently not visible due to the additional decoration dimensions of the JFrame. Finally remember to call super.paintComponent to repaint the background of the component.
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.RED);
g2.drawString("John", 5, 100);
}
See: Painting in AWT and Swing
You need to add this line after public void paintMessage(Graphics g){ :
super.paint(g);
This tells Java to use the superclass (JComponent) to paint the message.
You will also need to call your method paintComponents() rather than paintMessage()
I have a JPanel that draws shapes and allows those shapes to be selected. I'm starting to add the capability to transform this view using the AffineTransform object, in conjunction with the Graphics2D object.
In my paint() method, of course a Graphics object is passed in. I set a new transform on that object (in this case, just scaling things by 2), and everything in the paint() method draws correctly according to the AffineTransform I just set. At this point the drawing shapes part works great! Now on to the shape selection...
Shape selection starts in the mousePressed() event (My JPanel implements the MouseListener interface). When I have a mousePressed() event, I call this.getGraphics() to get the JPanel's Graphics object. I then case it to a Graphics2D object and call getTransform() on it to get my current transform so I can map the clicked point to the transformed point. When I call getTransform(), however, the AffineTransform is back to the default AffineTransform of [1, 0, 0], [0, 1, 0].
I'm thinking that maybe the Graphics object passed to the JPanel's paint() is different than the one I have in my JPanel, but I'm not sure on that. Does anyone have any idea what's going on here?
Yes, you can't be sure that you will get the same Graphics object back. In fact, you shouldn't work with a Graphics object outside of the paintComponent() method, as this breaks the Swing UI model. You will probably get artifacts and/or incomplete drawing if you do this. The right approach is to have some instance variables that store the state of your UI/widget. When mousePressed() is called, you just update those variables and call repaint(). Then in your paintComponent() method, apply the appropriate transforms and draw your UI.
Simple Class Print An Object OR JPanel.
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.Chromaticity;
import javax.print.attribute.standard.DialogTypeSelection;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class TemplateDemo extends JFrame implements Printable, ActionListener {
JButton btn;
JTextField name_txt;
JPanel panel;
public TemplateDemo() {
panel = new JPanel(null);
panel.setBounds(0, 0, 300, 300);
add(panel);
name_txt = new JTextField();
name_txt.setBounds(0, 10, 200, 20);
panel.add(name_txt);
btn = new JButton("Click");
btn.setBounds(0, 240, 200, 30);
btn.addActionListener(this);
panel.add(btn);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0, 0, 400, 400);
setLayout(null);
setVisible(true);
}
#Override
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
Graphics2D graphics = (Graphics2D) g;
if (pageIndex == 0) {
g.translate((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY());
panel.print(g);
return PAGE_EXISTS;
}
return NO_SUCH_PAGE;
}
#Override
public void actionPerformed(ActionEvent e) {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(this);
PrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
set.add(Chromaticity.COLOR);
set.add(DialogTypeSelection.COMMON);
if (pj.printDialog(set)) {
try {
pj.print(set);
} catch (PrinterException ex) {
}
}
}
public static void main(String[] args) {
new TemplateDemo();
}
}