0

The function and the code for drawing lines are not responded by an ActionListener from the code inside public void actionPerformed(ActionEvent e). Why cannot I draw lines inside the ActionListener? Why cannot I call a function that draws a line.

MainClass.java

import javax.swing.SwingUtilities;

public final class MainClass {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new CreateFrame();
                System.out.println("GUI created Successfully");
            }
        }); 
    }
}

//CreateFrame.java
import javax.swing.JFrame;

public class CreateFrame {
    CreateFrame(){
        createFrame();
    }
    public void createFrame(){
        JFrame frame = new JFrame("Drawing Lines");
        frame.setSize(400, 300);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //calling a class and adding in the frame
        frame.add(new CreateDrawings()); 
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

//CreateDrawings.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class CreateDrawings extends JPanel {
    private static final long serialVersionUID = 1L;
    JButton drawButton;
    JPanel panel;

    CreateDrawings() {
        setLayout(null);
        drawButton = new JButton("Draw");
        drawButton.setBounds(150, 220, 120, 30);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        add(drawButton);
        g.setColor(Color.blue);
        g.drawLine(10, 50, 200, 50);
        drawButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                g.setColor(Color.red);           //NOT WORKING
                g.drawLine(10, 100, 200, 100);   //NOT WORKING
                drawSomething(g);                //NOT WORKING
                JOptionPane.showMessageDialog(null, "This is called though!");
            }
        });
    }// PaintComponent

    private void drawSomething(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.black);
        g.drawLine(10, 150, 200, 150);
    }
}
Andrew Lygin
  • 6,077
  • 1
  • 32
  • 37
  • 1
    if local variable is used in Annonumus class then this variable must be declare as final variable. So add to the final Graphics G to the method parameter – Nikesh Joshi Aug 10 '16 at 06:20
  • @Nikesh: Thank you for your comment. I added 'final' to both methods like paintComponent (final Graphics g) and drawSomething(final Graphics g). It still did not work. Only the JOptionPane is called! – Rajesh Rajchal Aug 11 '16 at 03:50

2 Answers2

1

Because g is a non-final variable, you can not access it inside an anonymous inner class likes above. I haven't found any official answer for this yet. However, you can reference to another question on StackOverflow.com

I guess you're using Java prior 8, therefore your source code didn't work. If you try on Java 8, it will work. The reason is Java 8 introduces the new concept about effectively final. See the definition here.

So, if you switch to Java 8, the g is an effectively final variable. Therefore, your source code will be able to compiled.

Community
  • 1
  • 1
NangSaigon
  • 1,253
  • 12
  • 14
  • Your answer provided an opportunity to look into more detail about Graphics g and the final. Thank you for providing links. There are many similar questions in stackoverflow.com. I could not find solutions to my problem though. I am using Java 8 and adding final in front of the Graphics g did not solve the problem. Any suggestions are very appreciative. – Rajesh Rajchal Aug 11 '16 at 03:54
  • I have tried your source code on my Eclipse with Java 8 and I was able to compile it. Which IDE are you using? – NangSaigon Aug 11 '16 at 10:27
  • I am using Eclipse too with Java 8. It compiles. It creates a frame and draws only **the blue line**. It does not draw the **red line** inside `ActionListener` or the **black line** called by the function inside `ActionListener`. I wonder if you see only the blue line or all three lines? – Rajesh Rajchal Aug 11 '16 at 15:47
  • Just tried your code and found some points: 1. The paintComponent is called many times in cases like: resize the frame, minimize, the button is shown, etc. And you did overwrite the paintComponent which only draws the blue line. So, when you click the button, the graphics may draw the Red and Black lines, but after that, the paintComponent is called and do it job which includes drawing the blue line. That's why the Red and Black lines can not be displayed. – NangSaigon Aug 12 '16 at 11:20
0

I appreciate supports from all programmers including my professor. I am finally able to write the code what calls a class and a function to create GUI by activating the ActionListener. I made a few changes to create 2D and make some colorful drawings on the frame. Output graphical image is here

//MainClass.java
    import javax.swing.SwingUtilities;

    public final class MainClass {
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    CreateFrame frame = new CreateFrame();
                    frame.createFrame();
                    System.out.println("GUI created Successfully");
                }
            });
        }
    }


//CreateFrame.java
    import javax.swing.JFrame;

    public class CreateFrame {
        public void createFrame() {
            JFrame frame = new JFrame("Drawing Lines");
            frame.setSize(400, 300);
            frame.setResizable(false);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            // calling a class and adding in the frame
            // creating an object is a good practice, because this way JVM will
            // guarantee its behavior
            CreateDrawings drawings = new CreateDrawings();
            drawings.createDrawings();
            frame.add(drawings);

            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    }


//CreateDrawings.java
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;

    public class CreateDrawings extends JPanel {
        private static final long serialVersionUID = 1L;

        private JButton drawButton, exitButton;
        private JLabel label;
        private DrawFromClass drawFromClass;

        public void createDrawings() {
            setLayout(null);
            drawButton = new JButton("Draw");
            exitButton = new JButton("Exit");
            label = new JLabel("Draw Random Colored Lines");
            drawButton.setBounds(50, 220, 120, 30);
            exitButton.setBounds(230, 220, 120, 30);
            label.setBounds(210, 180, 170, 30);
            add(drawButton);
            add(exitButton);
            add(label);
            drawFromClass = new DrawFromClass();
            drawButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    // repaint() creates an event that dispatch thread of the Swing
                    // to invoke paintCompnent method (invokes update and paint too)
                    repaint();
                }
            });

            exitButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });
        }

        @Override
        public void paintComponent(final Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.red);
            g.drawLine(10, 100, 200, 100);
            g.setColor(Color.blue);
            g.drawLine(10, 50, 200, 50);

            // drawing a line from a method
            drawFromMethod(g);

            // drawing a random-colored 2D lines from a class
            drawFromClass.draw(g);

        }// PaintComponent

        // drawing a black line from this method
        public void drawFromMethod(final Graphics g) {
            g.setColor(Color.black);
            g.drawLine(10, 150, 200, 150);
        }
    }

// DrawFromClass.java
    import java.awt.BasicStroke;
    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.util.Random;

    // this class draws three 5px thick random colored lines
    public class DrawFromClass {
        public void draw(final Graphics g) {
            Graphics2D gg = (Graphics2D) g;
            // draw lines with 5 pixel thick
            gg.setStroke(new BasicStroke(5));

            gg.setColor(getColor());
            gg.drawLine(270, 20, 270, 170);
            gg.setColor(getColor());
            gg.drawLine(300, 20, 300, 170);
            gg.setColor(getColor());
            gg.drawLine(330, 20, 330, 170);
        }

        // creates a random RGB color
        public Color getColor() {
            int[] colors = new int[3];
            Random random = new Random();
            colors[0] = random.nextInt(255);
            colors[1] = random.nextInt(255);
            colors[2] = random.nextInt(255);
            Color RGB = new Color(colors[0], colors[1], colors[2]);
            return RGB;
        }
    }