简体   繁体   English

在 JPanel 的整个高度上绘制线条

[英]Drawing lines the full height of JPanel

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当绘制的线条数 > 20 时,线条不会被绘制以占用面板的全部空间

** Look at the bottom right side of my screenshot. ** 看看我截图的右下角。 The lines go part way down the full height of the panel. go 行在面板的整个高度下方。 I need it to go the full length of the height down.我需要它到 go 高度的全长。 ** **

在此处输入图像描述

Here's my code for DrawPanelTest这是我的 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这是我的代码 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.我认为我的问题出在 DrawPanel 第 41 行。我认为我没有正确计算线条之间的空间,因此它们最终占据了面板的整个高度。

Thanks in advance for your help.在此先感谢您的帮助。

Your calculation of the "stepValue" has two problems:您对“stepValue”的计算有两个问题:

  1. the stepValue is to small, so the last line will never appear at the bottom stepValue 太小,所以最后一行永远不会出现在底部
  2. 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. stepValue 因 integer 数学而被截断,因此每次将截断值添加到“spaceValue”都会产生稍微不太准确的值。

Lets say you have a panel with a height of 600 and the number of lines is 3.假设您有一个高度为 600 且行数为 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.我认为这是错误的,因为您会绘制 3 条“spaceValue”为 0、200、400 的线,因此永远不会绘制最后一条线(在 600 处)。

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.这将给出“spaceValue”为 0、300、600 的线,这将是顶部、中间和底部的线。

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)例如,如果height400且行数为6 ,则stepValue将为66而不是67 (这将允许 66.6666 向上舍入)

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.现在,您可以自己“四舍五入”该值,但我更愿意利用可用的 API 为我做这些事情。

Line2D.Double supports double precision parameters, which makes it perfect for this job Line2D.Double支持双精度参数,非常适合这项工作

@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循环中,改变

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. i必须等于 numLines 才能达到统一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM