2012-12-21 21 views
3

我正在创建绘图板程序,基本上是MS Paint的简化版本。它在大多数情况下都有效,但是当我在画板上画画时,当前选定的UI元素显示在绘图区域中。在Java中自定义绘画 - 将UI元素绘制到JPanel上

我尝试了paintComponent,它在我调用super.paintComponent(g)(就像这样)时工作,但它在绘制下一个对象之前清除了绘图区域。我覆盖更新并在其中放置一个println语句,它永远不会被调用。

顶部的按钮为红色,因为我将背景设置为底部JPanel以红色,以查看这些按钮的背景是什么。显然他们是底层JPanel的一部分。我正在使用BorderLayout进行布局。

enter image description here

这里是我的代码(去掉一些无关痛痒的位):

public class JSPaint extends JFrame implements Serializable 
{  
    private static final long serialVersionUID = -8787645153679803322L; 
    private JFrame mainFrame; 
    private JPanel bp; 
    private JButton ... 
    private DrawingArea da; 

    public JSPaint() 
    { 
     setTitle("JS Paint"); 
     setSize(1024, 768); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     // Drawing area 
     da = new DrawingArea(); 

     setLayout(new BorderLayout()); 

     // add the buttons to the panel 
     buttonPanel(); 

     // Add the drawing area 
     add(bp, BorderLayout.SOUTH); 
     bp.setBackground(Color.RED); 
     add(da, BorderLayout.CENTER); 
     da.setBackground(Color.BLUE); 

     setVisible(true);   
    } 

    // I put it here too just in case 
    @Override 
    public void update(Graphics g) 
    { 
     System.out.println("update in JSPaint called."); 
     paint(g); 
    } 

    /* 
    * Creates the panel for the buttons, creates the buttons and places them on 
    * the panel 
    */ 
    public void buttonPanel() 
    { 
     // Create the panel for the buttons to be placed in 
     bp = new JPanel(); 

     saveButton = new JButton("Save"); 
     loadButton = new JButton("Load"); 
     //more buttons 

     bp.add(saveButton); 
     bp.add(loadButton); 
     //more buttons 

     // ActionListeners 

     colorButton.addActionListener(new ActionListener() 
     { 
      public void actionPerformed(ActionEvent ae) 
      { 
       System.out.println("color"); 
       da.color(); 
      } 
     });    
    } 

    public class DrawingArea extends JPanel 
    {   
     private static final long serialVersionUID = -8299084743195098560L; 
     boolean dragged = false; 

     @Override 
     public void update(Graphics g) 
     { 
      System.out.println("Update in DrawingArea called"); 
      paint(g); 
     } 

     /* 
     * Draws the selected shape onto the screen and saves it into a Stack. 
     * 
     */ 
     public void draw() 
     { 
      this.addMouseMotionListener(new MouseMotionListener() 
      {     
       public void mouseDragged(MouseEvent me) 
       { 
        dragged = true; 
       } 

       public void mouseMoved(MouseEvent me) {} 
      }); 

      //more listeners... 
      }); 
     } 

     /* 
     * Draws the selected String onto the screen when the mouse is held down. 
     * 
     */ 
     public void brush() 
     { 
      this.addMouseMotionListener(new MouseMotionListener() 
      {     
       public void mouseDragged(MouseEvent me) 
       { 
        // If we are in drawing mode, draw the String. Create a new 
        // Figure Object and push it onto the Stack 
        if(activeButton == "brush") 
        { 
         startPoint = me.getPoint(); 

         Figure fig = new Figure("String", startPoint, null, currentColor); 
//      figures.push(calculate(fig)); 
         toPaint.push(calculate(fig)); 
         repaint(); 
        } 
       } 

       public void mouseMoved(MouseEvent me) {} 
      });   
     } 

     // more of the same... 

     public void paint(Graphics g) 
     {       
      toSave.addAll(toPaint); 

      while(!toPaint.isEmpty()) 
      { 
       Figure f = toPaint.pop(); 
       String t = f.type; 

       if(f.color != null) 
       { 
        g.setColor(f.color); 
       } 

       switch(t) 
       { 
        case "Rectangle": g.drawRect(f.x1, f.y1, f.width, f.height); 
         break; 
        case "Oval": g.drawOval(f.x1, f.y1, f.width, f.height); 
         break;   
        case "Line": g.drawLine(f.x1, f.y1, f.x2, f.y2); 
         break; 
        case "Clear": 
         g.fillRect(0, 0, da.getWidth(), da.getHeight()); 
         clearStack(toSave); 
         break; 
        case "String": g.drawString(f.toPrint, f.x1, f.y1); 
         break; 
       } 
      } 
     } 
    } 

    private class Figure implements Serializable 
    { 
     private static final long serialVersionUID = 4690475365105752994L; 
     String type, toPrint; 
     Color color; 
     Point start; 
     Point end; 
     int x1, y1, x2, y2, width, height; 

     public Figure(String figureType, 
      Point startPoint, Point endPoint, Color figureColor) 
     { 
      type = figureType; 
      color = figureColor; 
      start = startPoint; 
      end = endPoint; 
     } 

     // Rect, Oval 
     public Figure(String figureType, int figureX, int figureY, 
      int figureWidth, int figureHeight, Color figureColor) 
     { 
      type = figureType; 
      x1 = figureX; 
      y1 = figureY; 
      width = figureWidth; 
      height = figureHeight; 
      color = figureColor; 
     } 

     // more shapes 
    } 

    public static void main(String args[]) 
    { 
     SwingUtilities.invokeLater(new Runnable() 
     { 
      public void run() 
      { 
       new JSPaint(); 
      } 
     }); 
    } 
} 
+1

您应该使用BufferedImage来保存绘图区域,然后在调用paintComponent时使用'drawImage'将其复制到屏幕上。您不希望覆盖油漆以不清除屏幕,因为缓冲区可能会变得无效并在调用油漆之间填充其他数据。 – yiding

+2

请编辑您的问题以包含[sscce](http://sscce.org/),其中显示您调用'pack()'的位置。 – trashgod

+1

@yiding *“你应该使用BufferedImage来保存绘图区域”*一旦你有了图像,你也可以将它显示在标签中。 –

回答

0

如果当前选择的用户界面元素显示了在绘图区域,这只能有一个理由:你是在Graphics对象上做错了什么,可能调用了它们的翻译,并且在完成时不重置转换。 (请参阅this链接以获取正确使用的翻译示例)。

+0

谢谢!我从这个项目中休息了很长时间,但最终还是打算回去。如果我明白这一点,我会告诉你。 我会研究它......谢谢! – jacky