【问题标题】:JFrame frame calls JPanel paintComponentJFrame框架调用JPanelpaintComponent
【发布时间】:2019-02-04 21:02:11
【问题描述】:

我实际上是在学习 Java 中的图形。我无法理解这个JFrame 对象如何调用MyDrawpanel 中的paintComponent 方法,该方法扩展了JPanel

frame.repaint() 再次调用paintComponent 但如何?为什么我不能像drawPanel.repaint()一样使用MyDrawPaneldrawPanel对象;

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

public class SimpleGui3C implements ActionListener
{
    JFrame frame;

    public static void main(String[] args)
    {
        SimpleGui3C gui = new SimpleGui3C();
        gui.go();
    }

    public void go() 
    {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JButton button = new JButton("Change Colors");
        button.addActionListener(this);

        MyDrawPanel drawPanel = new MyDrawPanel();

        frame.getContentPane().add(BorderLayout.SOUTH, button);
        frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
        frame.setSize(300,300);
        frame.setVisible(true);
    }

    public void actionPerformed(ActionEvent event)
    {
        frame.repaint();
    }
}

class MyDrawPanel extends JPanel
{
    public void paintComponent(Graphics g)
    {
        g.fillRect(0,0,this.getWidth(), this.getHeight());

        int red = (int)(Math.random() * 255);
        int green = (int)(Math.random() * 255);
        int blue = (int)(Math.random() * 255);

        Color randomColor = new Color(red,green,blue);
        g.setColor(randomColor);
        g.fillOval(70,70,100,100);
    }
}

【问题讨论】:

  • 调用repaint() 告诉绘制管理器绘制组件及其拥有的所有子组件。它是绘画“链”的一部分。
  • 查看:Lesson: Performing Custom Painting:Swing 图形入门教程。 AND Painting in AWT and Swing:Swing 图形高级教程
  • 但是框架对象如何调用repaint()
  • 简短的回答是“这很复杂”,有时,您需要接受一点“黑魔法”,直到您获得足够的 API 经验。话虽如此,您应该阅读Painting in AWT and Swing 以更好地了解绘画系统的工作原理
  • "但是框架对象如何调用 repaint()" - 并且绘制请求是由框架响应 setSizesetVisible。并非所有方法都这样做,但有些方法必须触发布局/绘制通道

标签: java swing graphics awt


【解决方案1】:

为什么我不能像 drawPanel.repaint() 这样使用 MyDrawPanel 的 drawPanel 对象;

目前您的frame 变量被定义为instance 变量,因此可以在类的任何方法中引用它。

但是,您的 drawPanel 变量被定义为 local 变量,因此它只能在定义它的方法中被引用。

更改drawPanel 变量,使其定义为instance 变量,而不是local 变量。然后你可以在actionPerformed(...)方法中使用drawPanel.repaint()

在面板上调用 repaint() 会更有效,因为只会重新绘制面板,而不是框架和按钮。

另外,您使用的是旧版本的 add(...) 方法。

frame.getContentPane().add(BorderLayout.SOUTH, button);

你应该使用:

frame.getContentPane().add(button, BorderLayout.SOUTH);

框架现在会将 add(...) 请求转发到内容窗格,因此您实际上可以使用:

frame.add(button, BorderLayout.SOUTH);

为自己节省一些打字时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2012-04-11
    • 1970-01-01
    • 1970-01-01
    • 2017-11-20
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多