I'm making a game like "Draw My Thing".
Now, in this game of course, a server is required, for which every person can see what the other player is drawing.
I managed to paint from one screen to another, but the problem is that the coordinates of the drawings are not the same if the dimension (WIDTH AND HEIGHT) of the screen is different.
Here's some code to begin with:
PAINT COMPONENT
public class DRAW_AREA extends JComponent {
// Image in which we're going to draw
private Image image;
private Graphics2D g2;
private int currentX, currentY, oldX, oldY;
private int WIDTH, HEIGHT;
private ServerSocket SERVER;
private Socket CLIENT;
private BufferedReader INPUT;
private PrintWriter OUTPUT;
protected void paintComponent(Graphics g) {
if (image == null) {
image = createImage(getSize().width, getSize().height);
g2 = (Graphics2D) image.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}
public void clear() {
g2.setPaint(Color.white);
g2.fillRect(0, 0, getSize().width, getSize().height);
g2.setStroke(new BasicStroke(6));
g2.setPaint(Color.black);
repaint();
}
Server
NOTE:
oldX, oldY, currentX, currentY are values sent from the client
if (g2 != null) {
g2.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
}
Related
I'm creating a program which has a Nimbus laf, in there i'm using a JScrollPane with a BasicScrollBarUI.
sp = new JScrollPane(lista);
sp.getVerticalScrollBar().setUI(new CustomScrollBarUI());
The problem is that i need the Nimbus laf for some custom buttons, and the BasicScrollBarUI for the scroll bar which i can't make with Nimbus, if i use both my scrollbar gets out of the border.
Just like that
The class i'm using for ScrollBarUI is:
protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color = ColorPri;
JScrollBar sb = (JScrollBar) c;
scrollBarWidth = 9;
if (!sb.isEnabled()) {
return;
} else if (isDragging) {
color = ColorSec;
}
g2.setColor(color);
g2.fillRect(r.x, r.y, r.width, r.height);
g2.setColor(color);
g2.fillRect(r.x, r.y, r.width, r.height);
}
#Override
protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color = null;
JScrollBar sb = (JScrollBar) c;
if (!sb.isEnabled()) {
return;
} else if (isDragging) {
color = ColorPri;
} else if (isThumbRollover()) {
color = ColorSec;
} else {
color = ColorSec;
}
g2.setPaint(color);
g2.fillRoundRect(1, r.y, 7, r.height, 5, 5);
g2.dispose();
}
#Override
protected void setThumbBounds(int x, int y, int width, int height) {
super.setThumbBounds(x, y, width, height);
scrollbar.repaint();
}
}
The colors are received from the main class
Is there any way to fix it without having to delete the laf or the basicUI?
Thanks in advance
I have been searching all over the internet for a simple way to just rotate a sprite following an angle.
The objective is to have a weapon sprite following the mouse by rotating at the centre of the screen (Top-down shooter in Java). I have tried different things:
NB: The render(Graphics g) function is inside my Gun.java class and uses g, the Graphics element I use to paint on the canvas of the game. The image is the BufferedImage containing the original sprite. And reticle.getAngle() is giving the angle made by the mouse considering the centre of the screen as the origin of the frame.
Attempt 1
public void render(Graphics g) {
// create a new BufferedImage with the image of the gun on it
BufferedImage rotatedImage = new BufferedImage(image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics gRotatedImage = rotatedImage.getGraphics();
gRotatedImage.drawImage(image, 0, 0, null);
// rotate this gun image in the direction of shoot
private AffineTransform at = new AffineTransform();
at.rotate(reticle.getAngle() + Math.PI,
rotatedImage.getWidth()/2, rotatedImage.getHeight()/2);
AffineTransformOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
rotatedImage = op.filter(rotatedImage, null);
// finally display the rotated version of the gun image
g.drawImage(rotatedImage,
(int)(handler.getDisplay().getWidth()/2 - rotatedImage.getWidth()/2),
(int)(handler.getDisplay().getHeight()/2 - rotatedImage.getHeight()/2),
rotatedImage.getWidth(), rotatedImage.getHeight(), null);
}
With this solution, from java2s.com, I end up with the sprite being displayed at the centre and rotating but more like a helicopter... It keeps rotating not following the mouse.
I also tested all the solutions from the related StackOverflow question. This time, I get the weapon being displayed at the top left corner following the mouse, but I can't find a way to place it at the centre of the screen. I tried translations but then the sprite image rotates considering the top left corner as the centre.
Attempt 2
public void render(Graphics g) {
Graphics2D g2d = (Graphics2D) g.create();
double rotation = 0f;
int width = image.getWidth() - 1;
int height = image.getHeight() - 1;
rotation = reticle.getAngle();
rotation = Math.toDegrees(rotation) + 180;
g2d.rotate(Math.toRadians(rotation), width / 2, height / 2);
// g2d.translate(handler.getDisplay().getWidth()/2, handler.getDisplay().getHeight()/2);
g2d.drawImage(image, 0, 0, null);
int x = width / 2;
int y = height / 2;
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.RED);
g2d.drawLine(x, y, x, y - height / 4);
g2d.dispose();
}
I just would like to rotate my sprite every tick of the game by the angle provided by reticle.getAngle() which I know is good. I feel really lost on how to use Graphics2D or AffineTransform to perform rotation. Can someone provide an example on how to rotate a sprite following the mouse and then display it at the centre of the screen?
What is the best way to rotate an image which we then want to display at the centre of the screen?
I don't know if this helps, but I wrote this example program, which has a rectangle (works the same as an image really...) at the center of the screen which rotates following your mouse. The important stuff is in the paintComponent method, pretty much everything else is setup.
package main;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class GPanel extends JPanel{
private int width, height;
private Timer timer;
private int mouseX, mouseY;
public static void main(String[] args) {
JFrame f = new JFrame();
GPanel gp = new GPanel(400, 400);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(gp,BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
public GPanel(int width, int height) {
mouseX = 0;
mouseY = 0;
this.width = width;
this.height = height;
this.setPreferredSize(new Dimension(width, height));
timer = new Timer(17 , new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TO DO
repaint();
}
});
addMouseMotionListener();
timer.start();
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g.setColor(new Color(255, 255, 255));
g2.fillRect(0, 0, width, height);
g2.setColor(new Color(0, 0, 0));
g2.translate(width / 2, height / 2);
double x = mouseX - width / 2d;
double y = mouseY - height / 2d;
double theta = Math.atan2(x, y);
g2.rotate(-theta);
g2.translate(-20, 0);
g2.fillRect(0, 0, 40, 100);
}
private void addMouseMotionListener() {
this.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
}
#Override
public void mouseDragged(MouseEvent e) {
if(SwingUtilities.isLeftMouseButton(e)) {
//TO DO
} else if(SwingUtilities.isRightMouseButton(e)) {
}
repaint();
}
});
}
}
What I would do is create an affine transformation for the sprite. I imagine a sprite, img should be at (cx, cy) and the angle it is rotated should be theta.
Graphics2D g2d = (Graphics2D)g;
AffineTransform at = new AffineTransform();
//translate the center to be at cx, cy.
at.translate(cx - img.getWidth()/2.0, cy - img.getHeight()/2.0);
//rotate about the center of the sprite.
at.rotate(theta, img.getWidth()/2.0, img.getHeight()/2.0);
g2d.drawImage(img, at, this);
I tested it out with this example, where you can click on the JPanel and center the sprite. The sprite follows the mouse cursor around when you move it.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
public class RotateArrow{
int cx = 0;
int cy = 0;
double theta = 0;
public void startGui(){
JFrame frame = new JFrame("arrow");
BufferedImage img = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.setColor(Color.RED);
g.drawLine(0, 32, 64, 32);
g.drawLine(48, 0, 48, 64);
g.dispose();
JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
AffineTransform at = new AffineTransform();
//rotate about center of image.
at.translate(cx - img.getWidth()/2.0, cy - img.getHeight()/2.0);
at.rotate(theta, img.getWidth()/2.0, img.getHeight()/2.0);
g2d.drawImage(img, at, this);
}
};
panel.addMouseListener( new MouseAdapter(){
#Override
public void mousePressed(MouseEvent evt){
cx = evt.getX();
cy = evt.getY();
panel.repaint();
}
} );
panel.addMouseMotionListener( new MouseAdapter(){
#Override
public void mouseMoved(MouseEvent evt){
double dx = evt.getX() - cx;
double dy = evt.getY() - cy;
if(dx != 0 || cy != 0){
theta = Math.atan2(dy, dx);
panel.repaint();
}
}
} );
frame.setContentPane(panel);
frame.setSize(512, 512);
frame.setVisible(true);
}
public static void main(String[] args){
EventQueue.invokeLater( ()->new RotateArrow().startGui() );
}
}
I'm writing paint on screen program using Java Swing. It working on ubuntu linux. But windows shows black screen instead of transparent panel. I included similar example code. What is wrong in my code?
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class Example {
public static final Color COLOR_TRANSPARENT = new Color(0,0,0,0);
public Example() {
Canvas drawArea = new Canvas();
drawArea.setBackground(COLOR_TRANSPARENT);
drawArea.setOpaque(true);
JWindow drawingFrame = new JWindow();
drawingFrame.setBackground(COLOR_TRANSPARENT);
drawingFrame.setContentPane(drawArea);
drawingFrame.pack();
drawingFrame.setSize(640, 460);
drawingFrame.setVisible(true);
drawingFrame.setLocationRelativeTo(null);
drawingFrame.setAlwaysOnTop(true);
}
public static void main(String[] args){
SwingUtilities.invokeLater(Example::new);
}
class Canvas extends JPanel{
private Image image;
private Graphics2D g2;
public Canvas() {
super();
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
g2.setPaint(Color.RED);
g2.fillOval(x-10, y-10, 20, 20);
repaint(x-10, y-10, 20, 20);
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null){
image = createImage(getWidth(), getHeight());
g2 = (Graphics2D) image.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setBackground(COLOR_TRANSPARENT);
clear();
}
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(image, 0,0, null);
}
public void clear(){
System.out.println("clearing canvas ");
g2.setComposite(AlphaComposite.Clear);
g2.setBackground(COLOR_TRANSPARENT);
g2.setColor(COLOR_TRANSPARENT);
g2.fillRect(0, 0, getWidth(), getHeight());
g2.clearRect(0, 0, getWidth(), getHeight());
g2.setPaint(Color.RED);
g2.setComposite(AlphaComposite.SrcOver);
repaint();
}
}
}
Here is screenshot what I wanted.
Example code updated. Now code should work without any other additional code.
For windows I made a couple of changes:
image = createImage(getWidth(), getHeight());
image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
I used a BufferedImage to you can set the alpha values of the image to be transparent.
//public static final Color COLOR_TRANSPARENT = new Color(0,0,0,0);
public static final Color COLOR_TRANSPARENT = new Color(0,0,0,1);
I made the alpha value non-zero, because a value of zero means the Java application won't receive the MouseEvent because it is passed to the application under the window.
I need to some help about drawing shapes with java graphics...,I'm trying to create paint application and when I using mousedragged its drawing multiple shapes (from small to large);like this : http://i.stack.imgur.com/0oQmv.png
Anyone can solve this issue ?
THANKS FOR ALL..
This is DrawingArea class :
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JColorChooser;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import say.swing.JFontChooser;
public class DrawingArea extends JComponent implements MouseListener,MouseMotionListener {
/**
*
*/
Shapers shape;//IMPORTED FROM SHAPERS CLASS TO USE THE ENUMS.
private Font myFont;
private Image image;
private Graphics2D g2;
private static final long serialVersionUID = 1L;
private Color currentColor, initialColor = Color.BLACK;
private int oldX, oldY, lastX, lastY, draggedX, draggedY, width, height, x, y, thickness = 3;
public DrawingArea() { //ADDING LISTENERS FOR JCOMPONENTS.
setDoubleBuffered(false);
addMouseMotionListener(this);
addMouseListener(this);
}
//PENCIL OR ERASER STROKE SETTED BY JSLIDER
public void setStroke(JSlider slider) {thickness = slider.getValue();}
//FOR CHOOSING COLOR FROM COLOR CHOOSER
public void ChooseColor() { currentColor = JColorChooser.showDialog(this, "Choose Your Color", initialColor);}
//CHOOSING FONT FROM FONTCHOOSER (EXTERNAL LIBRARY).
public void ChooseFont() {
JFontChooser chooseFont = new JFontChooser();
int results = chooseFont.showDialog(this);
if (results == JFontChooser.OK_OPTION) {
myFont = chooseFont.getSelectedFont();
}
}
#Override//GETTING FIRST (STARTING) COORDINATE WHEN THE MOUSE PRESSED
public void mousePressed(MouseEvent e) {
oldX = e.getX();
oldY = e.getY();
repaint();
if(shape == Shapers.TEXT){ //DRAWING TEXT (FONT,SIZE AND COLOR ENABLED).
String str = JOptionPane.showInputDialog("Write Your Text Here : ");
g2.setFont(myFont);
g2.setColor(currentColor);
g2.drawString(str, oldX, oldY);
}
}
#Override//GETTING RELEASED COORDINATE TO DRAW LINE.
public void mouseReleased(MouseEvent e) {
lastX = e.getX();
lastY = e.getY();
}
//GETTING COORDINATE TO DRAW FILLEDRECT,FILLEDOVAL,OVAL,RECT.
public void mouseDragged(MouseEvent e) {
draggedX = e.getX();
draggedY = e.getY();
repaint();
width = Math.abs(oldX - draggedX);
height = Math.abs(oldY - draggedY);
x = Math.min(draggedX, oldX);
y = Math.min(draggedY, oldY);
}
public void mouseMoved(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
//CLEAR THE ALL SHAPES DRAWED ON DRAW AREA.
public void clear() {
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, (int) this.getWidth() + 55, (int) this.getHeight() + 55);
super.repaint();
}
//FIRST DRAWING WHITE IMAGE TO ABLE SAVE DRAWED SHAPES ON DRAWING AREA.
//AFTER THAT DRAWING WHEN FIRE BUTTONS ACTIONLISTENER (FROM CODER_PAINT CLASS) SELECTING SHAPES WITH IF & ELSE.
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image == null) {
image = createImage((int) this.getWidth(), (int) this.getHeight());
g2 = (Graphics2D) image.getGraphics();
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, this);
g2.setColor(initialColor);
if(shape == Shapers.PENCIL){
g2.setColor(currentColor);
g2.fillOval(draggedX, draggedY, thickness, thickness);
repaint();
}
else if(shape == Shapers.OVAL){
g2.setColor(currentColor);
g2.drawOval(oldX, oldY, draggedX, draggedX);
repaint();
}
else if(shape == Shapers.FILLEDOVAL){
g2.setColor(currentColor);
g2.fillOval(oldX, oldY, draggedX, draggedY);
repaint();
}
else if(shape == Shapers.RECT){
g2.setColor(currentColor);
g2.drawRect(x, y, width, height);
repaint();
}
else if(shape == Shapers.FILLEDRECT){
g2.setColor(currentColor);
g2.fillRect(x, y, width, height);
repaint();
}
else if(shape == Shapers.LINE){
g2.setColor(currentColor);
g2.drawLine(oldX, oldY, lastX, lastY);
oldX = lastX;//SETTING FIRST COORDINATE TO LAST COORDINATE BECAUSE ABLE TO CONTINUE DRAWING LINE.
oldY = lastY;
repaint();
}
else if(shape == Shapers.ERASER){
g2.setColor(Color.WHITE);
g2.fillRect(draggedX, draggedY, thickness, thickness);
repaint();
}
else{
}
}
//AFTER DRAWING IF THE USER WANTED SAVE THE DRAWED WE CAN USE THIS METHOD.
public void SaveImage() {
try {
String fileName = JOptionPane.showInputDialog(null, "Please enter file name...");
String fileType = JOptionPane.showInputDialog(null, "Please enter file type...");
if (fileName != null && fileType != null && fileName.length() > 0 && fileType.length() > 0) {
ImageIO.write((RenderedImage) image, fileType.toUpperCase(),//WRITING NEW FILE DATAS GETTED FROM DRAW AREA IMAGE.
new File("/Users/MacbookPro/Desktop/" + fileName + "." + fileType.toUpperCase()));
JOptionPane.showMessageDialog(null, "Your image saved.");
} else {
JOptionPane.showMessageDialog(null, "Please try re saving and dont't forget filling the blanks!");
return;
}
} catch (IOException e2) {System.out.println("CanNot save the image!");}
}
//CHANGING CHOOSED COLOR PANEL TO USER CAN KNOW WHICH COLOR CHOOSED NOW
public void changeColor(JPanel panel) {panel.setBackground(currentColor);}
//THIS METHOD USING TO IMPORT IMAGE FROM COMPUTER.
public void PrintImage(Image img) {
g2.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
super.paint(g2);
repaint();
}
//CALLING UPDATE METHOD FOR WHAT I'M ALSO DON'T KNOW :)
public void update(Graphics g) {super.repaint();}
}
Finally after a lot struggle I solved it :)
and there is some example code :
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g2D = (Graphics2D) image.getGraphics();
g2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(image, 0, 0, AREA_WIDTH, AREA_HEIGHT, null);
}
//SETTING STROKE FOR SHAPES
BasicStroke basicStroke = new BasicStroke(thickness);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(basicStroke);
g2d.setPaint(currentColor);
if(g2d != null) {
// ENUMROPE = IS ENUM CLASS USED LIKE BRIDGE BETWEEN MAIN CLASS AND DRAWING AREA
if (figures == EnumRope.RECT && rectangle != null) {
g2d.draw(rectangle);
}else if(figures == EnumRope.FILLEDRECT && rectangle != null){
g2d.fill(rectangle);
}else if (figures == EnumRope.OVAL && ellipse2d != null) {
g2d.draw(ellipse2d);
}else if (figures == EnumRope.FILLEDOVAL && ellipse2d != null){
g2d.fill(ellipse2d);
}else if (figures == EnumRope.LINE && line2d != null) {
g2d.draw(line2d);
}else if(figures == EnumRope.PENCIL && ErasRect != null){
g2d.fill(ErasRect);
}else if(figures == EnumRope.ERASER && ErasRect != null){
g2d.fill(ErasRect);
}
}
}
public void clear()
{ //INVOKING CLEARAREA METHOD
clearArea();
repaint();
}
public void clearArea() {
//THERE CREATED NEW IMAGE TO CLEAN DRAW AREA & ERASE ALL DRAWN SHAPES
image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_ARGB);
}
public void addRectangle(Rectangle rectangle, Color color, int tickness)
{
// DRAW THE RECTANGLE ONTO THE BUFFEREDIMAGE
BasicStroke basicStroke = new BasicStroke(tickness);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setStroke(basicStroke);
g2d.setColor( currentColor );
if(figures==EnumRope.FILLEDRECT){
g2d.fill( rectangle );
}else {
g2d.draw( rectangle );
}
repaint();
}
public void addEllipse(Ellipse2D.Float ellipse2D, Color color, int tickness)
{
// DRAW THE OVAL(circle) ONTO THE BUFFEREDIMAGE
BasicStroke basicStroke = new BasicStroke(tickness);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setStroke(basicStroke);
g2d.setColor( currentColor );
if(figures == EnumRope.FILLEDOVAL) {
g2d.fill( ellipse2D );
}else {
g2d.draw( ellipse2D );
}
repaint();
}
public void addLine(Line2D.Float line2D, Color color, int tickness)
{
// DRAW THE LINE ONTO THE BUFFEREDIMAGE
BasicStroke basicStroke = new BasicStroke(tickness);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setStroke(basicStroke);
g2d.setColor( currentColor );
g2d.draw( line2D );
repaint();
}
public void addEraser(Rectangle2D.Float erasRect, Color color, int tickness)
{
// DRAW THE ERASER(WHITE,CONSTANT RECTANGLE) ONTO THE BUFFEREDIMAGE
BasicStroke basicStroke = new BasicStroke(tickness);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setStroke(basicStroke);
g2d.setColor(Color.WHITE);
g2d.fill(erasRect);
repaint();
}
public void addPencil(Rectangle2D.Float erasRect, Color color, int tickness)
{
// DRAW THE PENCIL(COLORED,CONSTANT RECTANGLE) ONTO THE BUFFEREDIMAGE
BasicStroke basicStroke = new BasicStroke(tickness);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setStroke(basicStroke);
g2d.setColor(currentColor);
g2d.fill(erasRect);
repaint();
}
//NEW INNER CLASS FOR MOUSEADAPTER
class MyMouseListener extends MouseInputAdapter{
private Point startpoint;
#Override
public void mousePressed(MouseEvent e)
{
startpoint = e.getPoint();
rectangle = new Rectangle();
oldX = e.getX();
oldY = e.getY();
repaint();
if(figures == EnumRope.TEXT){
text = JOptionPane.showInputDialog("Write Your Text Here : ");
g2D.setFont(myFont);
g2D.setColor(currentColor);
g2D.drawString(text, oldX, oldY);
repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
currentX = e.getX();
currentY = e.getY();
int x = Math.min(startpoint.x, e.getX());
int y = Math.min(startpoint.y, e.getY());
int width = Math.abs(startpoint.x - e.getX());
int height = Math.abs(startpoint.y - e.getY());
rectangle.setBounds(x, y, width, height);
repaint();
ellipse2d = new Ellipse2D.Float(x, y, width, height);
repaint();
line2d = new Line2D.Float(oldX, oldY, currentX, currentY);
repaint();
ErasRect = new Rectangle2D.Float(currentX, currentY, thickness, thickness);
repaint();
// WE NEED ADD THIS TWO SHAPE HERE BECAUSE SHAPE DARWING WITH MOUSEDRAG !
if (figures == EnumRope.ERASER) {
addEraser(ErasRect, Color.WHITE, thickness);
ErasRect = null;
}else if (figures == EnumRope.PENCIL) {
addPencil(ErasRect, currentColor, thickness);
ErasRect = null;
}
}
// GETTING RELEASED COORDINATE TO DRAW SHAPES BECAUSE SOME SHAPES GETTED
//COORDINATES FROM MOUSEDRAGGED, IF YOU ADD THE SHAPE TO IMAGE IN MOUSEDRAGGED
//SHAPE WILL BE NESTED( more nested shapes from small to big). SO ADD ALL
//COORDINATES WHEN MOUSE RELEASED.
#Override
public void mouseReleased(MouseEvent e) {
if (figures == EnumRope.OVAL) {
addEllipse(ellipse2d, currentColor, thickness);
ellipse2d = null;
} else if (figures == EnumRope.FILLEDOVAL) {
addEllipse(ellipse2d, currentColor, thickness);
ellipse2d = null;
} else if (figures == EnumRope.RECT) {
addRectangle(rectangle, currentColor, thickness);
rectangle = null;
} else if (figures == EnumRope.FILLEDRECT) {
addRectangle(rectangle, currentColor, thickness);
rectangle = null;
} else if (figures == EnumRope.LINE) {
addLine(line2d, currentColor, thickness);
line2d = null;
}
}
}
I hope to this answer benefit to others.
So I am making a paint program that draws by imputing commands from an IRC server chat room. So everything but the drawing works and I checked it (you can see the checking system out :P) but the drawLine() command doesn't do its thing. Please help!
PS:This is a class file in a project, everything else works sending to here trust me!
code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class PadDraw extends JComponent
{
//this is gonna be your image that you draw on
Image image;
//this is what we'll be using to draw on
Graphics2D graphics2D;
//these are gonna hold our coordinates
int currentX = 0, currentY = 0, oldX = 0, oldY = 0;
public PadDraw()
{
}
public void onCommand(String msg)
{
if(msg.equalsIgnoreCase("up"))
{
if(oldY > 0)
{
currentY = currentY - 30;
if(graphics2D != null)
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
}
}
if(msg.equalsIgnoreCase("down"))
{
if(oldY < 861)
{
System.out.println(msg);
System.out.println("Starting Y: " + currentY);
currentY = currentY + 30;
System.out.println("Ending Y: " + currentY);
if(graphics2D != null)
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
System.out.println("Old Y: " + oldY);
}
}
if(msg.equalsIgnoreCase("left"))
{
if(oldX > 0)
{
currentX = currentX - 30;
if(graphics2D != null)
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
oldX = currentX;
oldY = currentY;
}
}
if(msg.equalsIgnoreCase("right"))
{
if(oldX < 847)
{
currentX = currentX + 30;
if(graphics2D != null){
graphics2D.drawLine(oldX, oldY, currentX, currentY);
repaint();
}
oldX = currentX;
oldY = currentY;
}
}
}
public void paintComponent(Graphics g)
{
if(image == null)
{
image = createImage(getSize().width, getSize().height);
graphics2D = (Graphics2D)image.getGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
clear();
}
g.drawImage(image, 0, 0, null);
}
You are forgetting to call super.paintComponent inside the paintComponent method. Some people will wrongly leave it out on purpose thinking its the right way to achieve "continous" painting, but what you are actually doing is breaking the paint chain, and what you actually seeing is paint artifacts, that would lead you to believe there's a continuous paint functionality.
The way you are doing it will not produce a "continous" painting. For one, you're not even drawing the line to the JComponent Graphics context. Second, once you do properly call super.paintComponent inside the paintComponent method, you will lose an previous painting
Here's what you could/should do, instead...
Have a list of Line2D objects.
List<Line2D> lines = new ArrayList<>();
Loop through the List in the paintComponent method, and draw them
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
...
for (Line2D line : lines) {
g2.draw(line);
}
}
Oh btw, paintComponent should be protected and not public
When ever you want to add a line to the drawing, just add another Line2D object to the list and repaint()
lines.add(new Line2D.Double(x1, y1, x2, y2));
repaint();
See more at Line2D API and Graphics2D tutorial