So, I have been doing Java for a couple of months, and I'm now learing about Graphics. So, I am trying to make a paint kind of thing, where I can just draw with my mouse. Nothing really fancy, just something to get me started. The program just paints a small dot whenever I drag the mouse. It sort of works, except for the fact that it doesn't save my old dots. It just creates a new one! It would be kind if someone could help me with this problem:
Main class:
import javax.swing.JFrame;
public class Test{
public static void main(String args[]){
Ploofer ploof = new Ploofer();
PumpkinPie f = new PumpkinPie(ploof);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000,1000);
f.setResizable(false);
ploof.setSize(1000,1000);
f.add(ploof);
f.setVisible(true);
}
}
"Ploofer" class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Ploofer extends JPanel{
PumpkinPie pObj = new PumpkinPie(this);
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
this.setBackground(Color.WHITE);
g2d.setColor(new Color(190, 50, 0));
if(pObj.draw==true){
g2d.fillRect(pObj.x, pObj.y, 2, 2);
pObj.draw = false;
}
}
#Override
public void update(Graphics g){
paint(g);
}
//I tried to override update, but it didn't really help
}
"PumpkinPie" class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Ploofer extends JPanel{
PumpkinPie pObj = new PumpkinPie(this);
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
this.setBackground(Color.WHITE);
g2d.setColor(new Color(190, 50, 0));
/* g2d.fillRect(475, 475, 50, 50);
g2d.drawString("^Red^", 484, 540); */
if(pObj.draw==true){
g2d.fillRect(pObj.x, pObj.y, 2, 2);
pObj.draw = false;
}
}
#Override
public void update(Graphics g){
paint(g);
}
//I tried to override update, but it didn't really help
}
It sort of works, except for the fact that it doesn't save my old dots. It just creates a new one!
Check out Custom Painting Approaches for the two common ways to do custom painting:
add objects to paint to an ArrayList and iterate through the list to paint all objects
draw to a BufferedImage and repaint the BufferedImage
In your case I would recommend approach 2.
//I tried to override update, but it didn't really help
Don't override update(). There is no reason to do that. That is an old AWT approach with is not needed in Swing.
Related
I am attempting to make a drawing pad using Graphics2D where I draw a line from two Points, a startPoint and an endPoint, within the MouseMotionlistener method mouseDragged, but whenever I add this line, it appears to be really jagged and rough. I have used this to help with AntiAliasing but it seems to do nothing.
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
but it does not help whatsoever for high strokevalues.
This is my code for drawing.
public void mouseDragged(MouseEvent e) {
//sets up graphics2d object
g2 = (Graphics2D)getGraphics();
g2.setStroke(new BasicStroke(strokeSize));
g2.setColor(color);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//draws line using points and shapes
endPoint = e.getPoint();
Shape line = new Line2D.Double(beginPoint, endPoint);
g2.draw(line);
beginPoint = endPoint;
beginPoint is given a value within mousePressed
There are lots of (really cool) rendering hints! I would recommend you start playing around with all of them and see what combinations give you the desired results!
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// Remember, graphics is a shared context, when you make changes
// to it, you should also undo them. To this end, we use create/dispose
// which takes a snapshot of the current state and restores it at the
// end.
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2.setColor(Color.BLACK);
g2.drawLine(0, 0, getWidth(), getHeight());
g2.drawLine(getWidth(), 0, 0, getHeight());
g2.dispose();
}
}
}
Warning
g2 = (Graphics2D)getGraphics(); is a very, very bad idea and isn't how custom painting is suppose to work.
getGraphics is nothing more then a snapshot of what was last painted during the last paint pass and will be invalidated on the next paint pass.
I would highly recommend reading through Performing Custom Painting and Painting in AWT and Swing to get a better understanding of how painting in Swing works and how you're suppose to work with it.
Drawing with the mouse is not a uncommon question and has any number of answers. I'd recommend having a looking around at some of the other question/answers to see how this might be done and adopt them to your needs
I am having trouble with creating a stroked shape in BasicStroke Outline = new BasicStroke(10f, 50, 50);. The error I am currently getting is error:
can't find symbol canvas.setStroke(Outline) pointing to the dot.
I am new to constructors so any help would be great and the only thing I did similar to this was creating an instance of Scanner.
import javax.swing.JFrame;
import java.awt.Graphics;
import java.awt.Color; //sets color
import java.awt.BasicStroke;
import java.awt.Graphics2D;
public class ColoredOlypmicRings extends JFrame
{
//varriables go here
public void paint(Graphics canvas)
{
super.paint (canvas);
canvas.setColor(Color.green);
canvas.drawOval(100,100,100,100); //color green
canvas.setColor(Color.red);
canvas.drawOval(200,200,100,100); //color red
final BasicStroke Outline = new BasicStroke(10f, 50, 50);
canvas.setStroke(Outline);
canvas.drawOval(300,300,200,200);
}
public ColoredOlypmicRings()
{
setSize(600,400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args)
{
ColoredOlypmicRings guiWindow = new ColoredOlypmicRings();
guiWindow.setVisible(true);
}
}
The Graphics class can't handle Strokes and doesn't have methods for setting it as its API will tell you.
The Graphics2D class on the other hand can handle this class and should be used to handle it. So cast your Graphics object to a Graphics2D object.
e.g.,
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setStroke(....); // do it here after casting
}
Also check out the BasicStroke API as you're not using the constructor correctly, passing in incorrect parameters.
Other issues:
Don't draw directly in a JFrame or other top-level window.
Instead draw in the paintComnponent method of a JPanel that is displayed in the JFrame.
The three int BasicStroke constructor is being mis-used as the 2nd and 3rd parameters should be constants that represent the cap and join state of the Stroke object.
I am following a tutorial on applets on Youtube. My code looks exactly the same as the tutorial's does, but the background does not turn pink and Eclipse tells me there are errors in implements MouseListener and g2.draw(line); What did I do wrong? Click here for the video and here is my code:
package applets1;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.JApplet;
public class clean extends JApplet implements MouseListener{
public void start(){
}
public void init(){
setBackground(Color.pink);
addMouseListener(this);
}
public void paint(Graphics g){
Graphics g2D = (Graphics2D) g;
g.drawString("WAZZUP", 100, 90);
g.drawRect(100, 100, 400, 400);
Point2D.Double topLeft = new Point2D.Double(0.0, 25.0);
Point2D.Double topRight = new Point2D.Double(100.0, 25.0);
Line2D.Double line = new Line2D.Double(topLeft, topRight);
g2D.draw(line);
}
}
EDIT: The error at g2D.draw(line); says The method draw(Line2D.Double) is undefined for the type Graphics. I changed g2D.drawLine to g2D.draw
I also fixed the implements typo. The background is still not pink, despite the absence of an error and everything else works. What can I do to fix the pinkness and g2D.draw?
You have a typographical error. implements not implemets:
public class clean extends JApplet implements MouseListener{
Also you have declared g2D with the wrong type (Graphics vs Graphics2D). In other words, instead of
Graphics g2D = (Graphics2D) g; you need to use
Graphics2D g2D = (Graphics2D) g;
Once you make the above change, you will be able to invoke the g2D.draw() methods using the various 2D classes as parameters.
Also you have overridden the paint() method but you have not included a call to super.paint() - this should be the first line in your paint() method. Once you do this the background color should be rendered correctly (because it is handled by the base class, JApplet)
Write a program that fills the window with a larrge ellipse. The ellipse shoud touch the window boundaries, even if the window is resized.
I have the following code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,150,200);
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
And the main class:
import javax.swing.JFrame;
public class EllipseViewer {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setSize(150, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
EllipseComponent component = new EllipseComponent();
frame.add(component);
frame.setVisible(true);
}
}
in your EllipseComponent you do:
Ellipse2D.Double ellipse = new Ellipse2D.Double(0,0,getWidth(),getHeight());
I'd also recommend the changes given by Hovercraft Full Of Eels. In this simple case it might not be an issue but as the paintComponent method grows in complexity you realy want as little as possible to be computed in the paintComponent method.
Do not resize components within paintComponent. In fact, do not create objects or do any program logic within this method. The method needs to be lean, fast as possible, do drawing, and that's it. You must understand that you do not have complete control over when or even if this method is called, and you certainly don't want to add code to it unnecessarily that may slow it down.
You should create your ellipse in the class's constructor. To resize it according to the JComponent's size and on change of size, use a ComponentListener.:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import javax.swing.JComponent;
public class EllipseComponent extends JComponent {
Ellipse2D ellipse = null;
public EllipseComponent {
ellipse = new Ellipse2D.Double(0,0,150,200);
addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
// set the size of your ellipse here
// based on the component's width and height
}
});
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.draw(ellipse);
g2.setColor(Color.red);
g2.fill(ellipse);
}
}
Caveat: code not run nor tested
Could any body diagnose the problem I am facing?
As you run the demo you can see the middle part left blank, I need to fill the entire area..
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class FillDemo
{
public static void main(String aths[])
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel pnl = new PolygonDemo();
pnl.setSize(100, 200);
f.getContentPane().add(pnl);
f.setSize(400,280);
f.setLocation(200,200);
f.setVisible(true);
}
}
class PolygonDemo extends JPanel
{
public PolygonDemo()
{
setBackground(Color.white);
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Polygon p=new Polygon();
p.addPoint(100,0);
p.addPoint(100,100);
p.addPoint(0,100);
p.addPoint(0,0);
p.addPoint(80,0);
p.addPoint(80,20);
p.addPoint(40,20);
p.addPoint(40,40);
p.addPoint(80,40);
p.addPoint(80,100);
p.addPoint(20,100);
p.addPoint(20,80);
p.addPoint(60,80);
p.addPoint(60,60);
p.addPoint(20,60);
p.addPoint(20,0);
p.addPoint(0,0);
g2.setColor(Color.BLACK);
g2.draw(p);
g2.setColor(new Color(120,250,100));
g2.fillPolygon(p);
//g2.fillPolygon(p.xpoints,p.ypoints,p.npoints);
}
}
Many thanks in advance
Your polygon intersects with itself. The fillPolygon method can not clearly decide which point is in and which is out. From the fillPolygon javadoc:
The area inside the polygon is defined using an even-odd fill rule, also known as the alternating rule.
Perhaps you can split your polygon into three single ones.
Draw Rectangle and Fill Color.....
public void paint(Graphics g)
{
int[] xPoints = {100,50,150};
int[] yPoints = {100,200,200};
g.setColor(Color.black);
g.drawPolygon(xPoints, yPoints, 3);
g.setColor(Color.red);
g.fillPolygon(xPoints, yPoints, 3);
}