Meet K.
Meet K.

Reputation: 499

I'm trying to draw a string in JFrame, but it won't work.. Help please

I'm trying to display a string when a button is pressed, but it does not work. I do not know what the problem is. I get no error, but that does not bother me. I'm missing something fundamental, I suppose. Please help!!

//I'm trying to draw a string in the frame when a button is pressed, but it won't work..
//Can't figure out what the problem is.


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

class AppletTwo extends JFrame implements ActionListener
{

    JFrame frameOne;
    JButton btnOne;

    AppletTwo()
    {

        frameOne = new JFrame("frameOne");
        frameOne.setSize(320,240);
        frameOne.setLayout(new FlowLayout(FlowLayout.LEFT));
        frameOne.setVisible(true);
        frameOne.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        btnOne = new JButton("Print");
        btnOne.addActionListener(this);
        frameOne.add(btnOne);
    }

    public void actionPerformed(ActionEvent ae)
    {

        if(ae.getSource() == btnOne)
        {
            repaint();
        }
    }

    public void paint(Graphics g)
    {
        g.drawString("Never Works",150,150);
    }

    public static void main(String[] args)
    {

        AppletTwo frame1 = new AppletTwo();
    }
}

Upvotes: 2

Views: 1112

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209002

" I'm missing something fundamental, I suppose. "

Yes, you are:

Main problem:

  • Your class is JFrame which is the component for which you are overriding the paint method. But you create another instance of a JFrame, which is the one you setVisible to. Keep in mind, you haven't drawn anything to this frame. So you are seeing the new instance of frame, not the class frame for which you are painting (and for which you never set visible).

Other problems:

  • You should always call super.paint[Component] after a paint[Component] override

    @Override
    public void paint(Graphics g) {
        super.paint(g);
    }
    
  • Don't paint on top level container like JFrame. Instead paint on a JPanel or JComponent and override is paintComponent method and call super.paintComponent, then add that component to the frame. See Performing Custom Painting

  • Swing apps should be run on the event dispatch thread (EDT). You can do so by wrapping your main code in a SwingUtilities.invokeLater(...). See Initial Threads

    public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                AppletTwo frame1 = new AppletTwo();
            }
        }); 
    }
    
  • Generally, you always want to set the frame visible after adding your components.

Other notes:


UPDATE

Example with all the above mentioned points.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
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;
import javax.swing.SwingUtilities;

public class SimpleDrawing {

    public SimpleDrawing() {
        final DrawingPanel panel = new DrawingPanel();

        final JTextField field = new JTextField(15);

        JButton button = new JButton("Change name");
        button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e) {
                String someString = field.getText();
                if (!someString.isEmpty()) {
                    panel.setString(someString);
                }
            }
        });

        JPanel bottomPanel = new JPanel();
        bottomPanel.add(field);
        bottomPanel.add(button);

        JFrame frame = new JFrame();
        frame.add(panel);
        frame.add(bottomPanel, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

    }

    public class DrawingPanel extends JPanel {
        private String someString = "Stackoverflow";

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawString(someString, 75, 75);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension (300, 100);
        }

        public void setString(String someString) {
            this.someString = someString;
            repaint();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                new SimpleDrawing();
            }
        });
    }  
}

Upvotes: 6

Related Questions