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.
CodePudding user response:
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();
}
}
}
CodePudding user response:
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 slightlight 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 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;
}
CodePudding user response:
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.