如何在将鼠标放在图形元素顶部的画布上添加 JPanel?

Posted

技术标签:

【中文标题】如何在将鼠标放在图形元素顶部的画布上添加 JPanel?【英文标题】:How to add a JPanel on top of a canvas placing the mouse on the top of a Graphic element? 【发布时间】:2016-07-18 15:11:27 【问题描述】:

我正在构建测试应用程序以供以后改进。我有一个使用游戏循环(更新、渲染)在画布上绘制的 Java 图形元素。它是一个红色的球,当鼠标放在它上面时会改变它的颜色。

我正在尝试找出一种方法来在鼠标位于球顶部时创建 JPanel,以在球内显示某种“隐藏信息”。我最初的想法是将使用JFreeChart API制作的直方图显示为“隐藏信息,所以我相信如果我创建这个JPanel我可以稍后将直方图添加到创建的JPanel中。类似于这个http://www.bitjuice.com.au/research/#hierarchicalclassificationexample。在链接中,无论何时将鼠标放在矩形上方,会显示额外的信息。

到目前为止,我已经得到了这个代码:

*Window.java *(JFrame)

public class Window extends JFrame 

 JLabel title_label = new JLabel();

public Window(int width, int height, String title, Animation animation)

    setTitle(title);
    setPreferredSize(new Dimension(width,height));
    setMaximumSize(new Dimension(width,height));
    setMinimumSize(new Dimension(width,height));        
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setResizable(false);
    setLocationRelativeTo(null);
    add(animation);
    add(title_label, BorderLayout.SOUTH);
    setVisible(true);
    animation.start();


public void update()
    title_label.setText(Animation.mouseX + " " + Animation.mouseY);


Animation.java(游戏循环)

public class Animation extends Canvas implements Runnable 

public static final int WIDTH = 1024, HEIGHT =  WIDTH/12*9 ;
private Thread thread;
private boolean running = false;
public static int mouseX,mouseY;
public Window window;
Button button = new Button();
public Animation()
     window = new Window(WIDTH, HEIGHT,"Test", this);   
     addMouseMotionListener(new Handler(window));
     addMouseListener(new Handler(window));


public void run()              
    this.requestFocus();
    long lastTime = System.nanoTime();
    double  amountOfTicks = 60.0;
    double ns = 1000000000/amountOfTicks;
    double delta = 0;
    long timer = System.currentTimeMillis();
    int frames = 0;


    while(running)         
        long now = System.nanoTime(); 
        delta += (now-lastTime) / ns;
        lastTime = now;         
        while(delta >= 1)
            update();               
            delta--;
        
        if(running) 
            render();
        frames++;           
        if(System.currentTimeMillis() - timer >1000)   
            //System.out.println(frames);
            timer += 1000;
            frames = 0;
        
    
    stop();


public synchronized void start()   
        thread = new Thread(this);
        thread.start();
        running = true;
    

public synchronized void stop()            
        try
            thread.join();
            running = false;                
        catch(Exception e)
            e.printStackTrace();
        
    



public static int getMouseX()
    return mouseX;


public static int getMouseY()
    return mouseY;


public static void setMouseX(int x)
    mouseX = x;


public static void setMouseY(int y)
    mouseY = y;


private void update()      
    window.update();
    button.update();


private void render()
    BufferStrategy bs = this.getBufferStrategy();
    if(bs == null)
        this.createBufferStrategy(4);
        return;
           
    RenderingHints rh = new RenderingHints(
            RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    rh.put(RenderingHints.KEY_RENDERING,
            RenderingHints.VALUE_RENDER_QUALITY);
    Graphics g = bs.getDrawGraphics();
    Graphics2D g2d = (Graphics2D)g;
    g2d.setRenderingHints(rh);
    g2d.setColor(Color.white);
    g2d.fillRect(0, 0, WIDTH, HEIGHT);      
    button.render(g);
    g.dispose();
    g2d.dispose();
    bs.show();


public static void main(String args[])
    new Animation(); 
 


Handler.java

public class Handler extends MouseAdapter 

int x,y; 

private Window window;
public Handler(Window window)
    this.window = window;


 public void mouseMoved(MouseEvent e)
     Animation.setMouseX(e.getX());
     Animation.setMouseY(e.getY());

 

Button.java

public class Button 

Ellipse2D mask;
boolean mouseIsOn = false;

public Button()
    mask = new Ellipse2D.Double(500,350,50,50);

public void update()
    if(mask.contains(Animation.mouseX,Animation.mouseY))
        mouseIsOn = true;
    else
        mouseIsOn = false;


public void render(Graphics g)

    if(mouseIsOn)
        g.setColor(Color.green);
    else
        g.setColor(Color.red);
    g.fillOval(500,350, 50, 50);


感谢您的帮助。

【问题讨论】:

【参考方案1】:

重量和重量轻的组件不会混合。 JPanel 是一个轻量级的组件,而 Canvas 是重量级的。重量级组件总是在轻量级组件之上绘制。

您可能想要做的只是将鼠标悬停部分直接绘制到画布上。如果你需要的话,你可以使用 FontMetrics 来绘制字符串。

【讨论】:

谢谢,但我不想只使用字符串。我想显示来自 JFreeChart (i1-scripts.softpedia-static.com/screenshots/…) 的图表如果我通过单击元素打开另一个 JFrame 怎么办? 是的。您可以将 CharPanel 添加到 JFrame,然后显示 JFrame。只要您的新图表 JFrame 不与光标所在的区域重叠,您甚至可以在光标移出打开它的区域后隐藏 JFrame。 好的,我试试。谢谢!

以上是关于如何在将鼠标放在图形元素顶部的画布上添加 JPanel?的主要内容,如果未能解决你的问题,请参考以下文章

canvas 使用 isPointInPath() 判断鼠标位置是否在绘制的元素上

如何获取鼠标单击画布元素的坐标? [复制]

visio怎么移动图形不是画布

即使水平滚动,如何使放置在fabricjs对象顶部的DOM元素保持在那里

如何使用画布和javascript同时绘制线条在鼠标指针顶部显示x和y坐标

如何使 JavaScript 画布元素随鼠标移动?