I've gotten my code to work for the most part except for one last thing. When the number of lines drawn > 20, the lines aren't being drawn to take up the full amount of panel
** Look at the bottom right side of my screenshot. The lines go part way down the full height of the panel. I need it to go the full length of the height down. **
Here's my code for DrawPanelTest
// Creating JPanel to display DrawPanel
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class DrawPanelTest
{
public static void main(String[] args)
{
int nValue = 0; // declare variable to store user input. Default value 0.
Boolean flag = true; // initalize flag to true for argument value of while-loop
// while-loop to prompt user input
while (flag) {
// prompt user for the value of N
nValue = Integer.parseInt(JOptionPane.showInputDialog("Enter number of lines between 2 and 100."));
// user input validation. Valid input is nValue [2, 100]
if (nValue < 2 || nValue > 100) {
nValue = Integer.parseInt(JOptionPane.showInputDialog("Enter number of lines between 2 and 100."));
} else {
flag = false; // if user input is correct, while-loop will end
} // end if-else
} // end while-loop
// displays the value of N to make sure it really is correct; This works
// String message = String.format("The value of n is: %d ", nValue);
// JOptionPane.showMessageDialog(null, message);
// create a panel that contains our drawing
DrawPanel drawPanel = new DrawPanel(nValue);
// create a new frame to hold the panel
JFrame application = new JFrame();
// set the frame to exit when closed
application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
application.add(drawPanel); // add panel to the frame
application.setSize(600, 600); // set the size of the frame
application.setVisible(true); // make the frame visible
}
} // end class DrawPanelTest
Here's my code DrawPanel
// Using drawLine() to connect the corners of a panel
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawPanel extends JPanel
{
int numLines;
// constructor initializes DrawPanel and initializes
// numLines with the argument value of n
public DrawPanel(int n)
{
numLines = n;
}
// draws a X from the corners of the panel
public void paintComponent( Graphics g)
{
// call paintComponent to ensure the panel displays correctly
super.paintComponent(g);
int width = getWidth(); // total width
int height = getHeight(); // total height
int x1 = 0; // starting x-coordinate
int y1 = height / 2; // starting y-coordinate
int x2 = width; // initial value for end x-coordinate
int spaceValue = 0; // represents the space between the lines
int stepValue = height/numLines; // represents the increment value starting from top right corner
for (int i = 0; i <= numLines; i++) {
if (numLines == 2) {
g.drawLine(x1, y1, x2, 0);
g.drawLine(x1, y1, x2, height);
break;
} // end numLines == 2
else if (numLines >= 3) {
g.drawLine(x1, y1, x2, spaceValue);
spaceValue += stepValue;
} // end else if
} // end for-loop
} // end paintComponent
} // end class DrawPanel
I think my problem lies in DrawPanel line 41. I don't think I'm calculating the spaces between the lines correctly so that they end up taking the entire height of the panel.
Thanks in advance for your help.
Your calculation of the "stepValue" has two problems:
the stepValue is to small, so the last line will never appear at the bottom
the stepValue is truncated because of integer math so each addition of the truncated value to the "spaceValue" will yield a slightly less accurate value.
Lets say you have a panel with a height of 600 and the number of lines is 3.
Your calculation is:
int stepValue = 600 / 3 = 200
which I would suggest is wrong as you would draw 3 lines with a "spaceValue" of 0, 200, 400, so the last line (at 600) would never be drawn.
In reality I think the calculation should be:
double stepValue = (double)height / (numLine - 1);
which gives:
double stepValue = 600 / (3 - 1) = 300.
which will give lines with a "spaceValue" of 0, 300, 600 which would be a line at the top, middle and bottom.
So your painting loop simply becomes:
for (int i = 0; i < numLines; i++)
{
g.drawLine(x1, y1, x2, spaceValue);
spaceValue += stepValue;
}
I think (one of) the issue you're having is a "integer division" issue.
int stepValue = height / numLines;
is truncating the result. For example, if the height is 400 and the number of lines is 6 the stepValue will be 66 instead of 67 (which would allow 66.6666 to be rounded up)
Now, you could "round" the value up yourself, but I'd prefer to make use of the available APIs to do these things for me.
Line2D.Double supports double precision parameters, which makes it perfect for this job
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (lineCount > 1) {
double gap = getHeight() / (double)(lineCount - 1);
for (int i = 0; i < lineCount; i++) {
Line2D line = new Line2D.Double(0, getHeight() / 2, getWidth(), i * gap);
g2d.draw(line);
}
} else {
g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
}
g2d.dispose();
}
Runnable example...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new EmptyBorder(32, 32, 32, 32));
frame.setContentPane(contentPane);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int lineCount = 1;
public TestPane() {
setBorder(new LineBorder(Color.RED));
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
lineCount++;
repaint();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
FontMetrics fm = g2d.getFontMetrics();
g2d.drawString(Integer.toString(lineCount), 10, fm.getAscent());
if (lineCount > 1) {
double gap = getHeight() / (double) (lineCount - 1);
for (int i = 0; i < lineCount; i++) {
Line2D line = new Line2D.Double(0, getHeight() / 2, getWidth(), i * gap);
g2d.draw(line);
}
} else {
g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
}
g2d.dispose();
}
}
}
In the for loop, change
for (int i = 0; i < numLines; i++) {
to
for (int i = 0; i <= numLines; i++) {
to iterate the full height of the component. The i must equal numLines to reach unity.
Related
I am having trouble getting my histogram to fill correctly.
I was given a large data file full of doubles that represented GPAs, about 5500 of them. I created a method to calculate the count, mean, and standard deviation of the data, however my last problem is to graph the data.
I am to make a histogram for each of the possible grades (12 of them) and graph them about the total of each grade.
I think I have coded the total for each grade correctly, but when it comes to actually drawing the histogram I cannot figure out the 4 arguments needed for fillRect.
I've been playing around with different variables, but nothing seems to get me close.
Any help is appreciated.
private static int[] gradeCounts(double[] stats) throws Exception{
double stdv = 0;
double sum = 0;
double sum2 = 0;
double variance = 0;
Scanner fsc = new Scanner(new File("introProgGrades.txt"));
while (!fsc.hasNextDouble())
fsc.nextLine();
int[] binCounts = new int[NUM_OF_GRADE_CATEGORIES];
double x = 0;
while (fsc.hasNextDouble()){
stats[2]++;
x = fsc.nextDouble();
sum += x;
sum2 += x * x;
if (x == 0.0)
binCounts[0]++;
else if (x == 0.6666667)
binCounts[1]++;
else if (x == 1.0)
binCounts[2]++;
else if (x == 1.3333333)
binCounts[3]++;
else if (x == 1.6666667)
binCounts[4]++;
else if (x == 2.0)
binCounts[5]++;
else if (x == 2.3333333)
binCounts[6]++;
else if (x == 2.6666667)
binCounts[7]++;
else if (x == 3.0)
binCounts[8]++;
else if (x == 3.3333333)
binCounts[9]++;
else if (x == 3.6666667)
binCounts[10]++;
else
binCounts[11]++;
}
stats[0] = sum/stats[2];
variance = (stats[2] * sum2 - sum * sum) / (stats[2]*(stats[2]-1));
stdv = Math.sqrt(variance);
stats[1] = stdv;
return binCounts;
}
What I am having trouble with:
private static void plotHistogram(int[] binCounts){
int max = Arrays.stream(binCounts).max().getAsInt();
DrawingPanel panel = new DrawingPanel (800,800);
Graphics2D g = panel.getGraphics();
g.fillRect(0, 0, 800/binCounts.length,max);
}
I think I have to iterate through the data with a for loop, but it's the parameters of fillRect that I am clueless on.
but when it comes to actually drawing the histogram I cannot figure out the 4 arguments needed for fillRect.
The JavaDocs are quite explicit in the properties and their meanings, it's just a box, with a position (x/y) and size (width/height)
public abstract void fillRect​(int x,
int y,
int width,
int height)
Fills the specified rectangle. The left and right edges of the rectangle are at x and x +
width - 1. The top and bottom edges are at y and y + height - 1. The
resulting rectangle covers an area width pixels wide by height pixels
tall. The rectangle is filled using the graphics context's current
color. Parameters: x - the x coordinate of the rectangle to be filled.
y - the y coordinate of the rectangle to be filled. width - the width
of the rectangle to be filled. height - the height of the rectangle to
be filled.
I've been playing around with different variables, but nothing seems to get me close.
So, two things come to mind, the first comes from the JavaDocs above...
The rectangle is filled using the graphics context's current
color
This is something that's easy to forget
The second is it seems that you misunderstand how painting works in Swing.
Painting in Swing has a very specific and well documented workflow. The first thing you should do is go read Performing Custom Painting and Painting in AWT and Swing to get a better understanding of how painting works and how you should work with it.
There is never a good reason to call JComponent#getGraphics, apart from been able to return null, this is just a snapshot of the last paint cycle and will be wiped clean on the next paint pass (which may occur at any time for any number of reasons).
Instead, you will need a custom component and override it's paintComponent method instead.
You should then have a read through the 2D Graphics trail to get a better understanding of how the API works and what features/functionality it can provide.
For example....
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.util.Arrays;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
Random rnd = new Random();
int[] binCounts = new int[10];
for (int index = 0; index < binCounts.length; index++) {
binCounts[index] = rnd.nextInt(100);
}
JFrame frame = new JFrame();
frame.add(new DrawingPanel(binCounts));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawingPanel extends JPanel {
private int[] binCounts;
private int max;
public DrawingPanel(int[] binCounts) {
this.binCounts = binCounts;
max = Arrays.stream(binCounts).max().getAsInt();
System.out.println(max);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 800);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int barWidth = 800 / binCounts.length;
for (int i = 0; i < binCounts.length; i++) {
int barHeight = (int)((binCounts[i] / (double)max) * getHeight());
// I personally would cache this until the state of the component
// changes, but for brevity
Rectangle rect = new Rectangle(i * barWidth, getHeight() - barHeight, barWidth, barHeight);
g2d.setColor(Color.BLUE);
g2d.fill(rect);
g2d.setColor(Color.BLACK);
g2d.draw(rect);
}
g2d.dispose();
}
}
}
I have some code here, and it graphs exponentially but, it graphs the wrong way. negative exponential growth. Here is my code, I'm trying to flip it up. I'll be working on it, but if you have an answer please tell me.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Graphics extends JPanel{
public static void main(String[] args) {
JFrame f =new JFrame ("Function");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Graphics g = new Graphics();
f.add(g);
f.setSize(700, 700);
f.setVisible(true);
}
public void paintComponent (java.awt.Graphics g) {
super.paintComponent(g);
int i = this.getWidth()-this.getWidth() + 5;
int xoffset = this.getWidth()/2;
int yoffset = this.getHeight()/2;
for (int x = 0 ; x < 20 ; x++){
g.setColor(Color.BLACK);
this.setBackground(Color.WHITE);
int p = x*x;
g.fillRect(i+xoffset,10+yoffset,5,p);
i = i + 10;
}
}
}
Does anyone know how to fix this?
Change the x/y position at where the rectangle starts to draw from (it always draws right/down)
So instead of
g.fillRect(i+xoffset,10+yoffset,5,p);
you could have...
g.fillRect(i + xoffset, 10 + yoffset - p, 5, p);
I've got no idea what your intentions are for int i = this.getWidth()-this.getWidth() + 5;, but clearly makes no sense (width - width == 0?)
I am trying to make a program that generates 25 random ovals then draw a ball and make it bounce, I got it somewhat done, I generated the ovals and I got the ball to move but when I added the thread it kept repeating the draw oval loop, I get somewhat why this is happening but I have no idea how to fix it.
Basically my program should:
draw 25 random sized ovals on random locations within the border - completed
draw a ball and make it move - completed
make the ball bounce - not done but I know how to do it
but it keeps repeating step one.
this is my code that I have written, oh and I have to use applets right now its part of the course please don't suggest I use swing or something else:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
public class As4B extends Applet implements Runnable
{
public int x, y;
public int width = 854;
public int height = 480;
public int border = 20;
public Image offscreen;
public Graphics d;
public void init()
{
setSize(width,height);
Thread th = new Thread(this);
th.start();
offscreen = createImage(width,height);
d = offscreen.getGraphics();
}
public void run()
{
x = 100;
y = 100;
while(true)
{
x ++;
y ++;
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void paint(Graphics gfx)
{
d.setColor(java.awt.Color.black);
d.fillRect(0, 0, width, height);
d.setColor(java.awt.Color.green);
d.fillRect(0 + border, 0 + border, (width - (border * 2)), (height - (border* 2)));
genOval(25, d);
d.setColor(Color.gray);
d.fillOval(x, y, 50, 50);
gfx.drawImage(offscreen, 0, 0, this);
}
public int random(int low, int high)
{
int answer =(int)((Math.random()*(high-low))+ low);
return answer;
}
public void genOval(int amount, Graphics f)
{
int ranWidth, ranHeight, ranX, ranY, red, blue, green;
int i = 0;
while(i < 25)
{
green = random(0,255);
blue = random(0,255);
red = random(0,255);
f.setColor(new Color(red,green,blue));
ranWidth = random(30,400);
ranHeight = random(30,200);
ranX = random(0 + border, ((width - border)- (ranWidth)));
ranY = random(0 + border , ((height - border)- (ranHeight)));
f.fillOval(ranX, ranY, ranWidth, ranHeight);
i++;
}
}
public void update(Graphics gfx) {
paint(gfx);
}
}
Your genOval() method has no persistent backing. Every time repaint() is called (by your thread), the paint() method is called, and this generates new locations for the random ovals. You need to create a persistent source for that information, like so:
List<Rectangle> rectangles = new ArrayList<Rectangle>();
List<Color> colors = new ArrayList<Color>();
public void init() {
...
for (int i = 0; i < 25; i++) {
int green = random(0,255);
int blue = random(0,255);
int red = random(0,255);
colors.add(new Color(red,green,blue));
ranWidth = random(30,400);
ranHeight = random(30,200);
ranX = random(0 + border, ((width - border)- (ranWidth)));
ranY = random(0 + border , ((height - border)- (ranHeight)));
rectangles.add(new Rectangle(ranX, ranY, ranWidth, ranHeight));
}
}
public void genOval(Graphics g) {
for (int i = 0; i < 25; i++) {
Color color = colors.get(i);
Rectangle rectangle = rectangle.get(i);
// Draw using color & rectangle
}
}
Trying to figure out the best way to do this (And without crossing any specifics DO NOTs that I don't know about).
I'm working on visually displaying a graph (Various nodes, with edges connecting them) with circles and lines to represent such. Each node will be added during runtime and I can't hardcode this. From what I understand, all painting needs to be done in the paint(Graphics g) method - which isn't that helpful, since I can't be change the parameters and it seems this is only called during the initial creation?
Right now I was thinking about having it call various other methods, passing the Graphics object, and depending on other variables - I'll decide whether that's what I even want to call (Since the paint() method is the only one I can call).
Am I going about this completely wrong? Never bothered with this before.
To give you a better idea of what I want to end up with: I want to be able to pass the coordinates of the shape I want to add for the node, and then add it to whatever I have on the graph so far. And then same with the edges, I want to be able to pass the beginning and end point of the line to repaint on top of whatever is existing at that time.
Not exactly what I want right now - but you'll get the idea from what I patched together so far:
import java.awt.*;
import javax.swing.*;
public class MyCanvas extends Canvas
{
public MyCanvas()
{
}
public void paint(Graphics graphics)
{
// Keep this until I figured out if it's painted on load or not.
graphics.drawLine(10, 20, 350, 380);
}
public static void main(String[] args)
{
MyCanvas canvas = new MyCanvas();
JFrame frame = new JFrame();
int vertexes = 0;
// Change this next part later to be dynamic.
vertexes = 10;
int canvasSize = vertexes * vertexes;
frame.setSize(canvasSize, canvasSize);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(canvas);
frame.setVisible(true);
}
public void drawNode(int x, int y, Graphics g)
{
// Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
int xLoc = (x*10) - 5;
int yLoc = (y*10) - 5;
g.setColor(Color.white);
g.fillOval(xLoc, yLoc, 8, 8);
g.drawOval(xLoc, yLoc, 8, 8);
}
public void drawArc(int x, int y, int xx, int yy, Graphics g)
{
int xLoc = (x*10) - 5;
int yLoc = (y*10) - 5;
int xxLoc = (xx*10) - 5;
int yyLoc = (yy*10) - 5;
g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
}
}
Edit: (Response for Andrew)
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
public class MyCanvas extends JPanel
{
public MyCanvas() {
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
public static void main(String[] args)
{
int vertexes = 0;
// Change this next part later to be dynamic.
vertexes = 10;
int canvasSize = vertexes * vertexes;
JFrame frame = new JFrame();
JLabel label = new JLabel();
BufferedImage bImage = new BufferedImage(canvasSize, canvasSize, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = bImage.createGraphics();
g2d.drawLine(50, 50, 300, 300);
ImageIcon iIcon = new ImageIcon(bImage);
label.setIcon(iIcon);
frame.add(label);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
g2d = drawNode(1,1,g2d);
label.repaint();
}
public static Graphics2D drawNode(int x, int y,Graphics2D g2d)
{
// Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
int xLoc = (x*10) - 5;
int yLoc = (y*10) - 5;
g2d.setColor(Color.white);
g2d.fillOval(xLoc, yLoc, 8, 8);
g2d.drawOval(xLoc, yLoc, 8, 8);
return g2d;
}
public static void drawArc(int x, int y, int xx, int yy)
{
int xLoc = (x*10) - 5;
int yLoc = (y*10) - 5;
int xxLoc = (xx*10) - 5;
int yyLoc = (yy*10) - 5;
// g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
}
}
There are various strategies you might pursue for this.
If the objects are never removed from the drawing once done, use a BufferedImage, put it in a (ImageIcon in a) JLabel. When it comes time to update:
Get the graphics instance of the image and draw the new element.
Dispose of the graphics object.
Call repaint() on the label.
Keep a list of the drawn elements. In the paint method, paint them all. When a new element is added, call repaint() on the rendering component.
Here is an example of the 1st technique:
import java.awt.image.BufferedImage;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class MyCanvas
{
JLabel view;
BufferedImage surface;
Random random = new Random();
public MyCanvas()
{
surface = new BufferedImage(600,400,BufferedImage.TYPE_INT_RGB);
view = new JLabel(new ImageIcon(surface));
Graphics g = surface.getGraphics();
g.setColor(Color.ORANGE);
g.fillRect(0,0,600,400);
g.setColor(Color.BLACK);
// Keep this until I figured out if it's painted on load or not.
g.drawLine(10, 20, 350, 380);
g.dispose();
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
addNewElement();
}
};
Timer timer = new Timer(200, listener);
timer.start();
}
public void addNewElement() {
boolean drawArc = random.nextBoolean();
int x = random.nextInt(60);
int y = random.nextInt(40);
Graphics g = surface.getGraphics();
if (drawArc) {
g.setColor(Color.BLUE);
int xx = random.nextInt(60);
int yy = random.nextInt(40);
drawArc(x,y,xx,yy,g);
} else {
drawNode(x,y,g);
}
g.dispose();
view.repaint();
}
public static void main(String[] args)
{
MyCanvas canvas = new MyCanvas();
JFrame frame = new JFrame();
int vertexes = 0;
// Change this next part later to be dynamic.
vertexes = 10;
int canvasSize = vertexes * vertexes;
frame.setSize(canvasSize, canvasSize);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(canvas.view);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public void drawNode(int x, int y, Graphics g)
{
// Treat each location as a 10x10 block. If position 1,1 then go to (5,5) - If position 3,5 then go to (25, 45) eg: (x*10)-5, (y*10)-5
int xLoc = (x*10) - 5;
int yLoc = (y*10) - 5;
g.setColor(Color.white);
g.fillOval(xLoc, yLoc, 8, 8);
g.drawOval(xLoc, yLoc, 8, 8);
}
public void drawArc(int x, int y, int xx, int yy, Graphics g)
{
int xLoc = (x*10) - 5;
int yLoc = (y*10) - 5;
int xxLoc = (xx*10) - 5;
int yyLoc = (yy*10) - 5;
g.drawLine(xLoc, yLoc, xxLoc, yyLoc);
}
}
Further tip
You might notice that the lines look quite 'jagged' & ugly. Both the BufferedImage or a JComponent has access to the more useful Graphics2D object (for the JComponent it is necessary to cast it in paintComponent()). A Graphics2D instance accepts rendering hints that can be used to smooth (dither) the elements drawn.
Ok so I am trying to add a JPanel to a JFrame as so:
gameClasses[2] = new a2();
gameClasses[2].setSize(100, 100);
menu.add(gameClasses[2]);
menu.setVisible(true);
a2() is a separate class that acts as a JPanel which I use the paintComponent to paint images to it. "menu" is the JFrame. My problem is when I call "gameClasses[2].setSize(100, 100);" it does not resize the JPanel but it stays the same size. Does anyone know what I am doing wrong or how this is supposed to be done because no one else seems to have any issues with this on the internet. Thanks.
EDIT: Here is the code related to menu and a2:
menu.setSize(swidth / 2 + swidth / 5, sheight / 2 + sheight / 5);
menu.setLocation((swidth - menu.getWidth()) / 2, (sheight - menu.getHeight()) / 3);
menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menu.setResizable(true);
menu.remove(main);
menu.add(gameClasses[0] = new a3());
menu.add(gameClasses[1] = new a4());
gameClasses[2] = new a2();
gameClasses[2].setSize(100, 100);
gameClasses[2].validate();
menu.add(gameClasses[2]);
menu.setVisible(true);
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class a2 extends JPanel {
public static int size = 48;
public static Image grsX = Toolkit.getDefaultToolkit().getImage("tiles/grsX.png");
public static Image grsY = Toolkit.getDefaultToolkit().getImage("tiles/grsY.png");
public static Image grsX1 = Toolkit.getDefaultToolkit().getImage("tiles/grsX1.png");
public static Image grsY1 = Toolkit.getDefaultToolkit().getImage("tiles/grsY1.png");
public a2() {
System.out.println("a2 loaded...");
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
//draw interface
for(int y = 0; y < a6.ay; y++) {
for(int x = 0; x < a6.ax; x++) {
g.drawImage(a5.Tile_Img.get(a5.ID_Tile.get(a6.area[x][y])), x * size, y * size, size, size, this);
if(x > 0) {
if(a6.area[x - 1][y].equals("00") && a6.area[x][y].equals("01")) {
g.drawImage(grsX, x * size, y * size, size, size, this);
}
}
if(x < a6.ax - 1) {
if(a6.area[x + 1][y].equals("00") && a6.area[x][y].equals("01")) {
g.drawImage(grsX1, x * size, y * size, size, size, this);
}
}
if(y > 0) {
if(a6.area[x][y - 1].equals("00") && a6.area[x][y].equals("01")) {
g.drawImage(grsY, x * size, y * size, size, size, this);
}
}
if(y < a6.ay - 1) {
if(a6.area[x][y + 1].equals("00") && a6.area[x][y].equals("01")) {
g.drawImage(grsY1, x * size, y * size, size, size, this);
}
}
}
}
repaint();
}
}
a3 and a4 are a KeyListener class and a MouseListener class that both extend JPanel
A layout is more likely to respect the preferred size than the size.
A call to pack() on the frame will make it become the minimum size needed to display the components inside. Call it after everything is added.
Don't call setLayout(null) (mentioned in comment as 'non-relevant' code). Use layouts.