0

I am attempting to draw multiple shapes in the contentPane of a JInternalFrame. When a button is clicked, the program should determine which checkboxes are selected, and add the appropriate shapes. If multiple shapes are selected, it should add all of them.

Currently the program can draw any of the shapes. The problem is that on click, only one shape is being drawn when I have multiple check boxes selected, and I can't figure out why. (Example: Yellow and blue JCheckboxes are selected, it only draws the yellow shape, when it should draw both) Please help me get the program to draw more than one shape on click!

Here is some code:

ActionListener that is to handle the adding of shapes:

class addListener implements ActionListener
{
    public void actionPerformed(ActionEvent e)
    {
        if (redBox.isSelected())
        {
            x = createRNG(RNG_MAX,RNG_MIN);//so the shapes starting location is random
            y = createRNG(RNG_MAX,RNG_MIN);
            rShape = new redShape(x,y);
            contentPane.add(rShape);//,BorderLayout.CENTER);
        }
        if (blueBox.isSelected())
        {
            x = createRNG(RNG_MAX,RNG_MIN);
            y = createRNG(RNG_MAX,RNG_MIN);
            bShape = new bShape(x,y);
            //internalFrame.getContentPane().add(bShape);
            contentPane.add(bShape);//BorderLayout.CENTER);
        }
        if (yellowBox.isSelected())
        {
            x = createRNG(RNG_MAX,RNG_MIN);
            y = createRNG(RNG_MAX,RNG_MIN);
            yShape = new yShape(x,y);
            //internalFrame.getContentPane().add(yShape);
            contentPane.add(yShape);//,BorderLayout.CENTER);

        }
        internalFrame.repaint();
        internalFrame.revalidate();
    }
}

The code of one of the shape classes. The code of these classes are all basically the same, just different shapes being drawn.

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

public class redShape extends coloredShapes
{
private static final int RECTANGLE_WIDTH = 80;
private static final int RECTANGLE_HEIGHT = 20;

private int xLeft;
private int yTop;

public redShape(int x, int y)
{
    xLeft = x;
    yTop = y;
}

public void paintComponent(Graphics g)
{
    //draws 1 large rectangle
    g.setColor(Color.red);
    g.fillRect(xLeft,yTop,RECTANGLE_WIDTH,RECTANGLE_HEIGHT);

    //Divides the rectangle into parts
    g.setColor(Color.black);
    g.drawLine(xLeft, yTop,xLeft+80,yTop);
    g.drawLine(xLeft,yTop,xLeft,yTop+20);
    g.drawLine(xLeft,yTop+20,xLeft+80,yTop+20);
    g.drawLine(xLeft+80,yTop+20,xLeft+80,yTop);
    g.drawLine(xLeft+20,yTop,xLeft+20,yTop+20);
    g.drawLine(xLeft+40,yTop,xLeft+40,yTop+20);
    g.drawLine(xLeft+60,yTop,xLeft+60,yTop+20);
}

public void moveComponentBy(int dx, int dy)
{
    if (yTop < 450)
    {
        xLeft += dx;
        yTop += dy;
        if (xLeft < 0)
        {
            xLeft = 0;
        }
        if (xLeft > 500)
        {
            xLeft = 500;
        }
        repaint();
    }
}

public int getYTop()
{
    return yTop;
}

public int getXLeft()
{
    return xLeft;
}
}

This is the code I thought would be relevant, if any further code is needed to determine the issue, please ask and I will provide it!

EDIT: coloredShapes abstract class, as requested.

import java.util.*;
import javax.swing.*;
abstract public class coloredShapes extends JComponent
{     
private static final int RECTANGLE_WIDTH = 10;
private static final int RECTANGLE_HEIGHT = 10;

private int xLeft;
private int yTop;

public coloredShapes()
{
    xLeft = 0;
    yTop = 0;
}

public abstract void moveComponentBy(int dx, int dy);

public abstract int getYTop();

public abstract int getXLeft();
}
Justiciar
  • 356
  • 1
  • 3
  • 20
  • If the shape classes are the same, the problem is most likly in the booleanvalues (the `#Selected()` calls). If you are not sure what is happening, maybe its worth debugging your code and see where things go wrong. – n247s Oct 14 '17 at 04:08
  • When paintComponent the 0,0 will be the position from whitin the current JComponent, with your logic, you may create a custom JInternalFrame that accepts the shapes and draw then on position – Marcos Vasconcelos Oct 14 '17 at 04:28
  • @Justiciar Can you show your ColoredShapes class? Is it a component? Where is your paintComponent method for your main panel? – user3437460 Oct 14 '17 at 05:03
  • 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) Please learn common Java nomenclature (naming conventions - e.g. `EachWordUpperCaseClass`, `firstWordLowerCaseMethod()`, `firstWordLowerCaseAttribute` unless it is an `UPPER_CASE_CONSTANT`) and use it consistently. 3) If my guesses are correct, the code not shown is using a `JComponent` as the parent of the `coloredShapes` class, and this is likely not the best way to create more than one colored shape. .. – Andrew Thompson Oct 14 '17 at 05:54
  • .. Better to use a single custom painted component that has a list of shapes to be drawn, then in the paint method, iterate the list and paint each in turn. – Andrew Thompson Oct 14 '17 at 05:54
  • @user3437460 coloredShapes is actually just an abstract class that does nothing by itself. I've posted it's code as an edit in the original post – Justiciar Oct 14 '17 at 14:03
  • @Justiciar And so, ColoredShapes indeed extends to JComponent. Unfortunately, this is not how you should do custom paintings. If you were to draw a JComponent freely on anywhere on the screen, you need to set the layout to null. But the best way is not to do that, but keep a list of Shapes and draw the shapes directly on the panel. – user3437460 Oct 14 '17 at 14:32
  • @user3437460 I am not very experienced with custom painting. Might you have a link to a tutorial that goes over what you are recommending? edit: thanks camickr . I'm looking over that now – Justiciar Oct 14 '17 at 14:37
  • See [Custom Painting Approaches](https://tips4java.wordpress.com/2009/05/08/custom-painting-approaches/) for the two common ways to do incremental painting. The example uses a "ColoredRectangle" to draw rectangles. You can easily change this class to hold a `Polygon` and then just paint the Polygon using the drawShape(...) method of the Graphics2D class. – camickr Oct 14 '17 at 14:38

1 Answers1

1

I assume that you use Borderlayout for your JInternalFrame.
From what I see I assume you add all shapes to the JInternalFrame by: contentPane.add(bShape); which adds bShape to Borderlayout center.

Borderlayout center can hold one component. Adding a second one overwrites the first.
For testing you can setLayout(null); to the JInternalFrame (and set bounds of the components added). For a more robust solution see here.
Also make sure that the background you paint is transparent. See here for more details.

c0der
  • 18,467
  • 6
  • 33
  • 65
  • The JInternalFrame is actually using the default layout, which I assume to be flow. I did set the contentPane to borderLayout however. I am looking into StackLayout now, I actually hadn't heard of that before. – Justiciar Oct 14 '17 at 04:18
  • Layout shouldn't affect custom paintings. If your shape is not a component and you are just drawing it, it should not be affected. It is more likely how you draw the shapes in paintComponent. – user3437460 Oct 14 '17 at 04:48
  • It may have nothing to do with the painting but with the attempt to add multiple components. – c0der Oct 14 '17 at 05:06
  • @Justiciar Actually, the default layout for all windows is `BorderLayout`, including `JInternalFrame` – MadProgrammer Oct 14 '17 at 06:07
  • @c0der I'm having trouble trying to implement the StackLayout you mentioned. Are you sure StackLayout can be used in Swing? From what I can see it is for SWT, which I am not using(and have never used before) – Justiciar Oct 14 '17 at 14:23
  • Sorry, you are right. Got confused with JavaFx. I'll amend my answer – c0der Oct 14 '17 at 16:10