Почему paintComponent() никогда не вызывается repaint()?
Я работал над программой, которая рисует пользовательские JComponents на JLayeredPane, однако все вызовы repaint () для компонентов, похоже, ничего не делают, но метод paintComponent вызывается автоматически при изменении размера окна.
Я следовал некоторым советам, данным здесь: Почему paint () / paintComponent() никогда не вызывается?
Но ни одно из решений, похоже, не решает мою проблему, обновляя компоненты свинга в EDT, устанавливая размер компонента вручную перед вызовом repaint(), вызывая super.paintComponent(g) в переопределенной paintComponent() и вызывая revalidate () во фрейме после добавление новых компонентов (хотя в данном случае это явно не проблема)
Есть идеи, что может остановить звонок? Заранее спасибо:)
Вот код для представления и SVGElementContainer, view.setFile() является точкой входа, так как она вызывается, когда нужно отобразить новый документ.
public class View extends JLayeredPane implements SVGViewport {
private SVGDocument document;
//Array list of the SVGElementContainer components
private ArrayList<SVGElementContainer> elemContainers;
private SVGFrame frame;
private int elemCount;
private Border viewBorder;
private int borderWidth = 1;
//panels displayed on the JLayeredPane
private JPanel backgroundPanel;
/** Creates a new view */
public View(SVGFrame frame) {
super();
this.frame = frame;
elemCount = 0;
elemContainers = new ArrayList<SVGElementContainer>();
viewBorder = BorderFactory.createLineBorder(Color.BLACK, borderWidth);
}
public float getViewportWidth() {
return getWidth();
}
public float getViewportHeight() {
return getHeight();
}
// paints all elements and adds them to the JLayeredPane
public void paintAllElements(){
System.out.println("Painting all elements");
// Paint document
for (SVGElement elem : document) {
//only paint stylable (rect, line, circle) elements
if (elem instanceof SVGStylable){
//create a new SVGElementContainer
SVGElementContainer newElemCont = new SVGElementContainer();
//add component to JLayeredPane
elemCount++;
this.add(newElemCont, new Integer(elemCount + 1));
//set the current element within its container and calls repaint() on the component
System.out.println("Painting element #" + elemCount);
newElemCont.setElement(elem);
newElemCont.repaint();
}
else {
System.out.println("Skip painting group element!");
}
}
}
/** Gets the document currently being displayed by the view. */
public SVGDocument getDocument() {
return document;
}
/** Sets the document that the view should display.
*
* @param document the document to set
*/
public void setDocument(SVGDocument document) {
this.document = document;
//paintBackground();
paintAllElements();
revalidate();
}
public void revalidate(){
//calls validate() on the frame in order to display newly added components
frame.getContentPane().validate();
}
}
public class SVGElementContainer extends JPanel{
private SVGElement elem;
public SVGElementContainer(){
super();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("PAINT METHOD CALLED!");
paint2D((Graphics2D) g);
}
//paint the element onto this JComponent
public void paint2D(Graphics2D g){
if (!(elem instanceof SVGStylable)){
System.out.println("Skipping non-stylable element!");
return;
}
setOpaque(false);
Shape shape = elem.createShape();
// get fill stroke and width properties
SVGStylable style = (SVGStylable) elem;
SVGPaint fillPaint = style.getFill();
SVGPaint strokePaint = style.getStroke();
SVGLength strokeWidth = style.getStrokeWidth();
// Fill the interior of the shape
if (fillPaint.getPaintType() == SVGPaint.SVG_PAINTTYPE_RGBCOLOR) {
g.setPaint(fillPaint.getRGBColor());
g.fill(shape);
}
// Stroke the outline of the shape
if (strokePaint.getPaintType() == SVGPaint.SVG_PAINTTYPE_RGBCOLOR) {
Stroke stroke = new BasicStroke(strokeWidth.getValue());
g.setStroke(stroke);
g.setColor(strokePaint.getRGBColor());
g.draw(shape);
}
}
public void setElement(SVGElement elem){
this.elem = elem;
setComponentSize();
}
private void setComponentSize(){
//this.setPreferredSize(new Dimension(
// (int)elem.getDocument().getWidth().getValue(),
// (int)elem.getDocument().getHeight().getValue()));
this.setSize(new Dimension(
(int)elem.getDocument().getWidth().getValue(),
(int)elem.getDocument().getHeight().getValue()));
}
}
3 ответа
Я вижу, что вы вызываете setOpaque (false). Из setOpaque javadoc, акцент мой:
Если true, компонент закрашивает каждый пиксель в пределах своих границ. В противном случае компонент может не закрасить некоторые или все свои пиксели, что позволяет просвечивать нижележащие пиксели.
Это может быть причиной того, что paintComponent() не вызывается после первого раза во время вызова repaint(). Swing может решить, что компонент не "изменился", и, следовательно, не требует перекраски.
установка размера компонента вручную перед вызовом repaint(), вызовом super.paintComponent(g) в переопределенном paintComponent() и вызовом revalidate () во фрейме после добавления новых компонентов
Ваш код неверен в этих понятиях.
а) никогда не вызывать метод setSize(). Это работа менеджера по расположению. Вы должны предоставлять подсказки диспетчеру макета, переопределяя методы, такие как getPreferredSize(), чтобы вернуть предпочтительный размер вашего компонента
б) не переопределяйте метод revalidate (). Смысл этого совета в том, чтобы использовать такой код:
panel.add( .... );
panel.revalidate();
panel.repaint();
Но я действительно не знаю, что должен делать весь ваш код, поэтому я не могу точно сказать, имеет ли ваш код смысл. Мне также кажется странным, что вы расширяете JLayeredPane.
Я могу видеть расширение JPanel
получить буфер и делегировать пользовательский интерфейс, но непрозрачность зависит от L&F. Вместо этого вам, вероятно, следует начать с JComponent
и реализовать EventListenerList
сантехника для вашего (гипотетического) SVGEvent
,