如果通过递归函数调用paintComponent不起作用?

时间:2012-04-26 17:11:08

标签: java swing paintcomponent

  1. 我希望一个接一个地看到所有 Points ,但我看到只能看到1 点。我改变了什么看到所有 Points
  2. System.out中你可以看到10次“设置”,然后是2次 “的paintComponent”。每次设定后我应该改变什么呢? 叫它改变“paintComponente”?
  3. =============================================== ===================================

    public class exampe extends JPanel  
    {
        int x; 
        int y;
    
        public void paintComponent(Graphics g) 
        {
            super.paintComponent(g);
    
            Graphics2D g2 = (Graphics2D) g;
            g2.fillOval(x-2,y-2,4,4);
            System.out.println("paintComponent");        
        }
    
        public void set(int X, int Y)
        {
            x = X;
            y = Y;
            System.out.println("set");
            super.repaint();
        }
    
        public static void main(String args[]) 
        {   
            int e=1;
    
            JFrame frame = new JFrame("TEST");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            exampe ex= new exampe();
            JScrollPane scroll = new JScrollPane(ex);
            frame.getContentPane().add(scroll);
    
            frame.setSize(400, 300);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
    
            for(int i=0; i< 10; ++i)
                ex.set(e+i,e+i);         
        }
    }
    

2 个答案:

答案 0 :(得分:6)

* 简单说明为什么你只能看到最后的更新:*

来自Chet Haase和Romain Guy的肮脏富客户的报价

It is important to note that repaint requests get “coalesced,” or combined. 
So, for example, if you request a repaint and there is already one on the 
queue that has not yet been serviced, then the second request is ignored 
because your request for a repaint will already be fulfilled by the earlier 
request. This behavior is particularly helpful in situations where many
repaint requests are being generated, perhaps by very different situations 
and components, and Swing should avoid processing redundant requests and 
wasting effort.

亲自动手,并询问您不清楚的事情:

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class PointsExample
{   
    private CustomPanel contentPane;
    private Timer timer;
    private int x = 1;
    private int y = 1;
    private ActionListener timerAction = new ActionListener()
    {   
        public void actionPerformed(ActionEvent ae)
        {
            contentPane.set(x, y);
            x++;
            y++;
            if (x == 450)
                timer.stop();
        }
    };
    /*
     * This is just JFrame, that we be 
     * using as the Base for our Application.
     * Though here we are calling our
     * JPanel (CustomPanel), whose
     * paintComponent(...) method, we had
     * override.
     */
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Locate Mouse Position");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new CustomPanel();
        frame.setContentPane(contentPane);  
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
        timer = new Timer(100, timerAction);
        timer.start();
    }

    public static void main(String\u005B\u005D args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new PointsExample().createAndDisplayGUI();
            }
        });
    }
}

class CustomPanel extends JComponent
{
    private int x;
    private int y;

    public void set(int a, int b)
    {
        x = a;
        y = b;
        repaint();
    }   

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(500, 500));
    }

    @Override
    public void paintComponent(Graphics g)
    { 
        g.clearRect(0, 0, getWidth(), getHeight());
        Graphics2D g2 =(Graphics2D) g;
        g2.fillOval(x, y, 4, 4);        
    }
}

以下是代码,它允许您在for循环中迭代时查看您的点,尽管这种方法非常不鼓励,因为与之相关的许多缺点。虽然可以尝试一下,而不是拨打repaint()来电paintImmediately(int ...)paintImmediately(Rectangle rect)

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class PointsExample
{   
    private CustomPanel contentPane;
    private Timer timer;
    private int x = 1;
    private int y = 1;

    /*
     * This is just JFrame, that we be 
     * using as the Base for our Application.
     * Though here we are calling our
     * JPanel (CustomPanel), whose
     * paintComponent(...) method, we had
     * override.
     */
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Locate Mouse Position");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new CustomPanel();
        frame.setContentPane(contentPane);  
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        for (int i = 0; i < 500; i++)
        {
            contentPane.set(x, y);
            x++;
            y++;
            if (x == 450)
                break;
        }
    }

    public static void main(String\u005B\u005D args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new PointsExample().createAndDisplayGUI();
            }
        });
    }
}

class CustomPanel extends JComponent
{
    private int x;
    private int y;

    public void set(int a, int b)
    {
        x = a;
        y = b;
        paintImmediately(0, 0, getWidth(), getHeight());

    }   

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(500, 500));
    }

    @Override
    public void paintComponent(Graphics g)
    { 
        super.paintComponent(g);
        g.fillOval(x, y, 4, 4);         
    }
}

答案 1 :(得分:2)

1:paintComponent()的第一行应该是您的super.paintComponent()

2:你为什么要调用super.repaint(),只需要repaint()

你的卓尔应该是这样的。

public class drow extends JPanel {
 ...........
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 =(Graphics2D) g;

}
public void set_list(LinkedList <point> p){
Points =p;     
repaint();
}

试试这个。 我希望这只是一个结构,你的paintComponent()没有绘制任何东西。

修改

public void set_list(LinkedList <point> p){
Points =p;     
System.out.println("set_ist");// 1:First this line will be displayed then..
repaint();//2: Then this is called, which in turn calls your `paintComponent()`
}

现在,当您调用paintComponent()时,它已

system.out.println("paintComponent");
//3: so now this will be displayed.

这里的问题在哪里?

编辑 - 摇摆定时器

您的代码还可以,但功能处理比GUI更新快,这就是为什么您无法在您面前看到更改的原因。你在做什么,在函数调用之间调用thread.sleep()来减慢它的调用,这不是一个好方法。对于摆动时间的任何时间,使用摆动计时器,我改变了挥杆计时器的代码。

使用Swing Timer:

public class exampe extends JPanel implements ActionListener {

    int x;
    int y;
    int temp = 0;

    public void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.fillOval(x - 2, y - 2, 4, 4);
    }

    public void set(int X, int Y) {

        x = X;
        y = Y;
    }

    public static void main(String args[]) {

        JFrame frame = new JFrame("TEST");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        exampe ex = new exampe();
        JScrollPane scroll = new JScrollPane(ex);
        frame.getContentPane().add(scroll);
        frame.setSize(400, 300);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
        Timer PointTimer = new Timer(1000, ex);
        PointTimer.setInitialDelay(1000);
        PointTimer.start();
        System.out.println("started");
    }

    @Override
    public void actionPerformed(ActionEvent e) {

       // set(rand.nextInt(350), rand.nextInt(350));
          set(temp+10,temp+10);
          temp=temp+2;
          repaint();
    }
}