2016-04-21 70 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!