2012-04-11 16 views
6

मेरे पास एक साधारण वर्ग है जो माउस ड्रैगिंग या माउस दबाते समय एक बिंदु खींचती है (रिलीज़)।विंडो की सामग्री गायब हो जाती है जब

जब मैं एप्लिकेशन को कम करता हूं और फिर इसे पुनर्स्थापित करता हूं, तो विंडो की सामग्री अंतिम बिंदु (पिक्सेल) को छोड़कर गायब हो जाती है। मैं समझता हूं कि विधि super.paint(g) खिड़की में हर बार पृष्ठभूमि को प्रतिबिंबित करती है, लेकिन नतीजा ऐसा लगता है कि मैं इसका उपयोग करता हूं या नहीं। उनमें से दोनों के बीच का अंतर यह है कि जब मैं इसका उपयोग नहीं करता हूं तो खिड़की पर चित्रित पिक्सेल से अधिक है, लेकिन मेरी सभी पेंटिंग नहीं। मैं इसे कैसे ठीक करूं?

यहां कक्षा है।

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

स्विंग और एडब्ल्यूटी घटकों को एक साथ मिलाएं! यदि यह अभी समस्या का कारण नहीं बना रहा है, तो यह तब होगा जब आप मेनू, टूल-टिप्स, कंमोस या अन्य फ़्लोटिंग तत्व जोड़ते हैं। इस उपयोग-मामले के लिए कितने तैयार तत्व सामान्य होंगे? क्या उन्हें कभी हटा दिया जाएगा? यदि पहले का जवाब 'हजारों' है और दूसरा 'नहीं' है, तो एक 'बुफर्ड इमेज' (लेबल में प्रदर्शित) एक बेहतर विकल्प हो सकता है। एक लेबल श्रोता लेबल में जोड़ा जा सकता है। –

+0

री स्विंग/एडब्ल्यूटी। विशेष रूप से यह 'कैनवास' है जिसका मैं जिक्र कर रहा हूं। स्विंग समकक्ष के लिए, 'JComponent' या' JPanel' का विस्तार करें, फिर 'पेंट() 'के बजाय' paintComponent()' को ओवरराइड करें। बीटीडब्लू - एक छवि को प्रतिपादन का मतलब है * कुछ भी * नहीं बढ़ाना, और 'java.awt.Label' छवियों का समर्थन नहीं करता है,' javax.swing.JLabel' करता है। ;) –

+0

हां, मैं पाया गया उदाहरण देख रहा हूं [यहां] (http://stackoverflow.com/questions/6132988/painting-in-a-bufferedimage-inside-swing-java) और मैं योजना बना रहा हूं एक बफर्ड छवि का उपयोग करें क्योंकि मुझे अपनी छवियों को सहेजने की भी आवश्यकता है, लेकिन इस पल के लिए मैं समझने की कोशिश कर रहा हूं कि काम कैसे करें और अपडेट करें। उदाहरण के लिए, मेरे कोड में (जैसे ही मुझे पता चला कि मैं कैसे और कहां पोस्ट करूंगा), मुझे समझ में नहीं आता कि अद्यतन में विधि पेंट को कॉल करना बिल्कुल वही कोड लिखने जैसा नहीं है (पेंट विधि से) अद्यतन विधि में। –

उत्तर

5

आप जो अंक खींच रहे हैं उसकी स्थिति को संग्रहीत नहीं कर रहे हैं। जब पैनल को पुनर्निर्मित किया जाता है, तो इसमें केवल अंतिम बिंदु के लिए जानकारी होती है। टिप्पणी करने के लिए


प्रतिक्रिया:

आप अंक का संग्रह है, उदाहरण के लिए ArrayList<Point> location = new ArrayList<Point>();

फिर अपने श्रोताओं में है, की आवश्यकता होगी: location.add(new Point(me.getX(), me.getY()));

अंत में, paintLine() में:

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

संग्रह locations आमतौर पर एक प्रदर्शन सूची के रूप में जाना जाता है। अधिकांश ग्राफिक्स प्रोग्राम उनका उपयोग करते हैं।


रिस्पांस टिप्पणी करने के लिए:

हाँ, मैं तो उम्मीद करते हैं। मैंने आपको एक शुरुआती बिंदु देने के लिए बस अपने कोड के आधार पर एक विचार फेंक दिया। जैसा कि मैंने वर्णन किया है, वही करना लगभग निश्चित रूप से एक बुरा विचार है।

+0

इसका मतलब यह नहीं है कि जब भी मैं माउस दबाता हूं या खींचता हूं तो मैं सभी बिंदुओं (एक के बजाए) खींचूंगा? –

+0

हां, विचार के लिए धन्यवाद। यह बहुत उपयोगी रहा है। मैं अपने कोड में कुछ सुधार करने में कामयाब रहा और अब मैं अंक और रेखाएं खींच सकता हूं और मेरी छवि अब गायब नहीं होती है। हालांकि, एक और मुद्दा है जो मुझे नहीं मिलता है। अगर मैं अपने पेंट विधि से "पेंट (जी)" के साथ कोड को प्रतिस्थापित करता हूं, तो जब भी मैं इसे पेंट करने की कोशिश करता हूं तो मेरी छवि चमकती है। क्या आप मुझे समझा सकते हैं क्यों? (उहम, मुझे यकीन नहीं है कि यहां अपना कोड कैसे पोस्ट करें।) –

+0

मुझे लगता है कि आप इसके बारे में पहले से ही इसके बारे में और जान सकते हैं। जीयूआई काम आमतौर पर मेरी बात नहीं है। – Dave

5

क्या इसका मतलब यह नहीं है कि जब भी मैं माउस दबाता हूं या खींचता हूं तो क्या मैं सभी बिंदुओं (एक के बजाए) खींचूंगा?

हां, लेकिन @ डेव का दृष्टिकोण हजारों नोड्स के लिए पूरी तरह से संतोषजनक है, जैसा कि GraphPanel में देखा जा सकता है। इसके अलावा, पर विचार करें, जैसा कि JTable renderers द्वारा उपयोग किया गया है और here सचित्र किया गया है।

Addendum: AWTPainting प्रश्नों पर ध्यान केंद्रित करते हुए, नीचे भिन्नता System- and App-triggered Painting के बीच अंतर को चित्रित कर सकती है। चूंकि माउस खींचा जाता है, repaint()update() को आमंत्रित करता है, जो paint() पर कॉल करता है; यह ऐप-ट्रिगर है। जैसे ही आप विंडो का आकार बदलते हैं, केवल paint() कहा जाता है (कोई लाल संख्या खींची नहीं जाती है); यह प्रणाली-ट्रिगर है। ध्यान दें कि एक झिलमिलाहट है जब माउस आकार बदलने के बाद जारी किया जाता है।

आम तौर पर चंचल तब होता है जब पूरे घटक की पृष्ठभूमि को मंजूरी दे दी है और दोबारा बनाई:

  4।यदि घटक update() ओवरराइड करता है, तो update() का डिफ़ॉल्ट कार्यान्वयन घटक की पृष्ठभूमि को साफ़ करता है (यदि यह हल्का घटक नहीं है) और बस 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

ठीक है, मुझे पता होना है: यह 'सार्वजनिक वर्ग क्या है! [AWTPainting] [7] {... '? – Dave

+1

उम, लापरवाही संपादन? मैं _wondered_ जहां वह पहली छवि [गया] (http://stackoverflow.com/posts/10112189/revisions)। :-) मेरे पास थोड़ा एडब्ल्यूटी अनुभव है, इसलिए मैं आपको महत्वपूर्ण समीक्षा का स्वागत करता हूं। – trashgod

+0

मैं एडब्ल्यूटी/स्विंग के संबंध में एक ही नाव में हूं; मैं प्राप्त कर सकता हूं, लेकिन मैं वास्तव में एक अनुभवी उपयोगकर्ता नहीं हूं।मैंने आपके टाइपो के बारे में पूछा क्योंकि, साल पहले, मुझे जावा 1.2 में अनुभव था, लेकिन फिर कुछ समय के लिए चाँद क्रेटर में रहने वाले चेहरे को समाप्त कर दिया। जब मैं वापस आया, जावा में जेनेरिक और अन्य चीजें थीं जो मुझे आश्चर्य से ले गईं। मुझे चिंतित था कि शायद यह फिर से हुआ था और ओरेकल ने जावा के लिए कुछ अजीब किया था जबकि मैं दूसरी तरफ देख रहा था। – Dave

2

@Andrew, @Dave, @trashgod हाय, मैं इस पर कुछ शोध किया था और, अंत में, यह मैं क्या मिल गया है है। कृपया मुझे सुधारें अगर मैं गलत हूं। आप पेंट() को ओवरराइड नहीं कर सकते हैं, इसलिए जब भी आपको एप-ट्रिगर पेंटिंग करने की ज़रूरत होती है तो आप पेंटेंट() को कॉल करते हैं। पुनर्वित्त() कॉल अपडेट() जो इसका डिफ़ॉल्ट व्यवहार पेंट() को कॉल करना है। अद्यतन() वृद्धिशील चित्रकला के लिए उपयोग किया जाता है; जो झटकेदार स्क्रीन को बताता है जब पेंट() सभी काम कर रहा था, जिसका व्यावहारिक अर्थ यह है कि यह हर कदम पर पूरी छवि को चित्रित कर रहा था। हालांकि, मेरा प्रश्न यह है कि यदि मैं अद्यतन विधि में "locationsAdded = 0" जोड़ता हूं जिसका मतलब है कि हर बार जब मैं माउस खींचता हूं तो मैं पूरी छवि (पेंट की तरह) पेंट करता हूं, तो यह पहले की तरह क्यों झपकी नहीं देता है? मैंने स्विंग में पेंटिंग के बारे में कुछ भी पढ़ा है और मुझे समझ में नहीं आया कि क्यों स्विंग() स्विंग के लिए कभी नहीं बुलाया जाता है। क्या आप मुझे समझा सकते हैं क्यों?

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; मैंने विस्तारित किया है [यहां] (http://stackoverflow.com/a/10112189/230513)। – trashgod

संबंधित मुद्दे

 संबंधित मुद्दे