如何在Swing组件调整大小时“做某事”?

30

我有一个继承了JPanel的类。我重写了protected void paintComponent(Graphics g) 方法。

当面板的尺寸改变时,需要重新计算一个变量。请问应该如何正确地实现这个功能?


计算是否很长/耗时? - jjnguy
8个回答

45

就像Adam Paynter建议的那样,你也可以在代码中添加一个内部类,如下所示:

class ResizeListener extends ComponentAdapter {
        public void componentResized(ComponentEvent e) {
            // Recalculate the variable you mentioned
        }
}

你在最内部的括号中输入的代码将会在组件每次调整大小时执行。

然后你可以使用该监听器将其添加到你的组件中。

myJPanel.addComponentListener(new ResizeListener());
您可以使用e.getComponent()获取组件。这样,您就可以从内部类中调用组件的任何方法。
e.getComponent().getWeight();

21

我想你可以重写各种setSizeresize方法并在那里执行计算。不过,你可能无法找到大小可以更改的所有位置。你可能希望让你的类实现ComponentListener并简单地监听自己的调整大小事件。

警告:我不是Swing专家。

警告:我没有编译这段代码。

public class MyJPanel extends JPanel implements ComponentListener {

    public MyJPanel() {
        this.addComponentListener(this);
    }

    public void paintComponent(Graphics g) {
        // Paint, paint, paint...
    }

    public void componentResized(ComponentEvent e) {
        // Perform calculation here
    }

    public void componentHidden(ComponentEvent e) {}

    public void componentMoved(ComponentEvent e) {}

    public void componentShown(ComponentEvent e) {}

}

2
然而,如果组件被调整大小,但它没有被绘制,您可能不想重新计算任何东西。 - jjnguy
+1,因为你展示了需要实现的 ComponentListener 所有方法,这样我就不需要自己查找它们了 ;) - Max Belli

16

如果我正确理解问题的话,那么你应该阅读 Swing 教程中关于如何编写组件监听器的部分,该部分向您展示如何侦听组件大小的变化。


7
如果计算不太耗时,我会在paintComponent()中每次重新计算值。
否则,您可以保存一个组件大小的值,并在paintComponent中将其与新大小进行比较。如果大小发生了变化,则重新计算,否则不需重新计算。
private Dimension size;

protected void paintComponent(Graphics g){
    if (!size.equals(getSize())){
        size = getSize();
        // recalculate value
    }
}

或者,你可以在调整大小事件上进行计算。

//in the constructor add the line
addComponentListener(resizeListener);

private ComponentListener resizeListener = new ComponentAdapter(){
    public void componentResized(ActionEvent e){
        // recalculate value
    }
};

4
最简单的方法是实现一个 ComponentListener:
myjpanel.addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
        //recalculate variable
    }
});

在这里,我使用了一个ComponentAdapter,因为我只打算重写componentResized()


1
这是我使用的代码(其中CoordinatePlane是一个JPanel):

我不是专家

public CoordinatePlane() {
    setBackground(Color.WHITE);
    this.addComponentListener(new ComponentAdapter(){
        public void componentResized(ComponentEvent e) {
            //YOUR CODE HERE         
        }
    });
}

1
This simple example is drawing a red circle in the resized frame....

import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import javax.swing.*;
import java.awt.geom.*;

public class RedCircle extends JFrame implements ComponentListener {
     int getWidth;
     int getHeight;
     
      public RedCircle() {
        super("Red Circle");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addComponentListener(this);             
        pack();
        setVisible(true);
    }
    
      public void componentResized(ComponentEvent e) {
            getWidth = e.getComponent().getWidth();
            getHeight = e.getComponent().getHeight();
            
            Panel pane = new Panel(getWidth,getHeight);
            
            add(pane);
      }
    
   
    public static void main(String[] args) {
        
         RedCircle rc = new RedCircle();
    }
    

 
 public void componentMoved(ComponentEvent e) {
       
    }

    
    public void componentShown(ComponentEvent e) {
     
    }

    
    public void componentHidden(ComponentEvent e) {
    
    }


}


class Panel extends JPanel {
    int panelWidth;
    int panelHeight;
    
    public Panel(Integer getWidth,Integer getHeight) {
       
    panelWidth = getWidth;
    panelHeight = getHeight;
    
    }
    
public void paintComponent(Graphics comp) {
        super.paintComponent(comp);
        Graphics2D comp2D = (Graphics2D) comp;
       
        int realWidth = panelWidth - 17;
        int realHeight = panelHeight - 40;
       
        float Height = (realHeight);
        float Width = (realWidth);
        
    // draw the Red Circle
        comp2D.setColor(Color.red);
        Ellipse2D.Float redCircle = new Ellipse2D.Float(0F, 0F, Width, Height);
        comp2D.fill(redCircle);
    }
}


0

如果它在一个边界布局面板内,并且作为边界布局的中心组件放置,它会自动调整大小。

  1. 如果不起作用,您可能已经忘记了这两个条件之一。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接