2012-04-11 41 views
6

Tôi có một lớp đơn giản vẽ một đường khi chuột kéo hoặc một dấu chấm khi chuột nhấn (nhả).Nội dung của cửa sổ biến mất khi thu nhỏ

Khi tôi thu nhỏ ứng dụng và sau đó khôi phục ứng dụng, nội dung của cửa sổ biến mất trừ dấu chấm cuối (pixel). Tôi hiểu rằng phương pháp super.paint(g) vẽ lại nền sau mỗi lần cửa sổ thay đổi, nhưng kết quả dường như giống nhau dù tôi có sử dụng hay không. Sự khác biệt giữa hai người trong số họ là khi tôi không sử dụng nó có nhiều hơn một điểm ảnh được vẽ trên cửa sổ, nhưng không phải tất cả bức tranh của tôi. Làm thế nào tôi có thể sửa lỗi này?

Đây là lớp học.

package painting; 

import java.awt.*; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionAdapter; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

class CustomCanvas extends Canvas{ 
    Point oldLocation= new Point(10, 10); 
    Point location= new Point(10, 10); 
    Dimension dimension = new Dimension(2, 2);  
    CustomCanvas(Dimension dimension){ 
     this.dimension = dimension; 
     this.init(); 
     addListeners(); 
    }  
    private void init(){      
     oldLocation= new Point(0, 0); 
     location= new Point(0, 0); 
    } 
    public void paintLine(){ 
     if ((location.x!=oldLocation.x) || (location.y!=oldLocation.y)) {   
      repaint(location.x,location.y,1,1);         
     } 
    } 
    private void addListeners(){ 
     addMouseListener(new MouseAdapter(){ 
      @Override 
      public void mousePressed(MouseEvent me){     
       oldLocation = location; 
       location = new Point(me.getX(), me.getY()); 
       paintLine(); 
      } 
      @Override 
      public void mouseReleased(MouseEvent me){     
       oldLocation = location; 
       location = new Point(me.getX(), me.getY()); 
       paintLine(); 
      } 
     }); 
     addMouseMotionListener(new MouseMotionAdapter() { 
      @Override 
      public void mouseDragged(MouseEvent me){     
       oldLocation = location; 
       location = new Point(me.getX(), me.getY()); 
       paintLine(); 
      } 
     }); 
    } 
    @Override 
    public void paint(Graphics g){ 
     super.paint(g); 
     g.setColor(Color.red);  
     g.drawLine(location.x, location.y, oldLocation.x, oldLocation.y);     
    } 
    @Override 
    public Dimension getMinimumSize() { 
     return dimension; 
    } 
    @Override 
    public Dimension getPreferredSize() { 
     return dimension; 
    } 

} 
class CustomFrame extends JPanel { 
    JPanel displayPanel = new JPanel(new BorderLayout()); 
    CustomCanvas canvas = new CustomCanvas(new Dimension(200, 200));   
    public CustomFrame(String titlu) {    
     canvas.setBackground(Color.white); 
     displayPanel.add(canvas, BorderLayout.CENTER);    
     this.add(displayPanel); 
    } 
} 
public class CustomCanvasFrame { 
    public static void main(String args[]) { 
     CustomFrame panel = new CustomFrame("Test Paint"); 
     JFrame f = new JFrame(); 
     f.add(panel); 
     f.pack(); 
     SwingConsole.run(f, 700, 700); 
    } 
} 
+0

Không kết hợp các thành phần Swing & AWT với nhau! Nếu nó không gây ra vấn đề ngay bây giờ, nó sẽ khi bạn thêm các menu, các mẹo công cụ, combo hoặc các phần tử nổi khác. Có bao nhiêu yếu tố được vẽ sẽ là điển hình cho trường hợp sử dụng này? Họ sẽ bị loại bỏ? Nếu câu trả lời cho câu hỏi thứ nhất là 'nghìn' và câu trả lời thứ hai là 'không', một 'BufferedImage' duy nhất (được hiển thị trong một nhãn) có thể là một lựa chọn tốt hơn. Một người nghe chuột có thể được thêm vào nhãn. –

+0

Re Swing/AWT. Cụ thể đó là 'Canvas' mà tôi đang đề cập đến. Đối với một Swing tương đương, mở rộng hoặc một 'JComponent' hoặc' JPanel' sau đó ghi đè 'paintComponent()' thay vì 'paint()'. BTW - hiển thị hình ảnh có nghĩa là không phải mở rộng * bất kỳ thứ gì *, và trong khi 'java.awt.Label' không hỗ trợ hình ảnh, thì' javax.swing.JLabel' sẽ không. ;) –

+0

Có, tôi đã xem qua ví dụ được tìm thấy [ở đây] (http://stackoverflow.com/questions/6132988/painting-in-a-bufferedimage-inside-swing-java) và tôi đang lập kế hoạch sử dụng một hình ảnh đệm vì tôi cũng cần phải lưu hình ảnh của tôi, nhưng cho thời điểm này tôi đang cố gắng để hiểu làm thế nào sơn và cập nhật công việc. Ví dụ, trong mã của tôi (mà tôi sẽ đăng ngay sau khi tôi tìm ra cách thức và vị trí), tôi không hiểu tại sao gọi phương thức vẽ trong bản cập nhật không giống như viết mã chính xác (từ phương pháp vẽ) trong phương thức cập nhật. –

Trả lời

5

Bạn không lưu trữ trạng thái của các điểm bạn đang vẽ. Khi bảng điều khiển được sơn lại, nó chỉ có thông tin cho điểm cuối cùng nó vẽ.


đáp ứng để bình luận:

Bạn sẽ cần phải có một bộ sưu tập các điểm, ví dụ ArrayList<Point> location = new ArrayList<Point>();

Sau đó, trong thính giả của bạn: location.add(new Point(me.getX(), me.getY()));

Cuối cùng, trong paintLine():

for (Point location : locations) { 
    repaint(location.x,location.y,1,1); 
} 

Bộ sưu tập locations thường được gọi là Danh sách Hiển thị. Hầu hết các chương trình đồ họa đều sử dụng chúng.


đáp ứng để bình luận:

Vâng, tôi hy vọng như vậy. Tôi chỉ tung ra một ý tưởng dựa trên mã của bạn để cung cấp cho bạn một điểm khởi đầu. Nó gần như chắc chắn là một ý tưởng tồi để làm chính xác như tôi đã mô tả.

+0

Điều đó không có nghĩa là tôi sẽ vẽ tất cả các điểm (thay vì một) mỗi lần tôi nhấn hoặc kéo chuột? –

+0

Có, cảm ơn ý tưởng. Nó rất hữu ích. Tôi đã thực hiện một số cải tiến đối với mã của mình và bây giờ tôi có thể vẽ điểm và đường và hình ảnh của tôi không còn biến mất nữa. Tuy nhiên, có một vấn đề khác mà tôi không nhận được. Nếu tôi thay thế mã từ phương thức cập nhật của mình bằng "paint (g)", hình ảnh của tôi sẽ nhấp nháy mỗi lần tôi thử vẽ lên. Bạn có thể giải thích cho tôi tại sao? (Uhm, tôi không chắc chắn cách đăng mã của mình ở đây.) –

+0

Tôi nghĩ bạn có thể đã biết nhiều về điều này hơn là tôi. GUI công việc thường không phải là điều của tôi. – Dave

5

Điều đó có nghĩa là tôi sẽ vẽ tất cả các điểm (thay vì một) mỗi lần tôi nhấn hoặc kéo chuột?

Có, nhưng cách tiếp cận của Dave là hoàn toàn thỏa đáng cho hàng nghìn nút, như có thể thấy trong GraphPanel. Ngoài ra, hãy xem xét flyweight pattern, như được sử dụng bởi JTable renderers và được minh họa here.

Hợp đồng bổ sung: Tập trung vào các câu hỏi AWTPainting của bạn, biến thể bên dưới có thể minh họa sự khác biệt giữa System- and App-triggered Painting. Khi chuột được kéo, repaint() gọi update(), gọi số paint(); đây là ứng dụng được kích hoạt. Khi bạn thay đổi kích thước cửa sổ, chỉ có paint() được gọi (không có số màu đỏ được vẽ); đây là hệ thống kích hoạt. Lưu ý rằng có nhấp nháy khi chuột được nhả ra sau khi thay đổi kích thước.

Nhấp nháy thường xảy ra khi nền toàn bộ thành phần của sẽ bị xóa và vẽ lại:

  4.Nếu thành phần đã làm không ghi đè update(), việc triển khai mặc định là update() sẽ xóa nền của thành phần (nếu đó không phải là thành phần nhẹ) và chỉ cần gọi paint().

AWTPainting

import java.awt.Canvas; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Frame; 
import java.awt.Graphics; 
import java.awt.Panel; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.util.ArrayList; 
import java.util.List; 

public class AWTPainting { 

    public static void main(String args[]) { 
     CustomPanel panel = new CustomPanel(); 
     Frame f = new Frame(); 
     f.addWindowListener(new WindowAdapter() { 

      @Override 
      public void windowClosing(WindowEvent e) { 
       System.exit(0); 
      } 
     }); 
     f.add(panel); 
     f.pack(); 
     f.setVisible(true); 
    } 
} 

class CustomPanel extends Panel { 

    public CustomPanel() { 
     this.add(new CustomCanvas(new Dimension(320, 240))); 
    } 
} 

class CustomCanvas extends Canvas { 

    private MouseAdapter handler = new MouseHandler(); 
    private List<Point> locations = new ArrayList<Point>(); 
    private Point sentinel = new Point(); 
    private Dimension dimension; 

    CustomCanvas(Dimension dimension) { 
     this.dimension = dimension; 
     this.setBackground(Color.white); 
     this.addMouseListener(handler); 
     this.addMouseMotionListener(handler); 
     this.locations.add(sentinel); 
    } 

    @Override 
    public void paint(Graphics g) { 
     g.setColor(Color.blue); 
     Point p1 = locations.get(0); 
     for (Point p2 : locations.subList(1, locations.size())) { 
      g.drawLine(p1.x, p1.y, p2.x, p2.y); 
      p1 = p2; 
     } 
    } 

    @Override 
    public void update(Graphics g) { 
     paint(g); 
     g.clearRect(0, getHeight() - 24, 50, 20); // to background 
     g.setColor(Color.red); 
     g.drawString(String.valueOf(locations.size()), 8, getHeight() - 8); 
    } 

    private class MouseHandler extends MouseAdapter { 

     @Override 
     public void mousePressed(MouseEvent e) { 
      if (locations.get(0) == sentinel) { // reference identity 
       locations.set(0, new Point(e.getX(), e.getY())); 
      } 
     } 

     @Override 
     public void mouseDragged(MouseEvent e) { 
      locations.add(new Point(e.getX(), e.getY())); 
      repaint(); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return dimension; 
    } 
} 
+0

Ok, tôi phải biết: lớp học công cộng này là cái quái gì! [AWTPainting] [7] {... '? – Dave

+1

Um, chỉnh sửa bất cẩn? Tôi _wondered_ nơi mà hình ảnh đầu tiên [đi] (http://stackoverflow.com/posts/10112189/revisions). :-) Tôi có ít kinh nghiệm AWT, vì vậy tôi sẽ chào đón bạn xem xét quan trọng. – trashgod

+0

Tôi đang ở trên cùng một chiếc thuyền liên quan đến AWT/Swing; Tôi có thể đi qua, nhưng tôi không thực sự là một người dùng có kinh nghiệm.Tôi hỏi về lỗi đánh máy của bạn bởi vì, nhiều năm trước, tôi đã có kinh nghiệm trong Java 1.2, nhưng sau đó kết thúc cuộc sống úp mặt xuống trong miệng núi lửa trong một thời gian khá dài. Khi tôi quay trở lại, Java đã có generics và những thứ khác khiến tôi ngạc nhiên. Tôi lo ngại rằng có lẽ điều này đã xảy ra một lần nữa và Oracle đã làm điều gì đó kỳ lạ với Java trong khi tôi đang tìm kiếm một cách khác. – Dave

2

@ Andrew, @ Dave, @trashgod Hi, tôi đã làm một số nghiên cứu về vấn đề này và cuối cùng, đây là những gì tôi đã có. Nêu tôi sai vui long chân chỉnh tôi. Bạn không thể ghi đè lên sơn() vì vậy bạn gọi repaint() mọi lúc bạn cần làm bức tranh do ứng dụng kích hoạt. Repaint() gọi update() mà hành vi mặc định của nó là gọi paint(). cập nhật() được sử dụng để vẽ tăng dần; giải thích màn hình nhấp nháy khi paint() đang thực hiện tất cả công việc, điều này thực tế có nghĩa là nó đã vẽ toàn bộ hình ảnh ở mọi bước. Tuy nhiên, câu hỏi của tôi là nếu tôi thêm "locationsAdded = 0" trong phương thức cập nhật có nghĩa là mỗi khi tôi kéo chuột, tôi vẽ toàn bộ hình ảnh (như trong sơn), vậy tại sao nó không chớp như trước? Tôi cũng đã đọc một số điều về vẽ trong xoay và tôi không hiểu tại sao update() không bao giờ được gọi cho swing. Bạn có thể giải thích cho tôi tại sao?

import java.awt.*; 
import java.awt.event.*; 
import java.util.ArrayList; 

class CustomCanvas extends Canvas{ 
    ArrayList<Point> locations;   
    int locationsAdded;  
    Point oldLocation; 
    Point location; 
    Dimension dimension; 
    CustomCanvas(Dimension dimension){ 
     locations = new ArrayList<>();   
     this.dimension = dimension; 
     this.init(); 
     addListeners(); 
    }  
    private void init(){       
     oldLocation= new Point(0, 0); 
     location= new Point(0, 0); 
    } 
    public void paintLine(Graphics g, int x){ 
     Point p1 = (Point)locations.get(x); 
     Point p2 = (Point)locations.get(x+1); 
     g.drawLine(p1.x, p1.y, p2.x, p2.y); 
     locationsAdded++; 
    } 
    @Override 
    public void paint(Graphics g){   
     locationsAdded = 0;   
     g.setColor(Color.red);     
     for(int i = locationsAdded; i < locations.size()-1; i++){ 
      paintLine(g, i); 
     }    
    } 
    public void update(Graphics g) {   
    //locationsAdded = 0; 
     for (int i = locationsAdded; i < locations.size()-1; i++) {    
      paintLine(g, i); 
     } 
    } 
    private void addListeners(){ 
     addMouseMotionListener(new MouseMotionAdapter() { 
      @Override 
      public void mouseDragged(MouseEvent me){         
       oldLocation = location; 
       location = new Point(me.getX(), me.getY()); 
       locations.add(location); 
       repaint(); 
      } 
     }); 
    } 

    @Override 
    public Dimension getMinimumSize() { 
     return dimension; 
    } 
    @Override 
    public Dimension getPreferredSize() { 
     return dimension; 
    } 
} 
class CustomFrame extends Panel { 
    Panel displayPanel = new Panel(new BorderLayout()); 
    CustomCanvas canvas = new CustomCanvas(new Dimension(700, 700));   
    public CustomFrame(String titlu) {    
     canvas.setBackground(Color.white); 
     displayPanel.add(canvas, BorderLayout.CENTER);    
     this.add(displayPanel); 
    } 
} 
public class AWTPainting { 
    public static void main(String args[]) { 
     CustomFrame panel = new CustomFrame("Test Paint"); 
     Frame f = new Frame(); 
     f.add(panel); 
     f.pack();   
     f.setSize(700,700);      
     f.show();     
    } 
} 
+0

+1 cho [sscce] (http://sscce.org/); Tôi đã xây dựng [ở đây] (http://stackoverflow.com/a/10112189/230513). – trashgod

Các vấn đề liên quan