【问题标题】:Paint on JPanel without redrawing background image在 JPanel 上绘画而不重绘背景图像
【发布时间】:2015-03-04 18:10:36
【问题描述】:

我正在尝试制作一个屏幕截图工具,以全屏方式向用户显示屏幕截图。然后用户将使用一些工具对其进行编辑。 在创建它时,我遇到了一些效果可视化的问题。 我想使用用于在桌面或文件资源管理器上选择多个文件的选择矩形(不知道确切的术语名称)创建所选区域的视觉表示。 example image link

我尝试在背景图片上绘制矩形,但是当我尝试移动光标时,图像令人耳目一新。 然后我尝试用setOpaque(false);setBackground(new Color(0,0,0,0)); 做透明面板,而不是在这个面板上固定鼠标侦听器。 它成功绘制了矩形,但面板的背景立即用默认的灰色填充。 如何使前景面板透明并在其上绘制一些东西,而无需重新绘制背景图像? 这是我的 Glass 课程:

private static final int WIDE = 1920;
private static final int HIGH = 1080;
private final Color clean = new Color(0,0,0,0);
private Point mousePt = new Point(WIDE / 2, HIGH / 2);
private Rectangle mouseRect = new Rectangle();


Glass(){
    this.setOpaque(false);
    this.setBackground(clean);
    this.addMouseListener(new MouseHandler());
    this.addMouseMotionListener(new MouseMotionHandler());
}
public void paintComponent(Graphics g) {  
    g.setColor(clean);
    g.fillRect(0, 0, 1920, 1080 );
    g.setColor(Color.darkGray);
    g.drawRect(mouseRect.x, mouseRect.y, mouseRect.width, mouseRect.height);
}
private class MouseHandler extends MouseAdapter {

    public void mouseReleased(MouseEvent e) {
        System.out.println("released");
        mouseRect.setBounds(0, 0, 0, 0);
        e.getComponent().repaint();
    }

    public void mousePressed(MouseEvent e) {
        mousePt = e.getPoint();
        System.out.println("pressed");
        e.getComponent().repaint();
    }
}
private class MouseMotionHandler extends MouseMotionAdapter {
    public void mouseDragged(MouseEvent e){
         mouseRect.setBounds(
              Math.min(mousePt.x, e.getX()),
              Math.min(mousePt.y, e.getY()),
              Math.abs(mousePt.x - e.getX()),
              Math.abs(mousePt.y - e.getY())); 
        e.getComponent().repaint();
    }
} 

【问题讨论】:

  • 为了尽快获得更好的帮助,请发布MCVE(最小完整可验证示例)或SSCCE(简短、自包含、正确示例)。

标签: java image swing jpanel paint


【解决方案1】:

您是否已经尝试将super.paintComponent(g) 添加到您的paintComponent 方法的开头,如下所示:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.setColor(clean);
    g.fillRect(0, 0, 1920, 1080 );
    g.setColor(Color.darkGray);
    g.drawRect(mouseRect.x, mouseRect.y, mouseRect.width, mouseRect.height);
}

另一种可能性是使用 JPanel 进行所有绘图,并在您的 paintComponent 方法中绘制背景图像:

class DrawPanel extends JPanel{
    public DrawPanel(){
        //...
    }

    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        //Draw background
        g.drawImage(yourImage, 0, 0);

        //Your drawing
        g.setColor(Color.darkGray);
        g.drawRect(mouseRect.x, mouseRect.y, mouseRect.width, mouseRect.height);
    }
}

使用 JPanel 而不是 java.awt.Panel 将使用双缓冲并避免在绘图时出现任何闪烁。

您的父容器代码可能如下所示:

public MainFrame(){
    //...

    //Your old code
    //background image...
    //getContentPane().add(glass);

    getContentPane().add(drawPanel);
}

【讨论】:

  • 是的,我试过了。结果是一样的。 Glass 类已经扩展了 JPanel。
  • 我实际上的意思是,您可以尝试不使用 Glass,而是将 DrawingPanel 添加到您添加 Glass Panel 的 Frame 或 Panel 中。这样,您将在您也用于绘制矩形的同一 JPanel 上绘制背景图像。
  • 我按照你的建议做了。现在看起来它甚至没有绘制一个矩形,但是鼠标侦听器处于活动状态并在事件发生时将文本打印到控制台。
  • @AlexandrZhukov I did what you recommended 但您还没有发布证明问题的SSCCEMCVE。我们不知道您发布的代码的实际使用情况。
猜你喜欢
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多