Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Написание swing-компонента


Автор: Dude03 24.4.2007, 12:42
Собственно сабж. Захотелось реализовать свой компонент... Начал с исходников классов jdk(JLabel, JTextField ну и так далее). Но что-то тяжковато разбиратся - что, куда и зачем. Можете покинуть линков, чтобы легче было(мне) smile 

Автор: fixxer 24.4.2007, 13:17
Какого рода компонент? На основе существующих или с кастомной отрисовкой?

В первом случае лучше наследоваться от JPanel, во втором или от JPanel или от JComponent и перекрывать paintComponent(Graphics)

Автор: RebornCrusader 26.4.2007, 04:00
Цитата(fixxer @  24.4.2007,  21:17 Найти цитируемый пост)
перекрывать paintComponent(Graphics)

Всю жизнь переопределял paint(Graphics). И вот почему:

Цитата из JavaDoc для paint():
Цитата

This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren.


Т. е.  если мы полностью хотим самостоятельно рисовать компонент, и должны перекрыть сам paint(). А в твоём случае система рисует ещё и рамку с дитями, что, как правило, для самодельных компонентов излишне. 

Также следует иметь в виду, что передаваемый графический контекс в paintComponent() нельзя изменять:
Цитата

If you override this in a subclass you should not make permanent changes to the passed in Graphics. For example, you should not alter the clip Rectangle or modify the transform. If you need to do these operations you may find it easier to create a new Graphics from the passed in Graphics and manipulate it.

Автор: fixxer 26.4.2007, 07:08
Цитата

Т. е.  если мы полностью хотим самостоятельно рисовать компонент, и должны перекрыть сам paint(). А в твоём случае система рисует ещё и рамку с дитями, что, как правило, для самодельных компонентов излишне. 


Ну на вкус и цвет все фломастеры разные.

Цитата

If you override this in a subclass you should not make permanent changes to the passed in Graphics. For example, you should not alter the clip Rectangle or modify the transform. If you need to do these operations you may find it easier to create a new Graphics from the passed in Graphics and manipulate it.


А вот это легко обходится.

Код

AffineTransform oldTransform = g2.getTransform();
g2.setTransform(...);
g2.draw(...);
g2.setTransform(oldTransform);


Ну или даже, как и написано g.create(...)

Автор: powerOn 26.4.2007, 19:13
Переопределения методов paint() и paintComponent() имеют свои особенности, что парой имеет большое значение.
Например метод paint() вызывается после того, как были прорисованы дочерние компоненты, а метод paintComponent - до. Если вы хотите порисовать некий собственный фон для вашего компонента-контейнера, то нужно делать это в методе paintComponent(), тогда все дочерние компоненты окажутся "на фоне". А если, к примеру, вы реализуете функциональность группового  выделения мышью, при котором должен рисоваться прозрачный прямоугольник (тот что показывает область выделения) поверх компонентов, то следует его рисовать в методе paint().

Автор: RebornCrusader 27.4.2007, 01:50
"Дико извиняюсь", но...
Цитата(powerOn @  27.4.2007,  03:13 Найти цитируемый пост)
Например метод paint() вызывается после того, как были прорисованы дочерние компоненты, а метод paintComponent - до

Что-то странное. Это откуда информация? Поверхностный просмотр javadocов, исходников и книжки Портянкина (в частности, стр. 113) такого не выявляет. Да, рисуется сам компонент, затем дети - это и так очевидно. Но выглядит это так: 
Цитата

(очень грубая схема)

paint() {
paintComponent()
paintBorder()
paintChildren()
}

Перекрывая paint(), мы убиваем весь этот механизм и рисуем полностью сами.

P.S. super.paint(), конечно, имеет смысл вызывать именно первым (если вообще вызывать).

Автор: powerOn 27.4.2007, 17:01
Главное в каком порядке отрабатывает наш код, а не код супер класса.

Я имел ввиду перекрытие с вызовом метода super.paint() и super.paintComponent(), как вы и сказали, на первом месте. Вообще методы суперкласса полезно вызывать, хотя и никто не заставляет. Но не делая этого, логика работы конечно же будет нарушена.

При таком подходе, бизнес нагрузка переопределенных методов будет срабатывать в несколько ином порядке. Т.е. я имет ввиду порядок, при котором метод полностью отработает. Кстати, ваша схема прекрасно это отображает.
Цитата

paint() {
paintComponent()
// paintComponent() завершился. Значит и наш (переопределенный в потомке) метод paintComponent() завершился - т.е. отработал первым.
paintBorder()
// paintBorder() завершился.
paintChildren()
// paintChildren() завершился.
}
paint() завершился. Отработал последним, хоть и дернули его первым.



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)