java.awt.Label 派生类的paint(Graphics g) 方法未调用

Posted

技术标签:

【中文标题】java.awt.Label 派生类的paint(Graphics g) 方法未调用【英文标题】:paint(Graphics g) method of java.awt.Label derived class not called 【发布时间】:2022-01-02 04:57:54 【问题描述】:

我儿子学校的课程仍然包括学习 Java AWT 的学生。虽然我觉得这不是最好的办法,但我也改不了,因为这是教育部规定的。无论如何,我试着帮助我儿子练习,就像我多年前自己编写的 AWT 一样。但是我在渲染标签时遇到了问题。我实际上是在 AWT 中创建一个简单的表,因为缺少表。方法是采用 GridLayout 并向其添加标签。这很好用,但我希望在列和行之间有分隔线。因此,我对标签进行了子分类并像这样覆盖了油漆:

在我做的 Table 类中

public class Table extends Container 
    ...
    this.setLayout(new GridLayout(rows+1, cols));
    for(int i=0; i<cols; i++) 
        for(int y=0; y< rows; y++) 
            TableLabel label = new TableLabel(rowData[i][y].toString()); 
            add(label);
        
    
    ...

指的是

public class TableLabel extends Label 

    public TableLabel(String labelText) 
        super(labelText);
    

    public void paint​(Graphics g) 
        super.paint(g);
        System.out.println("paint");
        Graphics2D g2 = (Graphics2D)g;
        g2.setPaint(Color.BLUE);
        g2.drawRect(getX(), getY(), getWidth(), getHeight());
    
    
    public void update​(Graphics g) 
        super.update(g);
        System.out.println("update");
        Graphics2D g2 = (Graphics2D)g;
        g2.setPaint(Color.BLUE);
        g2.drawRect(getX(), getY(), getWidth(), getHeight());
    

渲染没有改变。根据调试器的说法,无论是绘制还是更新都不会被调用。 println 也没有写入控制台。我错过了什么?该应用程序在 Java 11 下编译和运行。我知道,AWT 和版本 11 有点连线,但这是给定的设置。提前谢谢你。

【问题讨论】:

这里有一个关于 AWT 的快速教程,我正在看这个,也许会有帮助。上面的代码是否重现了问题? oracle.com/java/technologies/painting.html 我想在列和行之间有分隔线。 - 阅读GridLayout API。您可以指定组件之间的水平/垂直间距。因此面板的背景将显示为您的线条。 你的绘画代码不正确:1)不需要重写update()。所有的绘画都是在paint() 方法中完成的。 2)绘画是相对于组件完成的,而不是面板。所以 x/y 值应该是 0,你需要从宽度/高度中减去 1。 【参考方案1】:

以下代码对我有用。你能扩展你的代码以包含一个可重现的问题吗?请准确描述问题所在,以便我们确定我们都在看同一件事。

public class AwtPaint 
   
   public static void main( String[] args ) 
      SwingUtilities.invokeLater( AwtPaint::init );
   
   
   private static void init() 
      JFrame frame = new JFrame();
      
      Table myTable = new Table( 3, 3 );
      frame.add( myTable );
      
      frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
      frame.pack();
      frame.setLocationRelativeTo( null );
      frame.setVisible( true );
   
   


class Table extends Container 
    public Table( int rows, int cols ) 
    this.setLayout(new GridLayout(rows+1, cols));
    for(int i=0; i<cols; i++) 
        for(int y=0; y< rows; y++) 
            TableLabel label = new TableLabel( "Col: " + i + ", row: " + y ); 
            add(label);
        
    
    

class TableLabel extends Label 

    public TableLabel(String labelText) 
        super(labelText);
    

    public void paint​(Graphics g) 
        super.paint(g);
        System.out.println("paint");
        Graphics2D g2 = (Graphics2D)g;
        g2.setPaint(Color.BLUE);
        g2.drawRect(getX(), getY(), getWidth(), getHeight());
    
    
    public void update​(Graphics g) 
        super.update(g);
        System.out.println("update");
        Graphics2D g2 = (Graphics2D)g;
        g2.setPaint(Color.BLUE);
        g2.drawRect(getX(), getY(), getWidth(), getHeight());
    

【讨论】:

总是添加@Override。也许 - 我不确定 - drawRect(0, 0, ...。无需致电super.paint【参考方案2】:

感谢您的所有反馈。我仍然不知道到底出了什么问题,但是当我按照 Joop 的建议输入“@Override”时,Eclipse 向我显示了一个错误,说我的签名未知。我看不出文档有什么不同,但删除了代码并再次创建了方法,这次使用的是 Eclipse 的 Overwrite 功能。现在它起作用了。可能是行中某处不可打印的字符?!

顺便说一下,虽然现在调用了paint,但蓝色边框仍未渲染。我用“setColor”替换了“setPaint”,但没有成功。我也尝试了设置hgap和vgap的提议,但是由于标签的背景颜色与表格的Container相同,因此间隙是不可见的。并且在设置容器的背景时,标签会更改,但容器不会更改。这是容器的问题。在我更改表不再扩展容器而是面板后,对表背景的更改不再转发到标签。现在我可以使用 setBackground 为表格和标签设置不同的颜色,因为我在 paint 方法中编码的任何内容都没有效果。我想有一个理由想出 Swing ;-)

【讨论】:

以上是关于java.awt.Label 派生类的paint(Graphics g) 方法未调用的主要内容,如果未能解决你的问题,请参考以下文章

Qt Designer 怎么让 label居中

使用 WS_EX_COMPOSITE 时不发送 WM_PAINT

自己写的计算机

Java 的 JPanel 子类中重写父类的 paint 方法 会被自动调用,请问调用的条件或时机

类的继承与派生

C++类的继承与派生