Java jFrame Canvas 绘制点而不是线

标签 java swing jframe awt java-canvas

我一直想设计一个龙曲线生成器。

(如果您想了解有关该问题的信息,请查看 this,但这对问题来说并不重要)

龙曲线是一个重复的数学构造。 我已经为 Canvas 应该绘制的内容编写了一个生成器,它的工作原理是返回一个由“r”或“l”组成的字符数组,表示接下来该线是否必须向左转或向右转。在此处的代码中,它是方法 input()。这部分工作完美。

问题是,每当我想在 Canvas 上绘制它(使用drawLine)时,它只会将前两行绘制为实际线条,其余的只是点。

这些点位于正确的位置,如果你把东西做得很大,你就无法再分辨出差异了,但尽管如此,那里应该有线条。

图片: imgur

这是我使用的代码:

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




/**
  *
  * Description
  *
  * @version 1.0 from 4/20/2016
  * @author 
  */

public class CurveGen extends JFrame {
  // start attributes
  private Canvas display = new Canvas();
  private JButton startButton = new JButton();
  private JLabel jLabel1 = new JLabel();
  private JTextArea outText = new JTextArea("");
    private JScrollPane outTextScrollPane = new JScrollPane(outText);
  private JLabel jLabel2 = new JLabel();
  private JSlider xSlider = new JSlider();
  private JSlider ySlider = new JSlider();
  private JNumberField iterationsNF = new JNumberField();
  private JNumberField sizeNF = new JNumberField();
  // end attributes




  public CurveGen(String title) { 
    // Frame-Init
    super(title);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    int frameWidth = 1022; 
    int frameHeight = 731;
    setSize(frameWidth, frameHeight);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2;
    setLocation(x, y);
    setResizable(false);
    Container cp = getContentPane();
    cp.setLayout(null);
    // start components

    display.setBounds(16, 64, 601, 601);
    cp.add(display);
    startButton.setBounds(736, 464, 241, 129);
    startButton.setText("START!");
    startButton.setMargin(new Insets(2, 2, 2, 2));
    startButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent evt) { 
        startButton_ActionPerformed(evt);
      }
    });
    startButton.setFont(new Font("Dialog", Font.BOLD, 36));
    cp.add(startButton);
    jLabel1.setBounds(760, 96, 75, 41);
    jLabel1.setText("Iterations:");
    cp.add(jLabel1);
    outTextScrollPane.setBounds(728, 392, 257, 57);
    cp.add(outTextScrollPane);
    jLabel2.setBounds(768, 144, 67, 41);
    jLabel2.setText("Size:");
    cp.add(jLabel2);
    xSlider.setBounds(0, 8, 633, 49);
    xSlider.setMinorTickSpacing(25);
    xSlider.setMajorTickSpacing(100);
    xSlider.setPaintTicks(true);
    xSlider.setPaintLabels(true);
    xSlider.setToolTipText("Starting point y-coordinate");
    xSlider.setMaximum(600);
    xSlider.setValue(300);
    cp.add(xSlider);
    ySlider.setBounds(624, 56, 65, 625);
    ySlider.setMinorTickSpacing(25);
    ySlider.setMajorTickSpacing(100);
    ySlider.setPaintTicks(true);
    ySlider.setPaintLabels(true);
    ySlider.setOrientation(SwingConstants.VERTICAL);
    ySlider.setMaximum(600);
    ySlider.setInverted(true);
    ySlider.setValue(300);
    ySlider.setToolTipText("Starting point x-coordinate");
    cp.add(ySlider);
    iterationsNF.setBounds(856, 96, 81, 41);
    iterationsNF.setText("");
    cp.add(iterationsNF);
    sizeNF.setBounds(856, 144, 81, 41);
    sizeNF.setText("");
    cp.add(sizeNF);
    // end components

    setVisible(true);
  } // end of public CurveGen

  // start methods

  public static void main(String[] args) {
    new CurveGen("CurveGen");



  } // end of main

  public char[] input(int iter) {         
    char oldOut[] = new char[0];            
    for (int i=1;i<=iter;i++) {
      char newOut[] = new char[((int)Math.pow(2, i))-1];
      for (int n=0;n<oldOut.length;n++) {
        newOut[n] = oldOut[n];
        if (oldOut[n]=='r') {
          newOut[newOut.length-n-1] = 'l';
        }
        if (oldOut[n]=='l') {
          newOut[newOut.length-n-1] = 'r';
        } // end of if
      } // end of for
      newOut[oldOut.length]='l';      
      oldOut = newOut; 
    } // end of for        
    return oldOut;
  }  



  public void startButton_ActionPerformed(ActionEvent evt) {


    int iterations = iterationsNF.getInt();
    int size = sizeNF.getInt();

    char com[] = input(iterations);
    outText.setText(String.valueOf(com));

    int dir = 0;
    int newDir = 0;
    int lastPos[] = {xSlider.getValue(),ySlider.getValue()-size};
    int newPos[] = {0,0};

    Graphics g = display.getGraphics();

    g.clearRect(0,0,601,601);
    g.drawLine(xSlider.getValue(),ySlider.getValue(),xSlider.getValue(),ySlider.getValue()-size);


    for (int i=0;i<=com.length-1;i++) {
      dir = newDir;
      if (dir==0) {
        if (com[i]=='l') {
          newPos[0] = lastPos[0]-size;
          newPos[1] = lastPos[1];
          newDir = 3;
        } 
        if (com[i]=='r') {
          newPos[0] = lastPos[0]+size;
          newPos[1] = lastPos[1];
          newDir = 1;
        }              
      } 
      if (dir==1) {
        if (com[i]=='l') {
          newPos[0] = lastPos[0];
          newPos[1] = lastPos[1]-size;
          newDir = 0;
        } 
        if (com[i]=='r') {
          newPos[0] = lastPos[0];
          newPos[1] = lastPos[1]+size;
          newDir = 2;
        }              
      } 
      if (dir==2) {
        if (com[i]=='l') {
          newPos[0] = lastPos[0]+size;
          newPos[1] = lastPos[1];
          newDir = 1;
        } 
        if (com[i]=='r') {
          newPos[0] = lastPos[0]-size;
          newPos[1] = lastPos[1];
          newDir = 3;
        }              
      } 
      if (dir==3) {                                
        if (com[i]=='l') {
          newPos[0] = lastPos[0];
          newPos[1] = lastPos[1]+size;
          newDir = 2;
        } 
        if (com[i]=='r') {
          newPos[0] = lastPos[0];
          newPos[1] = lastPos[1]-size;
          newDir = 0;
        }              
      } 

      g.drawLine(lastPos[0],lastPos[1],newPos[0],newPos[1]);

      lastPos=newPos;
    } // end of for




  } // end of startButton_ActionPerformed

  // end methods
} // end of class CurveGen

最佳答案

好吧,我已经回顾了代码......

  • 混合重量级 (java.awt.Canvas) 和轻量级 (Swing) 组件是不可取的,因为它们可能会导致或各种绘画问题
  • getGraphics 不是绘制的方式。相反,我会从自定义 JPanel 开始并覆盖其 paintComponent。请参阅Painting in AWT and SwingPerforming Custom Painting了解更多详情
  • 避免使用 null 布局,像素完美布局是现代 UI 设计中的一种幻觉。影响组件个体尺寸的因素太多,您无法控制其中任何一个。 Swing 的设计目的是与核心的布局管理器一起工作,放弃这些将导致无休止的问题和问题,您将花费越来越多的时间来尝试纠正

我相信问题与此有关...

lastPos=newPos;

您所做的只是使 lastPos 指向内存中与 newPos 相同的位置,因此当您为 newPos 赋值时,lastPos 将具有相同的值,这就是您看到点的原因。

我首先要做的是将负责生成数据的部分与显示部分分开。

我将从某种模型开始(注意,您可以创建一个采用迭代并自行生成数据的模型,但我专注于解决最初的问题)

public class DragonModel {

    private Point startPoint;
    private int size;
    private char[] values;

    public DragonModel(Point startPoint, int size, char[] values) {
        this.startPoint = startPoint;
        this.size = size;
        this.values = values;
    }

    public Point getStartPoint() {
        return startPoint;
    }

    public int getSize() {
        return size;
    }

    public char[] getValues() {
        return values;
    }

}

然后显示...

public class DragonPane extends JPanel {

    private DragonModel model;

    public void setModel(DragonModel model) {
        this.model = model;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (model != null) {
            Graphics2D g2d = (Graphics2D) g.create();
            int size = model.getSize();
            int dir = 0;
            int newDir = 0;
            Point lastPos = model.getStartPoint();
            Point newPos = new Point(0, 0);

            for (char value : model.values) {
                if (dir == 0) {
                    if (value == 'l') {
                        newPos.x = lastPos.x - size;
                        newPos.y = lastPos.y;
                        newDir = 3;
                    }
                    if (value == 'r') {
                        newPos.x = lastPos.x + size;
                        newPos.y = lastPos.y;
                        newDir = 1;
                    }
                }
                if (dir == 1) {
                    if (value == 'l') {
                        newPos.x = lastPos.x;
                        newPos.y = lastPos.y - size;
                        newDir = 0;
                    }
                    if (value == 'r') {
                        newPos.x = lastPos.x;
                        newPos.y = lastPos.y + size;
                        newDir = 2;
                    }
                }
                if (dir == 2) {
                    if (value == 'l') {
                        newPos.x = lastPos.x + size;
                        newPos.y = lastPos.y;
                        newDir = 1;
                    }
                    if (value == 'r') {
                        newPos.x = lastPos.x - size;
                        newPos.y = lastPos.y;
                        newDir = 3;
                    }
                }
                if (dir == 3) {
                    if (value == 'l') {
                        newPos.x = lastPos.x;
                        newPos.y = lastPos.y + size;
                        newDir = 2;
                    }
                    if (value == 'r') {
                        newPos.x = lastPos.x;
                        newPos.y = lastPos.y - size;
                        newDir = 0;
                    }
                }
                g.drawLine(lastPos.x, lastPos.y, newPos.x, newPos.y);
                dir = newDir;
                lastPos = new Point(newPos);

            }
        }

    }
} 

这里的想法是尝试将责任稍微解耦,数据生成和显示的责任牢牢地位于两个不同的领域。

然后在您的 actionPerformed 方法中您可以简单地执行...

public void startButton_ActionPerformed(ActionEvent evt) {

    int iterations = Integer.parseInt(iterationsNF.getText());
    int size = Integer.parseInt(sizeNF.getText());

    char com[] = input(iterations);
    outText.setText(String.valueOf(com));

    DragonModel model = new DragonModel(new Point(xSlider.getValue(), ySlider.getValue()), size, com);
    display.setModel(model);

} // end of startButton_ActionPerformed

这可能会导致......

Dragons!

关于Java jFrame Canvas 绘制点而不是线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36757704/

相关文章:

java - Q关于Java WindowListener

java - 无法更新子 JFrame 中的结果表

java - 从 JFrame 类中的按钮触发 Controller 类中的方法

java - 如何在eclipse galileo中配置struts?

java - 如何选择光源来实现 Phong 着色?

java - jsoup 表获取特定元素

java - 确保 SpringLayout 不会缩小到一定大小以下

java - 为什么这三个使用 GridBagLayout 的面板使用不同的额外空间,以及如何使它们统一

java - SWING - 绘制直线,编译时不会出现

java - 如何从 GWT 中的动态 FlexTable 获取行值?