2016-04-21 36 views
0

所以我一直想设计一个龙曲线发生器。Java jFrame画布画点而不是线条

(如果您想对这些信息检查了这一点https://en.wikipedia.org/wiki/Dragon_curve ,但它并不真正重要的问题)

龙曲线是重复的数学结构。 我已经为画布应该绘制的东西写了一个生成器,它通过返回一个由'r'或'l'组成的char数组来表示它是否必须向左或向右转。在这里的代码中,它的方法input()。这部分工作完美。

问题在于,无论何时我想在画布上绘制它(使用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 
+2

按照网站[求助]建议,请发布你的[mcve]。什么是“显示”?我希望它是一个BufferedImage而不是Swing组件。 –

+2

'图形g = display.getGraphics();'吓倒我。如果您使用'JComponent#getGraphics',则不要 – MadProgrammer

+0

“display”是正在绘制的画布。 –

回答

0

绘图代码应该是内线(图形)方法与渲染循环正确进行同步。在事件处理程序中,更新组件的数据模型(计算行并将它们保存在组件内的数据结构中),然后调用方法repaint()来触发事件渲染循环,该循环将调用您的paint方法。

还有一些其他的变化,但总的想法是,你改变数据,然后请求渲染。在其他情况下,渲染引擎也可能会调用您的绘画方法,不仅在您更改数据时,所以理想情况下,paint()具有快速渲染所需的所有数据,这意味着它不应该执行除渲染之外的计算或繁重操作Graphics对象。

这意味着您必须在新类中继承JComponent,并在其中实现paint。这个类应该有一个内部数据结构,其中的行可以随时渲染。然后在JFrame中使用你的新类。

2

好了,我已经回到了代码...

  • 混合重量级(java.awt.Canvas),重量轻(摇摆)组件是不妥当的,因为它们可引起或绘画的问题各种各样
  • getGraphics是不是应该如何做油漆。相反,我会从一个自定义JPanel开始并覆盖它的paintComponent。有关更多详细信息,请参阅Painting in AWT and SwingPerforming Custom Painting
  • 避免使用null布局,像素完美布局是现代UI设计中的幻觉。影响组件的个体大小的因素太多,其中没有一个可以控制。 Swing旨在与布局经理一起工作,放弃这些将导致问题和问题的终结,您将花费越来越多的时间尝试纠正

我相信问题与此有关。 。

lastPos=newPos; 

所有你做的是使lastPos指向内存中的同一个地方newPos,所以当你赋值newPoslastPos将具有相同的值,因此,您所看到的点的原因。

我会先做什么,是独立的负责从显示屏生​​成数据。

我会先从一些样的模式(注意,你可以创建历时iterations代替和生成的数据本身就是一个模型,但我重点解决最初的问题)

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!