简体   繁体   English

无法从另一个类重新绘制 JPanel

[英]Can't repaint JPanel from another class

Following my previous Question about Drawing rectangle within the loop?遵循我之前关于在循环内绘制矩形的问题

Now I want to draw the Rectangle from another class, inside the for-loop.现在我想在 for 循环内从另一个类绘制 Rectangle 。 Here is the class of the loop:这是循环的类:

public class FaceDetect extends SwingWorker {
    
    IntegralCalc3 ic3 = new IntegralCalc3();
    MainFrame mf = new MainFrame();
  
    Rectangle R;

       protected FaceDetect doInBackground() throws Exception {
       //Initial width and height is 60, 60
       outerloop:
       for(int w = 50; w <= ic3.integral.length && w <= ic3.integral[0].length; w = (int) Math.round(w*1.2)  ) {  
            int h = w;

            for(int x = 0; x <= ic3.integral.length-w; x+=5 ) { 
            for(int y = 0; y <= ic3.integral[0].length-w; y+=5 ) {
            
             R = new Rectangle (x, y, w, h);
             mf.lm.add(R);
             mf.lm.revalidate();
             mf.lm.repaint();
            } 
            }             
        } 
        return null;
    }

}

Here is my rectangle class:这是我的矩形类:

public class Rect extends JComponent {
    public int x;
    public int y;
    public int w;
    public int h;
    
    public Rect (int x, int y, int w, int h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        repaint();
    }

    @Override
    public void paintComponent(Graphics g)  {
        Graphics2D g2 = (Graphics2D) g;
        super.paintComponent(g);
        g2.setColor(Color.green);
        g2.drawRect(x+15, y+15, w, h);
    }
}

And finally here is my button inside the JFrame class:最后这是我在 JFrame 类中的按钮:

public class MainFrame extends JFrame {
    Rect R = new Rect(15, 15, 50, 50);
    JPanel lm = new JPanel();
    LayoutManager lay = new OverlayLayout(lm);
    JButton animate = new JButton("animate");

    public MainFrame () {
        setSize(1200, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        lm.setLayout(lay);
        lm.add(R);
}
        animate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { 
               try {   
               new FaceDetect().execute();
                } catch (Exception ex) {
                    Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
                }
               }   
      });

    public static void main(String[] args) {
            EventQueue.invokeLater(() -> new MainFrame());
        }
    }

But nothing happened when I click the animate button.但是当我单击animate按钮时什么也没发生。 Where is the flaw of my codes?我的代码的缺陷在哪里?

Where is the flaw of my codes?我的代码的缺陷在哪里?

You create an instance of the MainFrame in your main() method:在 main() 方法中创建 MainFrame 的一个实例:

public static void main(String[] args) {
        EventQueue.invokeLater(() -> new MainFrame());
    }
}

Then you create another instance in your FaceDetect class:然后在 FaceDetect 类中创建另一个实例:

public class FaceDetect extends SwingWorker {
    IntegralCalc3 ic3 = new IntegralCalc3();
    MainFrame mf = new MainFrame();

You can't just keep creating new instances of an object.您不能只是不断地创建对象的新实例。 You need to pass a reference of the MainFrame class to the FaceDetect class.您需要将 MainFrame 类的引用传递给 FaceDetect 类。

However I would suggest that is still not the proper design since your SwingWorker logic is incorrect.但是我建议这仍然不是正确的设计,因为您的 SwingWorker 逻辑不正确。 You are using the SwingWorker incorrectly!您错误地使用了 SwingWorker! The doInBackground logic should NOT update the state of the Swing component! doInBackground逻辑不应更新 Swing 组件的状态!

Following my previous question...按照我之前的问题...

The suggestion was to use a Swing Timer for animation.建议是使用Swing Timer来制作动画。 That is how your code should be designed.这就是你的代码应该如何设计。 All the Swing Timer does is generate an event at a regular interval. Swing Timer 所做的就是定期生成一个事件。 You then respond to the event.然后您响应该事件。

So in your case you would want to create a move() method in your Rect class, which would update the x/y location and repaint() the component.因此,在您的情况下,您可能希望在 Rect 类中创建一个move()方法,该方法将更新 x/y 位置并 repaint() 组件。 The logic for the Timer would be to simply invoke the move() method. Timer 的逻辑是简单地调用move()方法。

See: How to make JScrollPane (In BorderLayout, containing JPanel) smoothly autoscroll for a basic example of using a Swing Timer.有关使用 Swing Timer 的基本示例,请参阅: 如何使 JScrollPane(在 BorderLayout 中,包含 JPanel)平滑地自动滚动

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM