java - 但为什么 swing 不绘制我的组件?

标签 java swing user-interface

我有一个最简单的 java gui 的工作版本,带有一个按钮和一个圆圈,工作正常:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
//a gui element shares its events only with classes that implement Actionlistener interface
public class SimpleGui1 implements ActionListener {    
   JButton button;
   JFrame frame;
   ppanel mypanel;

public static void main (String[] args) {
    SimpleGui1 mywindow = new SimpleGui1();
    mywindow.renderWindow();
}  
public void renderWindow(){
    frame = new JFrame();
    button = new JButton("click me");
    mypanel = new ppanel();

    //register my interest to catch button events
    button.addActionListener(this);

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

    frame.setSize(300,300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
}   
//button will call this method when clicked (its the callback)
public void actionPerformed(ActionEvent event)
{       
    frame.repaint();
    button.setText("Clicked!!");
}
}
//i need this to override paintComponent
public class ppanel extends JPanel  {   
    //draw something silly
    public void paintComponent(Graphics g) {
    //super.paintComponent(g);
    Graphics2D g2d = (Graphics2D) g;
    int red = (int) (Math.random() * 255);
    int green = (int) (Math.random() * 255);
    int blue = (int) (Math.random() * 255);

    Color startColor = new Color(red, green, blue);
    red = (int) (Math.random() * 255);
    green = (int) (Math.random() * 255);
    blue = (int) (Math.random() * 255);
    Color endColor = new Color(red, green, blue);
    GradientPaint gradient =  new GradientPaint(70,70,startColor, 150,150, endColor);
    g2d.setPaint(gradient);
    g2d.fillOval(70,70,100,100);
}
}

然后,只是为了好玩,我尝试将这两个类聚合为一个,如下所示:

public class SimpleGui1 extends JPanel implements ActionListener {    
private JButton button;
private JFrame frame;
private JPanel mypanel;


public static void main (String[] args) {
    SimpleGui1 mywindow = new SimpleGui1();
    mywindow.renderWindow();
}

public void renderWindow(){
    frame = new JFrame();
    button = new JButton("click me");
    mypanel = new JPanel();

    frame.setSize(300,300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

    // register my interest to catch button events
    button.addActionListener(this);

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

    //without this i see only the button
    //frame.add(this);

}
//button will call this method when clicked (its the callback)
public void actionPerformed(ActionEvent event)
{
    frame.repaint();
    button.setText("Clicked!!");
}

public void paintComponent(Graphics g) {
   //super.paintComponent(g);

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

    Color startColor = new Color(red, green, blue);
    red = (int) (Math.random() * 255);
    green = (int) (Math.random() * 255);
    blue = (int) (Math.random() * 255);
    Color endColor = new Color(red, green, blue);
    GradientPaint gradient =  new GradientPaint(70,70,startColor, 150,150, endColor);
    g2d.setPaint(gradient);
    g2d.fillOval(70,70,100,100);
}
}

新类编译成功,但在运行时它只绘制按钮。由于某种原因,paintComponent 未被调用,正确工作的唯一方法是在 renderwindow() 中添加以下内容:

 frame.add(this);

我的问题是为什么这种行为...为什么我必须显式添加 对象到我的框架以使该版本正常工作?

几乎在所有地方都尝试过 repaint() 和 validate() 。变化不大
我也知道我不应该从 EDT 中提取东西,并且带有内部类的版本也可以缓解问题

最佳答案

事实上,您必须显式地将 this 对象添加到内容 Pane 中。我编译并测试了以下内容:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
//a gui element shares its events only with classes that implement Actionlistener interface
public class SimpleGui1 extends JPanel implements ActionListener {    
       JButton button;
       JFrame frame;
       ppanel mypanel;

    public void paintComponent(Graphics g) 
    {
        //super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        int red = (int) (Math.random() * 255);
        int green = (int) (Math.random() * 255);
        int blue = (int) (Math.random() * 255);

        Color startColor = new Color(red, green, blue);
        red = (int) (Math.random() * 255);
        green = (int) (Math.random() * 255);
        blue = (int) (Math.random() * 255);
        Color endColor = new Color(red, green, blue);
        GradientPaint gradient =  new GradientPaint(70,70,startColor, 150,150, endColor);
        g2d.setPaint(gradient);
        g2d.fillOval(70,70,100,100);
    }

    public static void main (String[] args) {
        SimpleGui1 mywindow = new SimpleGui1();
        mywindow.renderWindow();
    }  
    public void renderWindow(){
        frame = new JFrame();
        button = new JButton("click me");

        //register my interest to catch button events
        button.addActionListener(this);

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

        frame.setSize(300,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }   
    //button will call this method when clicked (its the callback)
    public void actionPerformed(ActionEvent event)
    {       
        frame.repaint();
        button.setText("Clicked!!");
    }
}

您需要显式添加组件才能进行绘制,组件是对象本身并不重要!

关于java - 但为什么 swing 不绘制我的组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32260145/

上一篇:sql - 合并 NULL 的表

下一篇:SSIS 和 SQLite

相关文章:

swing - 在 Swing 中强制立即布局和绘制

java - 无法使用自定义渲染器

python - 文件选择器打开时无需单击子窗口上的按钮

java - 如何使用java itext保存pdf

java - Eclipse:无法从 Java 角度终止进程

java - @RunWith 未在 JUnit5 中编译

java - 如何在 Eclipse 内使用 JDK/JRE 和第 3 方库的 Eclipse 外部空注释 (EEA)?

java - 如何使用外部类实现 ActionListener?

java - 在 OSGi 框架中运行基于 SWT 的 GUI

c++ - Qt 工具窗口可在 Mac 上调整大小