Неправильные линии, нарисованные на JPanel

#java #xfdl

#java #xfdl

Вопрос:

Я разрабатываю приложение для рендеринга XFDL на Java. XFDL — это язык определения формы, который является расширением XML.

Класс рендеринга использует StAX для обработки документа и добавляет необходимые элементы в настроенную JPanel для отображения. Мне удалось правильно добавить поля (JTextFields) и метки (JLabels) к строкам JPanel, что стало проблемой. При создании формы с несколькими страницами, когда я когда-либо отображаю форму, каждая страница получает строки последней страницы в форме.

Я просмотрел свой код (показан ниже) и не могу найти причину такого поведения. Когда я выполняю переход, все счетчики увеличиваются правильно, так что строки добавляются на соответствующие страницы, но я всегда получаю последнюю страницу строк за текущей страницей меток и полей.

Я подозреваю, что я что-то неправильно понял в том, как Java обрабатывает рисование, но я не уверен, что именно.

Заранее спасибо за ответы и советы.

В документе XFDL строки определены как таковые:

 <page SID="PAGE1">
      <line sid="LINE1">
         <itemlocation>
            <ae>
               <ae>absolute</ae>
               <ae>1219</ae>
               <ae>75</ae>
            </ae>
            <ae>
               <ae>extent</ae>
               <ae>3</ae>
               <ae>854</ae>
            </ae>
         </itemlocation>
      </line>
      ...
</page>
<page SID="PAGE2">
      <line sid="LINE2">
         <itemlocation>
            <ae>
               <ae>absolute</ae>
               <ae>1219</ae>
               <ae>75</ae>
            </ae>
            <ae>
               <ae>extent</ae>
               <ae>3</ae>
               <ae>854</ae>
            </ae>
         </itemlocation>
      </line>
      ...
</page>
  

Когда класс визуализации достигает тега, вызывается следующий метод:

 private ArrayList<FormPanel> pages;

/**
 * Draws a new line on the Panel
 * 
 * Start State: Cursor is positioned on the <line> start element.
 * End State: Cursor is positioned on the <line> end element.
 * 
 * @throws XMLStreamException 
 */
private void addLine() throws XMLStreamException {
    while(reader.hasNext() amp;amp;
            !(reader.isEndElement() amp;amp; 
                    reader.getLocalName().equals(XFDL_LINE))) {

        reader.next();
        if(reader.isStartElement()) {
            if(reader.getLocalName().equals(XFDL_ITEMLOCATION)) {
                pages.get(currentPage).addLine(processItemLocation());
            }
        }
    }

}

/**
 * Processes an item location field into a Rectangle object used to set
 * the bounds and location of form item.
 * Start State: Cursor positioned on the itemlocation start element.
 * End State: Cursor positioned on the itemlocation end element
 * 
 * Currently only handles absolute positioning and extent sizes.
 * Any other form of positioning data returns null.
 * 
 * @return Rectangle representing the location and size of item.
 * @throws XMLStreamException 
 */
private Rectangle processItemLocation() throws XMLStreamException {
    Rectangle result = new Rectangle();

    ArrayList<String> attributes = new ArrayList<String>();

    while(reader.hasNext() amp;amp;
            !(reader.isEndElement() amp;amp; 
                    reader.getLocalName().equals(XFDL_ITEMLOCATION)))
    {
        reader.next();
        if(reader.isCharacters() amp;amp; !reader.isWhiteSpace()) {
            attributes.add(reader.getText());
        }
    }

    for(int x=0; x<attributes.size(); x  ) {
        if(attributes.get(x).equals(XFDL_LOCATION_STYLE_ABSOLUTE)) {
            result.setLocation(Integer.parseInt(attributes.get(x 1)),
                    Integer.parseInt(attributes.get(x 2)));
        } else if(attributes.get(x).equals(XFDL_LOCATION_SIZE_EXTENT)) {
            result.setSize(Integer.parseInt(attributes.get(x 1)),
                    Integer.parseInt(attributes.get(x 2)));
        } else {
            try{
                Integer.parseInt(attributes.get(x));
            } catch (NumberFormatException nfe) {
                result = null;
                x = attributes.size();
            }
        }
    }

    return resu<
}
  

FormPanel является расширением JPanel с дополнительным методом AddLine() и переопределенным paintComponent(), показанным ниже:

 private static ArrayList<Rectangle> lines;

public void addLine(Rectangle line) {
    lines.add(line);
}

/**
 * Overrides JPanel paintComponenet and draws lines on the form.
 */
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    for(int x = 0; x<lines.size(); x  ) {
        g.drawRect(lines.get(x).x, 
                lines.get(x).y, 
                lines.get(x).width, 
                lines.get(x).height);
        g.fillRect(lines.get(x).x, 
                lines.get(x).y, 
                lines.get(x).width, 
                lines.get(x).height);
    }
}
  

Комментарии:

1. используете ли вы CardLayout для отображения различных страниц или что-то в этом роде, или каждая страница находится чуть ниже предыдущей страницы по вертикали?

Ответ №1:

Казалось бы, когда вы заходите на новую страницу, вы должны вызвать

 lines.clear();
  

Предполагая, что каждая страница находится в своем собственном контейнере.

Конечно, переменная lines определена как статическая, поэтому у вас есть один контейнер lines для всего документа. Можно подумать, что вы хотите по одной на страницу, поэтому использование static кажется сомнительным.

Комментарии:

1. Я даже не помню, чтобы писал статический модификатор в lines ArrayList. Удалил его, и все встало на свои места.