在Java Swing中为JLabel图标绘制线条

在Java Swing中为JLabel图标绘制线条,java,swing,jframe,jlabel,Java,Swing,Jframe,Jlabel,大家好,我想用DrawLines()类将线绘制到Jlabel图标,但程序没有绘制。当我使用toframe.add(m)时,程序正在将线绘制到frame DrawLine m = new DrawLine(); frame.add(m); 但是当我使用label.add(m)方法时,程序不起作用。我需要弄清楚这个问题,为什么我不能给jlabelIcon画线,如何解决这个问题 这是我的抽绳课 package com.company; import javax.swing.*; import ja

大家好,我想用DrawLines()类将线绘制到Jlabel图标,但程序没有绘制。当我使用to
frame.add(m)
时,程序正在将线绘制到frame

DrawLine m = new DrawLine();
frame.add(m);
但是当我使用
label.add(m)
方法时,程序不起作用。我需要弄清楚这个问题,为什么我不能给jlabelIcon画线,如何解决这个问题

这是我的抽绳课

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);
}
}
这是我的主课

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

如果你的目标是把线条和图像画在一起,那么你最好的赚钱方法就是去掉ImageIcon和JLabel,而是把它们都画在一个单独的paintComponent中。通过调用
Graphics#drawLine(…)
可以将图像绘制为图像精灵,将线条绘制为线条,或使用
Graphics2D#draw(…)

例如,假设我们有两个BuffereImage对象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);
    }       
}
下面是一个示例程序,它就是这样做的——用一条线连接两幅图像。我还添加了一个MouseAdapter,允许用户移动第一个图像,即绿色向上箭头,显示线条也将移动,因为它是在绘制方法中计算的:

import java.awt.*;
导入java.awt.event.*;
导入javax.swing.*;
导入java.net.URL;
导入java.io.IOException;
导入java.awt.image.buffereImage;
导入javax.imageio.imageio;
公共类Foo01扩展了JPanel{
私有静态最终字符串UP\u IMG\u PATH=”https://upload.wikimedia.org/wikipedia/commons/7/7d/Green_circle_icon.jpg";
专用静态最终字符串DN\U IMG\U PATH=”https://upload.wikimedia.org/wikipedia/commons/b/bc/Red_circle_icon.jpg";
私有静态最终int GUI_W=1000;
专用静态最终int GUI_H=800;
专用点upPt=新点(300100);
专用点dnPt=新点(700650);
专用缓冲区映像upImg、dnImg;
公共食品01(){
MyMouse MyMouse=新建MyMouse();
addMouseListener(myMouse);
addMouseMotionListener(myMouse);
挫折地面(颜色:白色);
试一试{
URL=新的URL(上行路径);
upImg=ImageIO.read(url);
url=新url(DN\u IMG\u路径);
dnImg=ImageIO.read(url);
}捕获(ioe异常ioe){
ioe.printStackTrace();
}
}
@凌驾
公共维度getPreferredSize(){
返回新维度(GUI_W,GUI_H);
}
@凌驾
受保护组件(图形g){
超级组件(g);
if(upImg!=null&&dnImg!=null){
g、 drawImage(upImg、upPt.x、upPt.y、this);
g、 drawImage(dnImg、dnPt.x、dnPt.y、this);
图形2d g2=(图形2d)g;
g2.setRenderingHint(renderingHits.KEY\u ANTIALIASING,renderingHits.VALUE\u ANTIALIAS\u ON);
g2.设定行程(新基本行程(5f));
int x1=upPt.x+upImg.getWidth()/2;
inty1=upPt.y+upImg.getHeight()/2;
int x2=dnPt.x+dnImg.getWidth()/2;
int y2=dnPt.y+dnImg.getHeight()/2;
g、 抽绳(x1、y1、x2、y2);
}       
}
私有类MyMouse扩展了MouseAdapter{
专用点p1=null;
@凌驾
公共无效鼠标按下(MouseEvent e){
如果(e.getX()upPt.x+upImg.getWidth()){
返回;
}
如果(e.getY()upPt.y+upImg.getHeight()){
返回;
}
p1=新点(e.getX(),e.getY());
}
@凌驾
公共无效MouseEvent(MouseEvent e){
如果(p1!=null){
moveSprite(e);
p1=零;
}
}
@凌驾
公共无效鼠标标记(鼠标事件e){
如果(p1!=null){
moveSprite(e);
}
}
私有void移动精灵(MouseEvent e){
点p2=新点(e.getX(),e.getY());
intx=upPt.x+p2.x-p1.x;
int y=upPt.y+p2.y-p1.y;
upPt=新点(x,y);
p1=p2;
重新油漆();
}
}
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(()->{
Foo01 Foo01=新的Foo01();
JFrame=新JFrame(“绘制精灵”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
添加框架(foo01);
frame.pack();
frame.setLocationRelativeTo(空);
frame.setVisible(true);
});
}
}

如果需要将自定义绘制添加到
JLabel
中,您可以覆盖其
绘制组件

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上运行长进程(如睡眠)会使该线程保持忙碌,因此它不会执行诸如更新gui之类的其他操作。gui变得无响应(冻结)。
如果要在某个延迟后添加行,请对作业使用swing
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
        }
    }
}

天哪。永远不要在事件线程的Swing GUI中调用
Thread.sleep
,这在绘制方法中有千倍的作用。请理解,当您将事件线程或绘制置于睡眠状态时,整个GUI将进入睡眠状态,使其完全无用。此外,将组件添加到JLabel也不会起作用。标签没有布局管理器,因为它通常不作为容器使用,即使它这样做了,该代码在该位置也没有真正意义。我认为您可能需要阅读Swing图形教程,然后从第一原理开始