Рисование линий для значка JLabel в Java Swing - PullRequest
1 голос
/ 04 апреля 2020

Привет всем Я хочу нарисовать линии в Jlabel Icon с классом DrawLines (), но программа не рисует. Когда я использую frame.add(m), программа рисует линии в кадре .....

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

но когда я использую метод label.add(m). Программа не работает. Мне нужно выяснить эту проблему Почему я не могу нарисовать линии в jlabelIcon и Как я могу это исправить?

Это мой класс DrawLine

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);

    }
}

Это мой основной класс

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);
}
}

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Если вам нужно добавить пользовательскую живопись в JLabel, вы можете переопределить ее 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 - это отдельная библиотека потоков. Все задачи рисования выполняются в потоке диспетчера событий ( EDT ). Запуск длинных процессов (таких как спящий режим) в EDT заставляет этот поток быть занятым, поэтому он не выполняет никаких других действий, таких как обновление gui. gui перестает отвечать (зависает). Если вы хотите добавить строку после определенной задержки, используйте для задания свинг Timer:

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

1 голос
/ 04 апреля 2020

Если ваша цель - нарисовать линии и изображения вместе, то лучше всего потратить деньги на избавление от ImageIcon и JLabel, а вместо этого нарисовать их все в одном компоненте paintComponent. Изображения могут быть нарисованы как спрайт изображений, а линии - как линии, вызывая Graphics#drawLine(...) или как объекты Line2D, как вы используете Graphics2D#draw(...)

Например, скажем, у нас было два объекта BufferedImage, upImg и dnImg, и два точечных объекта, которые определили местоположение этих спрайтов, upPt и dnPt

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

И, скажем, мы хотим нарисовать линию, которая соединяла два спрайта изображения, тогда все они могли бы быть Рисуем в методе paintComponent примерно так:

@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);
    }       
}

Вот пример программы, которая делает именно это - dr aws два изображения со связующей линией. Я также добавил MouseAdapter, чтобы позволить пользователю перемещать первое изображение, зеленую стрелку вверх, показывающую, что линия также будет двигаться, поскольку она рассчитывается в рамках метода рисования:

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);
        });
    }
}
...