На JPanel нарисованы неправильные линии
Я занимаюсь разработкой приложения для визуализации 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() &&
!(reader.isEndElement() &&
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() &&
!(reader.isEndElement() &&
reader.getLocalName().equals(XFDL_ITEMLOCATION)))
{
reader.next();
if(reader.isCharacters() && !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 result;
}
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 ответ
Казалось бы, когда вы входите на новую страницу, вы должны позвонить
lines.clear();
Предполагая, что каждая страница находится в своем собственном контейнере.
Конечно, переменная lines определяется как статическая, поэтому у вас есть один контейнер строк для всего документа. Можно подумать, что вы хотите по одному на страницу, поэтому использование статики кажется сомнительным.