Drawing in JPanel disappears when scrolling or res

2019-09-13 15:21发布

问题:

I have a big problem that I can't solve it I have a JPanel in a JFrame. In this panel I draw many things (like a diagram) it works, but when I scroll the panel or when I resize the frame the drawings disappears!

How should I get the drawing to remain?

The code:

  private void full_simulation_button(java.awt.event.ActionEvent evt) {

   if (jTextField1.getText().equals("")){
  JOptionPane jop2 = new JOptionPane();
  jop2.showMessageDialog(null, "You should enter you trace file !",         "Attention", JOptionPane.WARNING_MESSAGE);
   }
   else {

  Graphics g = jPanel5.getGraphics();  

g.setColor(Color.RED);
g.drawRect(150,10,100,20);  
g.fillRect(150,10,100,20);
g.drawLine(200,10 , 200, 2000);
g.setColor(Color.BLACK);
g.drawString("UE",190 ,25 );

g.setColor(Color.BLUE); 
g.drawRect(350,10,100,20); 
g.fillRect(350,10,100,20);
g.drawLine(400,10 , 400, 2000);
g.setColor(Color.BLACK);
g.drawString("Node B",380 ,25 );

 g.setColor(Color.GREEN);
g.drawRect(550,10,100,20);    
g.fillRect(550,10,100,20);
g.drawLine(600,10 , 600, 2000);
g.setColor(Color.BLACK);
g.drawString("RNC",590 ,25 );

g.setColor(Color.YELLOW); 
g.drawRect(750,10,100,20);    
g.fillRect(750,10,100,20);
g.drawLine(800,10 , 800, 2000);
g.setColor(Color.BLACK);
g.drawString("CN",790 ,25 );

System.out.println(new java.io.File("").getAbsolutePath());
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
try {
     final DocumentBuilder builder = factory.newDocumentBuilder();      
     final Document document= builder.parse(new File(jTextField1.getText()));
     //Affiche la version de XML
     System.out.println("la version du XML est "+ document.getXmlVersion());
    //Affiche l'encodage
    System.out.println("l'encodage utilisé est"+document.getXmlEncoding()); 
    //Affiche s'il s'agit d'un document standalone      
    System.out.println("le document est standolone:"+document.getXmlStandalone());

    final Element racine = document.getDocumentElement();
    System.out.println("le racime du fichier est :"+racine.getNodeName());

    final NodeList racineNoeuds = racine.getChildNodes();

    final int nbRacineNoeuds = racineNoeuds.getLength();

    for (int i = 0; i<nbRacineNoeuds; i++) {
          if(racineNoeuds.item(i).getNodeType() == Node.ELEMENT_NODE) {
                 final Element nd = (Element) racineNoeuds.item(i);
                 final Node noeud = racineNoeuds.item(i);
                 System.out.println(noeud.getNodeName());



    final NodeList msg = nd.getElementsByTagName("PARA");
    final int nbre = msg.getLength();
    int marge=0;
    int rang =1;
    String type =null;
    String direction=null;
    for(int j = 0; j<nbre ; j++){

        final Element message = (Element) msg.item(j);


        g.setColor(Color.BLACK);
        if ( message.getAttribute("name").equals("Message Type")){ 
        type = message.getAttribute("value");
       // System.out.println(type);
        if (type.startsWith("RRC")){

          g.drawLine(200,50+marge , 600, 50+marge);
          g.drawString(rang+". "+type,220 ,45+marge );
          marge=marge+30;
          rang=rang+1; 
         }
        if (type.startsWith("NBAP")){
          g.drawLine(400,50+marge , 600, 50+marge);
          g.drawString(rang+". "+type,420 ,45+marge );
          marge=marge+30;
          rang=rang+1; 

         }
        if (type.startsWith("RANAP")){
            g.drawLine(600,50+marge , 800, 50+marge);
            g.drawString(rang+". "+type,620 ,45+marge );
            marge=marge+30;
            rang=rang+1; 

         }
        }
        if ( message.getAttribute("name").equals("Message Direction")){ 
        direction = message.getAttribute("value");
        //System.out.println(direction);
        if ((direction.equals("From-UE"))&&(type.startsWith("RRC"))){
          g.drawString(">",595, 50+marge-25 );
          System.out.println(type);

         }
        if ((direction.equals("To-UE"))&&(type.startsWith("RRC"))){
          g.drawString("<",200, 50+marge-25 );
          System.out.println(type);

         }
        if ((direction.equals("From-NodeB"))&&(type.startsWith("NBAP"))){
          g.drawString(">",595, 50+marge-25 );
          System.out.println(type);

         }
        if ((direction.equals("To-NodeB"))&&(type.startsWith("NBAP"))){
          g.drawString("<",400, 50+marge-25 );
          System.out.println(type);

         }
        if ((direction.equals("From-CN"))&&(type.startsWith("RANAP"))){
          g.drawString("<",600, 50+marge-25 );
          System.out.println(type);

         }
        if ((direction.equals("To-CN"))&&(type.startsWith("RANAP"))){
          g.drawString(">",795, 50+marge-25 );
          System.out.println(type);

         }
  }

}
         }   

}

}

        catch (final ParserConfigurationException e) {
         e.printStackTrace();
            }
        catch (final SAXException e) {
          e.printStackTrace();
           }
       catch (final IOException e) {
        e.printStackTrace();
         }
           }
          }                                       

回答1:

You should never paint outside of the provided swing functions like paintComponent(Graphics g). When resizing or scrolling the component will be repainted. In this process the paintComponent method of every involved component is called. Since your drawing happens outside of it, the panel is not redrawn as intended. Override the paintComponent method and copy all your drawing code into it.

class MyPanel extends JPanel
{
    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.drawRect(150,10,100,20);  
        g.fillRect(150,10,100,20);
        g.drawLine(200,10 , 200, 2000);
        g.setColor(Color.BLACK);
        g.drawString("UE",190 ,25 );
        /* ... All drawing code ... */
    }
}


回答2:

Each time you resize you component or move it in a scrollpane, it is redrawn. It's the way Swing works. If you want you panel to be able to redraw its content, it has to know about it. In this kind of situation, you should create a new class that extends the JComponent class and override the paintComponent(Graphics) method. It's this method that will be responsible to draw your diagram.

public class Drawer extends JComponent {

    private File source;

    public void setSource(File source) {
        this.source = source;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        if (source == null) {
            return;
        }
        g.setColor(Color.RED);
        g.drawRect(150, 10, 100, 20);
        g.fillRect(150, 10, 100, 20);
        g.drawLine(200, 10, 200, 2000);
        g.setColor(Color.BLACK);
        g.drawString("UE", 190, 25);

        g.setColor(Color.BLUE);
        g.drawRect(350, 10, 100, 20);
        g.fillRect(350, 10, 100, 20);
        g.drawLine(400, 10, 400, 2000);
        g.setColor(Color.BLACK);
        g.drawString("Node B", 380, 25);

        g.setColor(Color.GREEN);
        g.drawRect(550, 10, 100, 20);
        g.fillRect(550, 10, 100, 20);
        g.drawLine(600, 10, 600, 2000);
        g.setColor(Color.BLACK);
        g.drawString("RNC", 590, 25);

        g.setColor(Color.YELLOW);
        g.drawRect(750, 10, 100, 20);
        g.fillRect(750, 10, 100, 20);
        g.drawLine(800, 10, 800, 2000);
        g.setColor(Color.BLACK);
        g.drawString("CN", 790, 25);

        System.out.println(new java.io.File("").getAbsolutePath());
        final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        try {
            final DocumentBuilder builder = factory.newDocumentBuilder();
            final Document document = builder.parse(source);


        } catch (final ParserConfigurationException e) {
            e.printStackTrace();
        } catch (final SAXException e) {
            e.printStackTrace();
        } catch (final IOException e) {
            e.printStackTrace();
        }

    }
}

Replace your JPanel by an instance of the Drawer class and replace the content of the listener method by:

private void full_simulation_button(java.awt.event.ActionEvent evt) {                                        

    if (jTextField1.getText().isEmpty()) {
        JOptionPane.showMessageDialog(null, "You should enter you trace file !", "Attention", JOptionPane.WARNING_MESSAGE);
    } else {
        drawer.setSource(new File(jTextField1.getText()));
    }
}

When the user clicks the button, a file is created and is given as the source of the Drawer. The Drawer repaints itself and the paintComponent() method is called by the internal mechanism of Swing.

Now you should try to improve the code by not parsing the XML file each time the paintComponent() method is called (you parse it in the setSource() and then you use the data in the paintComponent()).