Using Bresenham’s Circle Algorithm to generate an Ellipse in Java - java

I am trying to create a GUI based program which uses a grid and Bresenham’s Circle Algorithm to draw an ellipse. However, I am having two problems. One is that I am unable to get the panel_grid to refresh such that the new value of r is passed to the GridComponent and the ellipse is redrawn with the new radius. The second issue is that I managed to get the code to generate a circle, but I am unable to figure out how I would modify it to generate an ellipse instead. Can someone explain to me step by step how I would go about solving both these problems? Thanks in advance.
public class GUI extends JFrame {
private int r = 100;
public GUI(){
JFrame frame = new JFrame("Bresenham’s Ellipse Algorithm");
frame.setIconImage(Toolkit.getDefaultToolkit().getImage(GUI.class.getResource("/com/sun/java/swing/plaf/windows/icons/TreeLeaf.gif")));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(600, 600));
frame.setMinimumSize(new Dimension(440, 400));
JPanel panel = new JPanel();
JLabel label = new JLabel("Input the Dimensions of the Ellipse");
label.setFont(new Font("Sinhala Sangam MN", Font.PLAIN, 16));
JPanel panel_inst = new JPanel();
panel_inst.setPreferredSize(new Dimension(550, 30));
panel_inst.add(label);
panel.add(panel_inst);
JPanel panel_1 = new JPanel();
JLabel w = new JLabel("Radius");
JTextField width = new JTextField(10);
JPanel panel_grid = new JPanel();
JButton draw = new JButton("Draw");
draw.setPreferredSize(new Dimension(80, 25));
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r = Integer.parseInt(width.getText());
panel_grid.revalidate();
panel_grid.repaint();
}
});
panel_1.add(w);
panel_1.add(width);
panel_1.add(draw);
panel.add(panel_1);
panel_grid.setBackground(Color.white);
panel_grid.setPreferredSize(new Dimension(550, 450));
GridComponent grid = new GridComponent(r);
panel_grid.add(grid);
panel.add(panel_grid);
frame.pack();
frame.setVisible(true);
frame.setContentPane(panel);
}
public class GridComponent extends JComponent{
int r;
public GridComponent(int r){
this.r = r;
setPreferredSize(new Dimension(550, 450));
}
public void paintComponent(Graphics g){
//Draw Grid
Graphics2D g2 = (Graphics2D) g;
int width = 54;
int height = 44;
int size = 10;
for( int i = 0; i < width; i ++){
for( int j = 0; j < height; j++){
Rectangle grid = new Rectangle( 0 + i * size, 0 + j * size, size, size);
g2.draw(grid);
}
}
g.setColor(Color.black);
g2.fillOval((int)Math.floor((width*size)/2)-3,(int)Math.floor((height*size)/2-6)+3, 5, 5);
g2.drawLine(0, (int)Math.floor((height*size)/2)-1, (int)Math.floor((width*size)), (int)Math.floor((height*size)/2)-1);
g2.drawLine((int)Math.floor((width*size/2))-1, 0, (int)Math.floor((width*size)/2)-1, (int)Math.floor((height*size)));
//Draw Ellipse using algo
int a = (int)Math.floor((height*size/2));//(int)Math.floor((width*15/2));
int b = (int)Math.floor((width*size/2));// (int)Math.floor((height*15/2));
int x = r, y = 0, d = 3 - 2*r;
g2.setColor(Color.red);
// x is initially r, x will be same as y at 45(degree) angle
while(y <= x) {
// Eight way symmetry of circle
g2.drawString("+", x + b, y + a);
g2.drawString(".", y + b, x + a);
g2.drawString("+", (-1)*y + b, x + a);
g2.drawString(".", (-1)*x + b, y + a);
g2.drawString("+", (-1)*x + b, (-1)*y + a);
g2.drawString(".", (-1)*y + b, (-1)*x + a);
g2.drawString("+", y + b, (-1)*x + a);
g2.drawString(".", x + b, (-1)*y + a);
if(d < 0) // move Up = d + Up + 2
d = d + 4*y + 6;
else { // move Left = d + Left + 2
d = d - 4*(x - y) + 10;
//Since we've started at the right hand side of the circle
x = x - 1;
}
// Since we have started at top of the circle
y = y + 1;
}
}
private int side;
}
}

Start by...
Adding a setter for the radius to your GridComponent class
public void setR(int r) {
this.r = r;
repaint();
}
Then...
Change your ActionListener to interact with your GridComponent and call it's setter method
GridComponent grid = new GridComponent(r);
draw.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
r = Integer.parseInt(width.getText());
grid.setR(r);
}
});
Which will answer the first part of your question.
The second part is more difficult and I'm not going to attempt to generate code, other then to say, you need two values, you need a width and height radius
But, Bresenham's circle/ellipse drawing algorithm might provide an insight

Related

Coloring a Triangle with 3 colors

Please help me how to color the triangle with the three colors. I have it as a problem for school,
Use Java programming language
Hello this is the code:
I am trying to fill the triangle with the three colors, but is hard to mix colors to get it. Please if you are to solve it(approximate it) as much as you can send it to me, i have it as a homework and 5-6 days deadline
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.geom.*;
public class NotFullVersion2 extends JApplet {
public static void main(String s[]) {
JFrame frame = new JFrame();
frame.setTitle("Colors");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet = new NotFullVersion2();
applet.init();
applet.addMouseListener(
new MouseAdapter(){
public void mousePressed(MouseEvent e) {
System.out.println(e.getX() + " " + e.getY());
}});
frame.getContentPane().add(applet);
frame.pack();
frame.setVisible(true);
}
ColorPanel panel;
public void init() {
panel = new ColorPanel();
Container cp = getContentPane();
cp.setLayout(new BorderLayout());
cp.add(panel, BorderLayout.CENTER);
JPanel p = new JPanel();
cp.add(p,BorderLayout.EAST);
}
}
class ColorPanel extends JPanel {
//int red = 100,green = 100, blue = 100;
public ColorPanel() {
setPreferredSize(new Dimension(500, 500));
setBackground(Color.black);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
for(int i = 0; i < 256; i++) {
int start = 399;
g2.setColor(new Color(0,i,255-i));
for(int j = 0; j < 200; j ++) {
Rectangle rec = new Rectangle(150+j,start - i,1,1);
g2.fill(rec);
}
}
for(int j = 0; j < 100; j++) {
int start = 100;
for(int i = 0; i < 300; i++) {
if(i < 22) {
g2.setColor(new Color(255,0,0));
Rectangle rec = new Rectangle(100 + i,start + j,1,1);
g2.fill(rec);
} else if(i > 21 && i < 278) {
g2.setColor(new Color(255-(i-22),(i-22),0));
Rectangle rec = new Rectangle(100 + i,start + j,1,1);
g2.fill(rec);
} else if(i < 300) {
g2.setColor(new Color(0,255,0));
Rectangle rec = new Rectangle(100 + i,start + j,1,1);
g2.fill(rec);
}
}
}
GeneralPath closePath1a = new GeneralPath();
g2.setColor(new Color(0,0,0));
closePath1a.moveTo(100,100);
closePath1a.lineTo(100,400);
closePath1a.lineTo(250,400);
closePath1a.closePath();
g2.fill(closePath1a);
GeneralPath closePath2a = new GeneralPath();
g2.setColor(new Color(0,0,0));
closePath2a.moveTo(400,100);
closePath2a.lineTo(400,400);
closePath2a.lineTo(250,400);
closePath2a.closePath();
g2.fill(closePath2a);
GeneralPath closePath3a = new GeneralPath();
g2.setColor(new Color(0,0,0));
closePath3a.moveTo(100,100);
closePath3a.lineTo(100,50);
closePath3a.lineTo(400,50);
closePath3a.lineTo(400,100);
closePath3a.closePath();
g2.fill(closePath3a);
}
}
Coloring a triangle like this is equivalent to calculating the barycentric coordinates of each pixel within the triangle. The following untested code calculates the barycentric coordinates for each pixel within the triangle ABC, and then uses it to color that pixel:
private float area(float Ax, float Ay, float Bx, float By, float Cx, float Cy) {
return 0.5*((Ax - Cx)*(By - Ay) - (Ax - Bx)*(Cy - Ay));
}
private void paintTriangle(Graphics g, float Ax, float Ay, float Bx, float By, float Cx, float Cy) {
// calculate the bounding box of the triangle:
int minX = Math.round(Math.min(Ax, Math.min(Bx, Cx)));
int minY = Math.round(Math.min(Ay, Math.min(By, Cy)));
int maxX = Math.round(Math.max(Ax, Math.max(Bx, Cx)));
int maxY = Math.round(Math.max(Ay, Math.max(By, Cy)));
// loop for each pixel in the bounding box of the triangle
for(int y = minY; y < maxY; ++y) {
for(int x = minX; x < maxX; ++x) {
// center of the pixel (x,y)
float Px = x + 0.5, Py = y + 0.5;
// barycentric coordinates of P
float denom = area(Ax, Ay, Bx, By, Cx, Cy);
float b0 = area(Px, Py, Bx, By, Cx, Cy)/denom;
float b1 = area(Ax, Ay, Px, Py, Cx, Cy)/denom;
float b2 = area(Ax, Ay, Bx, By, Px, Py)/denom;
// discard pixels outside the triangle
if(b0 < 0 || b1 < 0 || b2 < 0)
continue;
// paint a pixel of color (b0,b1,b2) at (x,y)
g.setColor(new Color(b0,b1,b2));
g.fillRect(x,y,1,1));
}
}
}
I'll leave it to you to test and integrate this code.
You can read more about barycentric coordinates on wikipedia;

How to Disable the components of a panel when a button is clicked

I have some problem with my code!.... I was able to create an array of 12 JButtons in a circular form in a JPanel with the code below!... I am setting an actionListener on each JButton, and I want to disable others once one of the Jbuttons is clicked.... and enable it afterwards..... For more understanding, here is my code
int n = 10;
public Beginner() {
int radius = 200;
Point center = new Point (250, 250);
double angle = Math.toRadians(360 / n);
List <Point> points = new ArrayList<Point> ();
points.add(center);
for (int i = 0; i < n; i++) {
double theta = i * angle;
int dx = (int) (radius * Math.sin(theta));
int dy = (int) (radius * Math.cos(theta));
Point p = new Point (center.x + dx , center.y + dy);
points.add(p);
}
draw (points);
}
public void draw (List<Point> points) {
JPanel panels = new JPanel();
SpringLayout spring = new SpringLayout();
int count = 1;
for (Point point: points) {
quest = new JButton("Question " + count);
quest.setForeground(Color.BLACK);
Font fonte = new Font("Script MT Bold", Font.PLAIN, 20);
quest.setFont(fonte);
add (quest);
count++;
spring.putConstraint(SpringLayout.WEST, quest, point.x, SpringLayout.WEST, panels );
spring.putConstraint(SpringLayout.NORTH, quest, point.y, SpringLayout.NORTH, panels );
setLayout(spring);
panels.setOpaque(false);
panels.setVisible(true);
panels.setLocation(5,5);
add(panels);
quest.addActionListener(new ActionListener(){
public void actionPerformed (ActionEvent q) {
if (point.equals(points.get(0))) {
//Some action....
//It is at this point that every other Jbutton in the panel is to be disabled until the action ends..... It is here that I need help!!!
try this solution:
quest.addActionListener(new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton b = (JButton)e.getSource();
for(Component c : yourPanel.getComponents()){
if(c instanceof JButton && !c.equals(b)){
c.setEnabled(false);
}
}
}
});

Button To Reset The View Of JFrame

I have to write a program that will generate 20 random circles with random radius lengths. If any of these circles intersect with another, the circle must be blue, and if it does not intersect, the color is red. I must also place a button on the JFrame. If this button is pressed, it needs to clear out the JFrame, and generate a new set of 20 circles following the same color rules. I am extremely new to Java Swing and am really stuck. I have everything working except the button. I cannot get a new set of circles to generate. Any help would be greatly appreciated. Thank You.
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class IntersectingCircles extends JPanel
{
private int[] xAxis = new int [20]; // array to hold x axis points
private int[] yAxis = new int [20]; // array to hold y axis points
private int[] radius = new int [20]; // array to hold radius length
public static void main (String[] args)
{
JFrame frame = new JFrame("Random Circles");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new IntersectingCircles());
frame.pack();
frame.setVisible(true);
}
public IntersectingCircles()
{
setPreferredSize(new Dimension(1000, 800)); // set window size
Random random = new Random();
// Create coordinates for circles
for (int i = 0; i < 20; i++)
{
xAxis[i] = random.nextInt(700) + 100;
yAxis[i] = random.nextInt(500) + 100;
radius[i] = random.nextInt(75) + 10;
}
}
public void paintComponent(Graphics g)
{
// Add button to run again
JButton btnAgain = new JButton("Run Again");
btnAgain.setBounds(850, 10, 100, 30);
add(btnAgain);
btnAgain.addActionListener(new ButtonClickListener());
// Determine if circles intersect, create circles, color circles
for (int i = 0; i < 20; i++)
{
int color = 0;
for (int h = 0; h < 20; h++)
{
if(i != h)
{
double x1 = 0, x2 = 0, y1 = 0, y2 = 0, d = 0;
x1 = (xAxis[i] + radius[i]);
y1 = (yAxis[i] + radius[i]);
x2 = (xAxis[h] + radius[h]);
y2 = (yAxis[h] + radius[h]);
d = (Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1)*(y2 - y1))));
if (d > radius[i] + radius[h] || d < (Math.abs(radius[i] - radius[h])))
{
color = 0;
}
else
{
color = 1;
break;
}
}
}
if (color == 0)
{
g.setColor(Color.RED);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
else
{
g.setColor(Color.BLUE);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
}
}
private class ButtonClickListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String action = e.getActionCommand();
if(action.equals("Run Again"))
{
new IntersectingCircles();
}
}
}
}
Suggestions:
Give your class a method that creates the random circles and calls repaint()
This method should create the circles and add them into an ArrayList.
Consider using Ellipse2D to represent your circles, and so you'd have an ArrayList<Ellipse2D>.
Call this method in your class constructor.
Call it again in the button's ActionListener.
Never add button's or change the state of your class from within your paintComponent method. This method is for drawing the circles and drawing them only and nothing more. Your way you will be creating the button each time the paintComponent method is called, so you could be potentially needlessly creating many JButtons
and needlessly slowing down your time-critical painting method.
Instead add the button in the constructor.
Be sure to call super.paintComponent(g) in your paintComponent method as its first call. This will clear the old circles when need be.
Also in paintComponent, iterate through the ArrayList of circles, drawing each one.
After some searching on this website, i found what i needed. Everything seems to work now. Thanks.
import java.awt.Graphics;
import javax.swing.JPanel;
import java.util.Random;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class IntersectingCircles extends JPanel
{
private int[] xAxis = new int [20]; // array to hold x axis points
private int[] yAxis = new int [20]; // array to hold y axis points
private int[] radius = new int [20]; // array to hold radius length
public static void main (String[] args)
{
JFrame frame = new JFrame("Random Circles");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(1000, 800));
ActionListener runAgain = new ActionListener()
{
#Override
public void actionPerformed(ActionEvent c)
{
frame.getContentPane().add(new IntersectingCircles());
frame.pack();
}
};
JButton btnAgain = new JButton("Run Again");
btnAgain.setBounds(850, 10, 100, 30);
btnAgain.addActionListener(runAgain);
frame.add(btnAgain);
frame.getContentPane().add (new IntersectingCircles());
frame.pack();
frame.setVisible(true);
}
public IntersectingCircles()
{
Random random = new Random();
// Create coordinates for circles
for (int i = 0; i < 20; i++)
{
xAxis[i] = random.nextInt(700) + 100;
yAxis[i] = random.nextInt(500) + 100;
radius[i] = random.nextInt(75) + 10;
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
// Determine if circles intersect, create circles, color circles
for (int i = 0; i < 20; i++)
{
int color = 0;
for (int h = 0; h < 20; h++)
{
if(i != h)
{
double x1 = 0, x2 = 0, y1 = 0, y2 = 0, d = 0;
x1 = (xAxis[i] + radius[i]);
y1 = (yAxis[i] + radius[i]);
x2 = (xAxis[h] + radius[h]);
y2 = (yAxis[h] + radius[h]);
d = (Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1)*(y2 - y1))));
if (d > radius[i] + radius[h] || d < (Math.abs(radius[i] - radius[h])))
{
color = 0;
}
else
{
color = 1;
break;
}
}
}
if (color == 0)
{
g.setColor(Color.RED);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
else
{
g.setColor(Color.BLUE);
g.drawOval(xAxis[i], yAxis[i], radius[i] * 2, radius[i] * 2);
}
}
}
}
private class ButtonClickListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
repaint();
}
}
Maybe you can have a try...

Closest pair of points using mouse clicks

The assignment is to to a closest pair of points using brute force.
I seem to have most everything I need - the frame appears, circles appear where I click, and the closest pairs seem to highlight properly, I say "seems" because this is where my question lies. I need only two circles highlighted at any given time (the closest pair), but previous closest pairs do not de-select/unhighlight.
I hope this is something simple I have overlooked. I have been at this for a while, so it's very possible my mind and eyes are just too tired to pick this problem up. Hopefully, a fresh set of eyes will do me some good.
Any help is greatly appreciated.
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import javax.swing.*;
public class AssignmentFour extends JFrame {
private final PointPanel canvas = new PointPanel();
public AssignmentFour() {
JPanel panel = new JPanel();
this.add(canvas, BorderLayout.CENTER);
this.add(panel, BorderLayout.SOUTH);
add(new JLabel("<html> Click anywhere within the panel."
+ "<BR> The two closest points will be highlighted.<BR>"
+ "Click the 'x' to exit program. </html>"), BorderLayout.SOUTH);
}//AssignmentFour method
public static void main(String[] args) {
AssignmentFour frame = new AssignmentFour();
frame.setTitle("Closest points");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600, 600);
frame.setVisible(true);
}//main
class PointPanel extends JPanel {
private int xCoordinate = 200;
private int yCoordinate = 200;
private int radius = 5;
private Graphics g;
double minDist = 999999999;
ArrayList<Point> points = new ArrayList<>();
Point ClosestPoint1, ClosestPoint2;
public final double distBetweenPoints(int x, int y, int a, int b) {
double theDist = 0.0;
theDist = Math.sqrt(Math.pow(a - x, 2) + Math.pow(y - b, 2));
return theDist;
}//distBetweenPoints method
public PointPanel() {
addMouseListener(new MouseAdapter() {
#Override
public void mouseReleased(MouseEvent e) {
xCoordinate = e.getX();
yCoordinate = e.getY();
Point newCoord = e.getPoint();
points.add(newCoord);
g = getGraphics();
g.setColor(Color.RED);
g.drawOval(xCoordinate, yCoordinate, radius, radius);
//g.dispose();
if (points.size() >= 2) {
for (int i = 0; i < points.size(); i++) {
for (int j = i + 1; j < points.size(); j++) {
Point p = points.get(i);
Point q = points.get(j);
int x1 = p.x;
int y1 = p.y;
int a1 = q.x;
int b1 = q.y;
if (distBetweenPoints(x1, y1, a1, b1) < minDist) {
minDist = distBetweenPoints(x1, y1, a1, b1);
ClosestPoint1 = p;
ClosestPoint2 = q;
}//inner if
else {
}//else
}//for 'j'
}// for 'i'
int x2 = ClosestPoint1.x;
int y2 = ClosestPoint1.y;
int a2 = ClosestPoint2.x;
int b2 = ClosestPoint2.y;
g.fillOval(x2, y2, radius, radius);
g.fillOval(a2, b2, radius, radius);
}//if
}//mouseReleased
}//MouseListener
);
}//pointPanel
}//point panel extend
}//assignmentfour class
Don't use getGraphics to perform
Custom painting, this is not how painting in Swing is done
Instead, override the JPanels paintComponent method and put your custom painting within it
Take a look at Performing Custom Painting for more details

Writing a JPanel subclass that will obey GridBagLayout?

I built a class that extends JPanel, and I have been setting a size on it every time. But now I need multiple instances of that JPanel sub-class to exist on another panel. I am using GridBagLayout, but my components disappear when I resize the Frame or take away the setSize(800,100) from the JPanel subclass. How do I built components that will obey these layout managers?
I want my custom component to be able to fit to the size that the layout manager asks for.
Here is my custom component
public class GridPanel extends JPanel implements MouseMotionListener, MouseListener{
private Rectangle offdutyRect, sbRect, driveRect, onRect;
private int delta = 60;
private int[][] gridArray;
int draggedStartX = -1;
int draggedStartY = -1;
private int dutyStatusSpacing = 60;
private int totalSpacing = 80;
public GridPanel(){
super();
this.setSize(new Dimension(800, 100));//without this it doesn't display
this.addMouseMotionListener((MouseMotionListener) this);
this.addMouseListener(this);
int gridArrayColumns = 24*60/delta;
gridArray = new int[4][gridArrayColumns];
int r = 0;
int rHeight = this.getHeight()/4;
offdutyRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
sbRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
driveRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
r++;
onRect = new Rectangle(this.getX() + dutyStatusSpacing, this.getY() + r*rHeight, this.getWidth() - totalSpacing, rHeight);
Rectangle rect = null;
for(r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
rect.setSize((int)(width*len), (int) rect.getHeight());
}
}
public void paintComponent(Graphics g){
g.clearRect(this.getX(), this.getY(), this.getWidth(), this.getHeight());
//the center black bar for duty status "placeholders"
g.setColor(Color.black);
g.drawRect(getX(), getY(), getWidth() - 1, getHeight() - 1);
g.drawRect((int)offdutyRect.getX(), (int)offdutyRect.getY() + (int)offdutyRect.getHeight()/2, (int)offdutyRect.getWidth(), 1);
g.drawRect((int)sbRect.getX(), (int)sbRect.getY() + (int)sbRect.getHeight()/2, (int)sbRect.getWidth(), 1);
g.drawRect((int)driveRect.getX(), (int)driveRect.getY() + (int)driveRect.getHeight()/2, (int)driveRect.getWidth(), 1);
g.drawRect((int)onRect.getX(), (int)onRect.getY() + (int)onRect.getHeight()/2, (int)onRect.getWidth(), 1);
g.setColor(Color.pink);
g.drawRect((int)offdutyRect.getX(), (int)offdutyRect.getY(), (int)offdutyRect.getWidth(), (int)offdutyRect.getHeight());
g.drawRect((int)sbRect.getX(), (int)sbRect.getY(), (int)sbRect.getWidth(), (int)sbRect.getHeight());
g.drawRect((int)driveRect.getX(), (int)driveRect.getY(), (int)driveRect.getWidth(), (int)driveRect.getHeight());
g.drawRect((int)onRect.getX(), (int)onRect.getY(), (int)onRect.getWidth(), (int)onRect.getHeight());
//draw the array
g.setColor(Color.green);
Rectangle rect = null;
for(int r = 0; r < gridArray.length; r++){
if(r == 0){
rect = offdutyRect;
}else if(r == 1){
rect = sbRect;
}else if(r == 2){
rect = driveRect;
}else if(r == 3){
rect = onRect;
}
//I haven't actually derived any of these things, just my best guesses.
int len = gridArray[r].length;
int width = (int) (rect.getWidth()/len);
int height = (int) rect.getHeight() - 2;
for(int c = 0; c < gridArray[r].length; c++){
if(gridArray[r][c] == 1){
int x = (int) (rect.getX() + width*c);
int y = (int) rect.getY() + 2;
g.fillRect(x, y, width, height);
}
}
}
}
And here is how I am adding them to the container using gridbag
public void actionPerformed(ActionEvent e) {
System.out.println("action performed" + panels.size());
removeAll();
repaint();
panels.add(new GridPanel());
int r = 0;
GridBagConstraints c = new GridBagConstraints();
for(int i = 0; i < panels.size(); i++){
JLabel label = new JLabel("day " + i);
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
this.add(label, c);
r++;
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(panels.get(i), c);
r++;
}
c = new GridBagConstraints();
c.gridx = 0;
c.gridy = r;
c.fill = GridBagConstraints.HORIZONTAL;
BufferedImage img = null;
try {
img = ImageIO.read(this.getClass().getResource("/res/add.png"));
} catch (IOException ex) { }
JButton addButton = new JButton();
addButton.setIcon(new ImageIcon(img));
addButton.addActionListener(this);
this.add(addButton, c);
}
When I do this "action performed" that is supposed to add it, my custom component shows up in the top left corner, but I have to resize the window to get all the components to show.
Many layout managers make use of the values returned by getPreferredSize, getMinimumSize and getMaximumSize.
GridBagLayout is one of those which will, generally, where possible, try and honor all three.
In your custom component, override (at least), the getPreferredSize method and return, to the best of you knowledge, the size of the component you need.
If the component is using a layout manager with other components in it, you should always let the layout manager make this determination (which is the default behavior)
Updated
Don't forget, when adding or removing components, you may be required to call revalidate to force the container hierarchy to update it's layout(s)

Categories

Resources