I'm trying to print a string that the user can enter to a textbox, to a JFrame. My problem is that the paintComponent method is never being called. Why?

PNGCreatorWindow Class:

public class PNGCreatorWindow {

private JFrame frame;
private JTextField txtText;

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                PNGCreatorWindow window = new PNGCreatorWindow();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public PNGCreatorWindow() {
    initialize();
}

private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 678, 502);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    txtText = new JTextField();
    txtText.setBounds(121, 13, 216, 22);
    frame.getContentPane().add(txtText);
    txtText.setColumns(10);

    JButton btnGenerate = new JButton("Generate");
    btnGenerate.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {

        }
    });
    btnGenerate.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent arg0) {
            GeneratePNGImage();
        }
    });
    btnGenerate.setBounds(436, 6, 183, 36);
    frame.getContentPane().add(btnGenerate);

    JPanel panel = new JPanel();
    panel.setBounds(107, 151, 338, 160);
    frame.getContentPane().add(panel);
}

protected void GeneratePNGImage() {
    PNGImage img = new PNGImage(txtText.getText());

    frame.getContentPane().add(img);        
    frame.getContentPane().validate();
    frame.getContentPane().setVisible(true);
    frame.repaint();

}
}

PNGImage Class:

public class PNGImage extends JComponent {

private String text;


public PNGImage(String text){
    this.text = text;
}

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);

    Graphics2D g2 = (Graphics2D)g;
    g2.setColor(Color.red);
    g2.drawString(this.text, 100,100);
    g2.fillRect(50, 50, 1000, 1000);
}

}
有帮助吗?

解决方案

I made a few changes to your code to get it to draw the text on the JPanel.

  1. I put the JTextField and the JButton inside of a control panel (JPanel) and set a layout manager (FlowLayout) for the control panel. You should always use a layout manager for laying out Swing components.

  2. I defined the image panel (PNGImage) as part of the laying out of the Swing components. First, you lay all of the Swing components out. Then, you change their state.

  3. I removed the mouse adapter and just used an action listener on the JButton. The action listener works with the mouse.

  4. In the PNGImage class, I added a setter, so I could pass the text to the class later, after the user typed the text in the JTextField.

  5. I added a call to setPreferredSize so that I could set the size of the drawing canvas. I removed all other sizing, and used the pack method of JFrame to make the JFrame the appropriate size to hold the Swing components.

  6. I added a null test to paintComponent, so that the text would only be drawn when there was some text to draw.

Here's the code. I put all the code in one module to make it easier to paste.

package com.ggl.testing;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class PNGCreatorWindow {

    private JFrame      frame;
    private JTextField  txtText;
    private PNGImage    imagePanel;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new PNGCreatorWindow();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public PNGCreatorWindow() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel controlPanel = new JPanel();
        controlPanel.setLayout(new FlowLayout());

        txtText = new JTextField(10);
        controlPanel.add(txtText);

        JButton btnGenerate = new JButton("Generate");
        btnGenerate.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                generatePNGImage();
            }
        });
        controlPanel.add(btnGenerate);

        imagePanel = new PNGImage();

        frame.getContentPane().add(controlPanel, BorderLayout.NORTH);
        frame.getContentPane().add(imagePanel, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

    protected void generatePNGImage() {
        imagePanel.setText(txtText.getText());
        imagePanel.repaint();
    }

    public class PNGImage extends JPanel {

        private static final long   serialVersionUID    = 602718701626241645L;

        private String              text;

        public PNGImage() {
            setPreferredSize(new Dimension(400, 300));
        }

        public void setText(String text) {
            this.text = text;
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (this.text != null) {
                Graphics2D g2 = (Graphics2D) g;
                g2.setColor(Color.red);
                g2.drawString(this.text, 100, 100);
            }
        }

    }

}

Edited to add an action listener that saves the contents of a JPanel as a .png file:

package com.ggl.crossword.controller;

import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;

import com.ggl.crossword.view.CrosswordFrame;

public class CreateImageActionListener implements ActionListener {

    private CrosswordFrame frame;

    private JPanel panel;

    public CreateImageActionListener(CrosswordFrame frame,
            JPanel panel) {
        this.frame = frame;
        this.panel = panel;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        writeImage();
    }

    public void writeImage() {
        FileFilter filter = 
                new FileNameExtensionFilter("PNG file", "png");
        JFileChooser fc = new JFileChooser();
        fc.setFileFilter(filter);
        int returnValue = fc.showSaveDialog(frame.getFrame());
        if (returnValue == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            if (!file.getAbsolutePath().endsWith(".png")) {
                file = new File(file.getAbsolutePath() + ".png");
            }
            RenderedImage image = createImage(panel);
            try {
                ImageIO.write(image, "png", file);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private BufferedImage createImage(JPanel panel) {
        int w = panel.getWidth();
        int h = panel.getHeight();
        BufferedImage bi = new BufferedImage(w, h, 
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g = bi.createGraphics();
        panel.paint(g);
        g.dispose();
        return bi;
    }

}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top