Jebathon
Jebathon

Reputation: 4581

Creating and overriding a shape to fit into JPanel?

In this program a polygon is created to show up into a JPanel tab.

In-order to make it show I had to over-ride the shape and create a setter method for it. Unfortunately it is not showing and the program is not running either.

The error:

Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
  at SelectShape component1 = new SelectShape(x, y, vert); in method Page1.

The only way it would work is by making a frame and removing the JTab and assigning the shape onto the frame but that is not what I want to make. I want to make a program that can distribute shapes to * different tabs* using one graphics method.

Here is the code:

import java.awt.*;
import java.io.IOException;
import javax.swing.*;


/* This program create a graphics component that draws a polygon 
 */
public class SelectShape extends JFrame 
{
    private JTabbedPane tabbedPane;
    private JPanel panel1; 

    // //////////////////////////

    static int[] x = { 20, 40, 50, 65, 80, 95 }; // Co-ords for a polygon
    static int[] y = { 60, 105, 105, 110, 95, 95 };
    static int vert = 6;

    public SelectShape() throws IOException // Builds GUI
    {
        setTitle("Program");
        setSize(900, 600);
        setBackground(Color.gray);

        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BorderLayout());
        getContentPane().add(topPanel);

        // Create the tab pages
        createPage1();

        // Create a tabbed pane
        tabbedPane = new JTabbedPane();
        tabbedPane.addTab("Shape Panel", panel1);
    }

    public void createPage1() throws IOException // Creates JPanel
    {
        panel1 = new JPanel();
        panel1.setLayout(null);

        SelectShape component1 = new SelectShape(x, y, vert); //error
        SelectShape component2 = new SelectShape(x, y, vert); //over-rides shape

        component1.setBounds(290, 70, 120, 40);
        component2.setBounds(290, 70, 120, 40);

        panel1.add(component1); // is not displayed!
        panel1.add(component2); // component2 overwrites component1!!!
        panel1.setVisible(true);

    }

    // overrides javax.swing.JComponent.paintComponent
    public void paintComponent(Graphics g) {
        // Recover Graphics2D
        Graphics2D g2 = (Graphics2D) g;

        // Construct a polygon then draw it
        Polygon polygon = new Polygon(x, y, vert); 
        g2.draw(polygon);
        g2.fill(polygon);
    }

    public SelectShape(int[] x, int y[], int vert) { // setter method
        this.x = x;
        this.y = y;
        this.vert = vert;
    }

    public static void main(String[] args) throws IOException {

        SelectShape mainFrame = new SelectShape(); //Frame
        mainFrame.setVisible(true);

    }
}

Upvotes: 2

Views: 1000

Answers (1)

Guillaume Polet
Guillaume Polet

Reputation: 47607

I think you are mixing many concepts together in your code which eventually leads to ununderstandable code.

  • JFrame does not extends JComponent and does not have a paintComponent method. Consider using the @Override annotation on methods that override another. This will allow you to easily mistakes like this.
  • No need to extend JFrame anyway and never override the paint() method of a Top-level container (JDialog, JFrame, ...)
  • Always invoke the super method of paintXXX methods
  • public SelectShape(int[] x, int y[], int vert) { // setter method is not a setter method. It is a constructor that takes 3 arguments and assign them. In all cases, this does absolutely nothing in your case because you made those variables static. Avoid the use of static unless if you describe constants, in which case it should be also followed by the final keyword.
  • Start the UI, and perform all modifications to the UI, on the Event Dispatching Thread (EDT). This can easily be done by using SwingUtilities.invokeLater().
  • The error you are seeing: Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container is thrown because you are trying to add a JFrame to a JComponent which is forbidden. JFrame cannot be added to anything. If you want to do that, you need to use JDesktopPane and add JInternalFrame (but that is another story).

I am not too sure as to what you are trying to achieve, but here is a working code derived from yours which works much better:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;

/* This program create a graphics component that draws a polygon 
 */
public class SelectShape extends JPanel {

    // Constants
    private static final int[] x = { 20, 40, 50, 65, 80, 95 }; // Co-ords for a polygon
    private static final int[] y = { 60, 105, 105, 110, 95, 95 };

    private static final Polygon POLYGON = new Polygon(x, y, Math.min(x.length, y.length));
    private static final Ellipse2D CIRCLE = new Ellipse2D.Double(100, 40, 45, 45);

    // Class variables
    private final Shape shape;
    private Dimension preferredSize;

    public SelectShape(Shape shape) {
        this.shape = shape;
        Rectangle bounds = shape.getBounds();
        this.preferredSize = new Dimension(bounds.x + bounds.width, bounds.y + bounds.height);
    }

    @Override
    public Dimension getPreferredSize() {
        return preferredSize;
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g.setColor(Color.BLUE);
        g2.draw(shape);
        g2.fill(shape);
    }

    public static void main(String[] args) throws IOException {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame mainFrame = new JFrame("Program");
                mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                SelectShape polygon = new SelectShape(POLYGON);
                SelectShape circle = new SelectShape(CIRCLE);
                // Create a tabbed pane
                JTabbedPane tabbedPane = new JTabbedPane();
                tabbedPane.addTab("Polygon", polygon);
                tabbedPane.addTab("Circle", circle);
                mainFrame.add(tabbedPane);
                mainFrame.pack();
                mainFrame.setVisible(true);
            }
        });

    }
}

Upvotes: 3

Related Questions