1

Hi Everyone I want to draw lines to Jlabel Icon with DrawLines() class but the program isn't drawing .When I use to frame.add(m) the program is drawing lines to frame .....

DrawLine m = new DrawLine();
frame.add(m);

but when I use to label.add(m) method .The program isn't working .I need to figure out this problem Why can't I draw lines to jlabelIcon and How can I fix this ?

This is my DrawLine Class

package com.company;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.Line2D;

public class DrawLine extends JComponent {


    public void paint(Graphics g) {
        super.paintComponents(g);


        g.drawLine(300, 152, 63, 185);

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {

        }
        g.drawLine(63, 185, 120, 198);

    }
}

This is my main class

package com.company;

import com.sun.source.tree.Tree;
import jdk.swing.interop.SwingInterOpUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.awt.geom.Line2D;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;


public class Main extends JFrame {

 public static void main(String[] args) {

        JFrame frame = new JFrame("Display Image");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = (JPanel) frame.getContentPane();
        frame.setSize(1000,560);
        JLabel label = new JLabel();
        label.setSize(1000,560);

        label.setIcon(new ImageIcon("myimage path"));
        DrawLine m = new DrawLine();
        label.add(m);

        panel.add(label);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
}
}
  • 3
    Good lord. ***Never*** call `Thread.sleep` in a Swing GUI on the event thread, and that goes a thousand-fold within a painting method. Understand that when you put the event thread or painting to sleep, the entire GUI goes to sleep, rendering it completely useless. – Hovercraft Full Of Eels Apr 03 '20 at 23:28
  • 3
    Also, adding a component to a JLabel isn't going to work. The label doesn't have a layout manager since it is not usually used as a container, and even if it did, that code doesn't really make sense in that spot. I think that you may want to read the Swing graphics tutorials and then start over from first principles. If this were my program, I'd do all painting in the paintComponent method of a JPanel, including the sprite that your JLabel currently holds (get rid of the label) and the lines. I'd be sure to call the super.paintComponent(g) method within my override.... – Hovercraft Full Of Eels Apr 03 '20 at 23:31
  • Hi ı deleted to thread.sleep but the problem still same. – Furkan Aydoğan Apr 03 '20 at 23:32
  • You're also calling `super.paintComponents` within the `paint` method -- not good. You should only call the super method of the current painting method. So if you override paint (but you shouldn't), you'd call `super.paint(g)`, and if you override `paintComponent` (yes), call `super.paintComponent(g)` within it. – Hovercraft Full Of Eels Apr 03 '20 at 23:33
  • What type of graphic are you trying to achieve? – Hovercraft Full Of Eels Apr 03 '20 at 23:34
  • `new ImageIcon("myimage path")` One way to get image(s) for an example (that others can use/test) is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). E.G. [This answer](https://stackoverflow.com/a/10862262/418556) hot links to an image embedded in [this question](https://stackoverflow.com/q/10861852/418556). – Andrew Thompson Apr 04 '20 at 09:02

2 Answers2

2

If your goal is to draw lines and images together, then your best bet for the money is to get rid of ImageIcon and JLabel and instead is to draw them all within a single paintComponent. The images can be drawn as image sprite, and the lines as lines by calling Graphics#drawLine(...) or as Line2D objects as you have using Graphics2D#draw(...)

For example, say we had two BufferedImage objects, upImg and dnImg, and two Point objects that determined the location of these sprites, upPt and dnPt

public class Foo01 extends JPanel {
    // .....
    private Point upPt = new Point(300, 100);
    private Point dnPt = new Point(700, 650);
    private BufferedImage upImg, dnImg;

And say we wanted to draw a line that connected the two image sprites, then these could all be draw within the paintComponent method like so:

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);  // tell the JPanel to do its house-keeping painting

    // make sure that neither image is null
    if (upImg != null && dnImg != null) {

        // draw both images at their respective locations
        g.drawImage(upImg, upPt.x, upPt.y, this);
        g.drawImage(dnImg, dnPt.x, dnPt.y, this);

        // to get a smooth line, use rendering hiints
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // to give the line some thickness
        g2.setStroke(new BasicStroke(5f));  

        // calculate the end-points of the line
        int x1 = upPt.x + upImg.getWidth() / 2;
        int y1 = upPt.y + upImg.getHeight() / 2;
        int x2 = dnPt.x + dnImg.getWidth() / 2;
        int y2 = dnPt.y + dnImg.getHeight() / 2;

        // and then draw it
        g.drawLine(x1, y1, x2, y2);
    }       
}

Here is an example program that does just this -- draws two images with a line connecting. I've also added a MouseAdapter to allow the user to move the first image, the green up-arrow, showing that the line will move as well, since it is calculated within the painting method:

enter image description here

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.URL;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;

public class Foo01 extends JPanel {
    private static final String UP_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Green_circle_icon.jpg";
    private static final String DN_IMG_PATH = "https://upload.wikimedia.org/wikipedia/commons/b/bc/Red_circle_icon.jpg";
    private static final int GUI_W = 1000;
    private static final int GUI_H = 800;
    private Point upPt = new Point(300, 100);
    private Point dnPt = new Point(700, 650);
    private BufferedImage upImg, dnImg;

    public Foo01() {
        MyMouse myMouse = new MyMouse();
        addMouseListener(myMouse);
        addMouseMotionListener(myMouse);
        setBackground(Color.WHITE);
        try {
            URL url = new URL(UP_IMG_PATH);
            upImg = ImageIO.read(url);

            url = new URL(DN_IMG_PATH);
            dnImg = ImageIO.read(url);
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(GUI_W, GUI_H);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (upImg != null && dnImg != null) {
            g.drawImage(upImg, upPt.x, upPt.y, this);
            g.drawImage(dnImg, dnPt.x, dnPt.y, this);

            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2.setStroke(new BasicStroke(5f));

            int x1 = upPt.x + upImg.getWidth() / 2;
            int y1 = upPt.y + upImg.getHeight() / 2;
            int x2 = dnPt.x + dnImg.getWidth() / 2;
            int y2 = dnPt.y + dnImg.getHeight() / 2;
            g.drawLine(x1, y1, x2, y2);
        }       
    }

    private class MyMouse extends MouseAdapter {
        private Point p1 = null;

        @Override
        public void mousePressed(MouseEvent e) {
            if (e.getX() < upPt.x || e.getX() > upPt.x + upImg.getWidth()) {
                return;
            }
            if (e.getY() < upPt.y || e.getY() > upPt.y + upImg.getHeight()) {
                return;
            }
            p1 = new Point(e.getX(), e.getY());
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            if (p1 != null) {
                moveSprite(e);
                p1 = null;
            }
        }

        @Override
        public void mouseDragged(MouseEvent e) {
            if (p1 != null) {
                moveSprite(e);
            }
        }

        private void moveSprite(MouseEvent e) {
            Point p2 = new Point(e.getX(), e.getY());
            int x = upPt.x + p2.x - p1.x;
            int y = upPt.y + p2.y - p1.y;
            upPt = new Point(x, y);

            p1 = p2;
            repaint();
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(()-> {
            Foo01 foo01 = new Foo01();

            JFrame frame = new JFrame("Draw Sprites");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(foo01);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });
    }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
1

If the need is to add custom painting to a JLabel you can override its paintComponent:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;


public class Main extends JFrame {

    private static final String BUG = "https://www.growtopiagame.com/forums/attachment.php?attachmentid=141847&d=1477126665";

    public static void main(String[] args) throws MalformedURLException {

        JFrame frame = new JFrame("Display Image");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DrawLine m = new DrawLine("A crossed bug", new ImageIcon(new URL(BUG)));
        frame.add(m);
        frame.pack();
        frame.setVisible(true);
    }
}

class DrawLine extends JLabel {

    DrawLine(String text, Icon icon) {
        super(text, icon, SwingConstants.CENTER);
        setVerticalTextPosition(SwingConstants.BOTTOM);
        setHorizontalTextPosition(SwingConstants.CENTER);
    }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.YELLOW);

        g2d.setStroke(new BasicStroke(10));
        int w = getWidth();   int h = getHeight();
        g2d.drawLine(0, 0, w, h); //draw right to left diagonal
        g2d.drawLine(0, h, w, 0); //draw left to right diagonal
    }
}

Swing is a single Thread library. All painting tasks are executed in the Event Dispatcher Thread (EDT). Running long processes (such as sleep) on the EDT makes keeps this thread busy, so it does not do other things like updating the gui. The gui becomes unresponsive (freezes).
If you want to add a line after a certain delay, use swing Timer for the job:

public class Main extends JFrame {

    private static final String BUG = "https://www.growtopiagame.com/forums/attachment.php?attachmentid=141847&d=1477126665";

    public static void main(String[] args) throws MalformedURLException {

        JFrame frame = new JFrame("Display Image");
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        DrawLine m = new DrawLine("A crossed bug", new ImageIcon(new URL(BUG)));
        frame.add(m);
        frame.pack();
        frame.setVisible(true);
    }
}

class DrawLine extends JLabel {

    private static final int DELAY = 1500; //millies
    private boolean isDrawSecondDialgonal = false;

    DrawLine(String text, Icon icon) {
        super(text, icon, SwingConstants.CENTER);
        setVerticalTextPosition(SwingConstants.BOTTOM);
        setHorizontalTextPosition(SwingConstants.CENTER);

        //use timer to enable painting of a second diagonal
        javax.swing.Timer timer = new javax.swing.Timer(DELAY, e->  {
            isDrawSecondDialgonal = true;
            repaint();
        });
        timer.setRepeats(false);
        timer.start();
    }

    @Override
    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(Color.YELLOW);

        g2d.setStroke(new BasicStroke(10));
        int w = getWidth();   int h = getHeight();
        g2d.drawLine(0, 0, w, h); //draw right to left diagonal
        if(isDrawSecondDialgonal) {
            g2d.drawLine(0, h, w, 0);//draw left to right diagonal
        }
    }
}

enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65