Swing: почему не перекрашивается мой пользовательский компонент? - PullRequest
1 голос
/ 12 апреля 2009

Элемент простой модели класса.

ItemComponent - это вид для Предмета, который просто рисует простые прямоугольники в заданном месте. Куча экземпляров ItemComponent помещается в родительский компонент, который добавляется в JFrame приложения (сейчас это просто оболочка).

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

Проблема в том, насколько я могу судить ... paint () вызывается только один раз. repaint (), кажется, не имеет никакого эффекта.

Что не так?

Я не программист на Swing и собрал все это на примерах, поэтому я ожидаю, что здесь может быть что-то тривиальное, я не понимаю.

public class ItemComponent extends JComponent implements ItemView {

    private static final Color COLOR_FILL_NORMAL = new Color(0x008080ff);
    private static final Color COLOR_FILL_TARGET = Color.LIGHT_GRAY;
    private static final Color COLOR_OUTLINE = new Color(0x00333333);

    Item item;
    RoundRectangle2D rect;
    State state = State.NORMAL;
    float alpha = 1.0f;

    public ItemComponent(Item item) {
        this.item = item;
        this.rect = new RoundRectangle2D.Double(0, 0, 0, 0, 5, 5);
        item.setView(this);
    }

    public void setState(State state) {
        this.state = state;
    }

    public void update() {
        System.out.println("ItemComponent.update");
        setLocation(item.getLeft(), 1);
        setSize(item.getWidth(), getParent().getHeight()-1);
        rect.setRoundRect(0, 0, getWidth()-1, getHeight()-1, 5, 5);

        repaint();
        //paintImmediately(getBounds());
    }

    @Override
    public void addNotify() {
        update();
    }

    @Override
    public void paint(Graphics g) {
        System.out.println("paint");

        Graphics2D g2 = (Graphics2D)g;

        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));

        if (state == State.NORMAL) {
            System.out.println("draw normal");
            g2.setPaint(COLOR_FILL_NORMAL); // light blue
            g2.fill(rect);

            g2.setPaint(COLOR_OUTLINE);
            g2.draw(rect);
        }
        else if (state == State.TARGET) {
            System.out.println("draw target");
            g2.setPaint(COLOR_FILL_TARGET);
            g2.fill(rect);

            float[] dashPattern = { 8, 5 };
            g2.setStroke(new BasicStroke(2, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, dashPattern, 0));
            g.setColor(COLOR_OUTLINE);
            g2.draw(rect);
        }
    }
}

Совет: Я проследил в repaint () и нашел точку, где проверяется isDisplayable (), и он возвращает false. Это гарантирует, что getPeer ()! = Null.

То есть мой компонент не имеет аналогов? Что с этим? Он был добавлен в контейнер, который сам добавляется в остальную часть приложения. И он один раз раскрашивается, так что я знаю, что он виден.

Ответы [ 3 ]

2 голосов
/ 12 апреля 2009

Мои извинения людям, которые уже смотрели на это. Я немного урезал код для публикации и нечаянно пропустил ключевую часть:

@Override
public void addNotify() {
    update();
}

Я использовал это, чтобы выполнить настройку, как только она была добавлена. Оказывается, очень важно, чтобы вы не переопределяли это, или, по крайней мере, вам нужно вызвать super.addNotify (), иначе не произойдет целая куча важных инициализаций.

Изменение на это решило проблему:

@Override
public void addNotify() {
    super.addNotify();
    update();
}
1 голос
/ 12 апреля 2009

Ответ где-то здесь . В частности, раздел Живопись на качелях . Я озадачен тем, что перемещение кода рендеринга в paintComponent () не сработало, как это было предложено Йоханнесом Ресселем. Как там написано в документации ..

Методы рисования

Правила, которые применяются к AWT легкие компоненты также применяются к Компоненты Swing - например, Paint () вызывается, когда пришло время рендер - разве что качай дальше факторы краски () называют три отдельные методы, которые вызываются в следующий порядок:

protected void paintComponent(Graphics g)
protected void paintBorder(Graphics g)
protected void paintChildren(Graphics g)

Программы Swing должны переопределять paintComponent () вместо переопределения краска ().

0 голосов
/ 15 апреля 2009

Вы хотели бы позвонить repaint(), чтобы заставить JComponent перекрашиваться вместо обновления.

Вместо переопределения paint( Graphics g ), вместо переопределения paintComponent( Graphics g ) и поместите ваш собственный код рендеринга в.

Обязательно вызовите super.paintComponent( g ) в качестве первой строки переопределенного метода, потому что происходит некоторая инициализация ключа.

Также важно отметить, что в зависимости от LayoutManager контейнера, к которому добавляется ваш ItemComponent, может потребоваться установить размер явно. Я вижу, вы пытаетесь сделать это в методе update (). Вам нужно только один раз установить размер, возможно, лучше всего поместить его в код, который создает ваш компонент и добавляет его в контейнер.

Для того, что вы пытаетесь сделать, необходимо только переопределить paintComponent (). Вы должны удалить все другие переопределенные методы.

Звоните repaint() с setState(). Если размер компонента зависит от переданного состояния, вы можете вызвать setSize() непосредственно перед repaint().

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...