【问题标题】:Drawing in JPanel disappears when scrolling or ressizing the frame滚动或调整框架大小时,JPanel 中的绘图消失
【发布时间】:2015-04-24 20:11:15
【问题描述】:

我有一个无法解决的大问题我在JFrame 中有一个JPanel。在这个面板中,我画了很多东西(比如图表),它可以工作,但是当我滚动面板或调整框架大小时,图纸会消失!

我应该如何让图纸保留下来?

代码:

  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();
         }
           }
          }                                       

【问题讨论】:

  • Graphics g = jPanel5.getGraphics(); 这就是问题的根源。组件应在被请求时进行绘制。有关正确方法的详细信息,请参阅本教程的Performing Custom Painting 课程。

标签: java swing jpanel awt java-2d


【解决方案1】:

你不应该在paintComponent(Graphics g)等提供的swing函数之外进行绘画。调整大小或滚动组件时,将重新绘制。在这个过程中,每个相关组件的paintComponent 方法都会被调用。由于您的绘图发生在它之外,因此面板不会按预期重绘。覆盖paintComponent 方法并将所有绘图代码复制到其中。

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 ... */
    }
}

【讨论】:

  • 请告诉我我在哪里添加了这段代码(class MyPanel extends JPanel { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); 这是我第一次用 java 进行开发跨度>
  • 把它放在jPanel5的代码中。在full_simulation_button方法中,调用jPanel5.repaint()..
  • 现在我什么都没有了 :(
  • 1+,通过覆盖 paintComponent() 自定义绘画是要走的路。您还需要覆盖getPreferredSize() 方法以返回面板可以正确显示的大小。阅读 Custom Painting 上的 Swing 教程中的部分,了解更多信息和工作示例,您可以通过玩来学习基础知识。
【解决方案2】:

每次调整组件大小或在滚动窗格中移动它时,都会重新绘制它。这就是 Swing 的工作方式。如果你想让你的面板能够重绘它的内容,它必须知道它。 在这种情况下,您应该创建一个扩展JComponent 类的新类并覆盖paintComponent(Graphics) 方法。正是这种方法将负责绘制您的图表。

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();
        }

    }
}

将您的 JPanel 替换为 Drawer 类的实例,并将侦听器方法的内容替换为:

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()));
    }
}

当用户单击按钮时,会创建一个文件并作为Drawer 的来源。 Drawer 重绘自身,paintComponent() 方法由 Swing 的内部机制调用。

现在您应该尝试通过在每次调用 paintComponent() 方法时不解析 XML 文件来改进代码(您在 setSource() 中解析它,然后使用 paintComponent() 中的数据)。

【讨论】:

  • final Document document = builder.parse(source); 这不是任何paint..(Graphics) 方法中应该存在的(可能长时间运行的)任务类型。当然不是每次都会调用该方法!相反,您可以将final Document document 声明为(非最终)类属性并在setSource 方法中进行解析(尽管这可能会在逻辑上将方法名称更改为..parseSource?)。
  • 这是我在帖子末尾解释的内容。他应该改进课程以避免在每次调用时解析文件。但是读了最后一句话,我发现它并不清楚。我把它改得更精确了。
  • 我的图纸与文件解析成比例的问题我无法将它们分开:(
  • 正如 Andrew Thompson 所说,您可以将 Document 实例保留为类的成员。您在调用setSource 时进行解析,它会创建一个Document,在paintComponent 方法中,您读取文档以进行绘制。
  • 另一种解决方案是在解析时在 BufferedImage 中绘制并在 paintComponent() 方法中绘制图像。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 1970-01-01
  • 2012-06-26
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多