【问题标题】:Override paint(graphics g) Java覆盖绘画(图形g)Java
【发布时间】:2015-12-21 11:58:38
【问题描述】:

我在 NetBeans 中的 GUI 有一点问题。当用户在鼠标单击位置的 JPanel 中单击时,我会绘制图像(点)。这部分工作得很好。我将每个图像位置存储在两个不同的 ArrayList 中,其中包含 X 位置和 Y 位置。现在我要做的是在单击按钮后删除面板中绘制的最新图像。所以我所做的是删除两个 ArrayList 的最后一个索引,然后调用 repaint() 从 X 和 Y ArrayList 中的位置绘制所有图像(代码如下)。

奇怪的是,我需要调整 GUI 的大小(将其全屏显示或只是更改其大小),以便绘制的图像再次显示在 JPanel 中,否则,面板仍然是空的。

以下是受影响的代码部分:

public void paint(Graphics g) {

    super.paint(g);
    for(int i=0;i<=listePointsX.size()-1;i++) {
        try{
            BufferedImage icon = ImageIO.read(getClass().getResourceAsStream("/myimage.png"));
            Graphics graphe = jPanel1.getGraphics();
            graphe.setColor(Color.BLACK);
            graphe.drawImage(icon, this.listePointsX.get(i),this.listePointsY.get(i), rootPane);
        }catch(Exception e1){

        }
    }

private void jButtonUndoActionPerformed(java.awt.event.ActionEvent evt) {                                            
    if(listePointsX.size()>0){
        int lastObject= listePointsX.size();
        listePointsX.remove(lastObject-1);
        listePointsY.remove(lastObject-1);
        jPanel1.repaint();         
    }
    else{

    }


}   

知道我需要做什么来“刷新”整个事情吗?难道我做错了什么?尝试搜索但没有找到任何东西......

【问题讨论】:

  • 天哪,您在绘画方法中多次重复读取图像文件,这种方法需要非常快。永远不要这样做一次,更不用说多次了。接下来,你不应该覆盖paint,而是应该覆盖paintComponent,你不应该有空的catch块,......这里有很多错误。请停下来,先阅读教程,因为你只是在猜测并且做出了很多错误的猜测。
  • 是的,气垫船说的。将 ImageIO.read() 调用移到 for 循环之外,以便您只执行一次。
  • @Parappa:读取的图像不仅应该在循环之外,还应该在所有绘画方法之外。绘制方法的速度是 GUI 程序感知响应能力的主要决定因素,绝不应该像上面的代码那样被文件 I/O 减慢。
  • @Hovercraft :我知道 Catch 块是空的,我只是还没有这样做,但我肯定不会让它为空,哈哈。
  • 对于 ImageIO.read(),就像你说的那样,它不会改变,所以我不会把它留在循环中......无论是在paint方法中,都只是一个静态的类变量。

标签: java swing paint paintcomponent undo


【解决方案1】:

Graphics graphe = jPanel1.getGraphics(); 不是绘画的工作方式,相反,您应该覆盖面板的 paintComponent 方法并在其中绘制点。

请参阅Painting in AWT and SwingPerforming Custom Painting 了解更多关于如何在 Swing 中进行绘画的详细信息

相反,您的面板应该完成所有工作,管理ArrayList 中的点并绘制它们。如果满足您的设计要求,您的父组件“可能”可以添加或删除点,但核心责任仍由面板承担。

避免在paint 方法中执行任何长时间运行或阻塞操作,它们应该尽可能快地运行。由于图像永远不会改变,您应该只加载一次(在构造类时或第一次需要图像时)并继续使用相同的引用。

【讨论】:

  • 我将尝试创建一个扩展 jPanel 的类 jPanel。然后覆盖paintComponent方法并按照您所说的那样绘制其中的点。如果它工作正常,将发布代码。感谢您的回复!
【解决方案2】:

好的,它现在工作得很好。我必须按照你在这里告诉我的方式去做。我创建了一个扩展 jPanel 的新类(如下)。然后在我的主窗体中,不得不创建这个类的一个对象。每当用户单击时,它将调用此绘图类对象并向 ArrayList 添加一个项目(此对象管理有关创建点的所有内容......它看起来像这样:

public class MyDrawingClass extends JPanel {
ArrayList<Integer> arrayListPointX = new ArrayList<>();
ArrayList<Integer> arrayListPointY = new ArrayList<>();

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    try{
    BufferedImage icon = ImageIO.read(getClass().getResourceAsStream("/images/dot.png"));
    g.setColor(Color.BLACK);
    if(arrayListPointX.size()<=0){
        ...
    }
    else{
        for(int i=0;i<listePointsX.size();i++){
                g.setColor(Color.BLACK);
                g.drawImage(icon, listePointsX.get(i), listePointsY.get(i), rootPane);
        }
    }
    }catch(Exception e){
        ...
    }
}

所以如果我想“撤消”,假设我的“MyDrawingClass”对象被称为“draw”。我可以:draw.arrayListPointX.remove(draw.arrayListPointX.size()-1);并调用 repaint();显示剩余点数。

感谢您的提示,不胜感激! :)

【讨论】:

  • 感谢您的提示不知道 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多