Надеюсь, я понимаю ваш вопрос: вы пытаетесь понять, как нарисовать иконку на JButton? Взгляните на метод рисования от JComponent
(его супер супер класс). Я буду добавлять комментарии, чтобы сделать его проще объяснить:
public void paint(Graphics g) {
boolean shouldClearPaintFlags = false;
//Check the size of the component: don't draw anything with a negative width or height!
if ((getWidth() <= 0) || (getHeight() <= 0)) {
return;
}
//Create new Graphics objects (why? to create the images)
Graphics componentGraphics = getComponentGraphics(g);
Graphics co = componentGraphics.create();
try {
RepaintManager repaintManager = RepaintManager.currentManager(this);
//Initialize a RepaintManager (JavaDoc says: "This class manages repaint requests, allowing the number of repaints to be minimized")
//Create a rectangle at the size of a graphics object
Rectangle clipRect = co.getClipBounds();
int clipX;
int clipY;
int clipW;
int clipH;
//If the rectangle is null, then give it default values
if (clipRect == null) {
clipX = clipY = 0;
clipW = getWidth();
clipH = getHeight();
} else { //otherwise, use its coordinates
clipX = clipRect.x;
clipY = clipRect.y;
clipW = clipRect.width;
clipH = clipRect.height;
}
//Ajust the clip widths and heights
if(clipW > getWidth()) {
clipW = getWidth();
}
if(clipH > getHeight()) {
clipH = getHeight();
}
//If your Component is placed on a JComponent (or extended class), then make adjustments
if(getParent() != null && !(getParent() instanceof JComponent)) {
adjustPaintFlags();
shouldClearPaintFlags = true;
}
//Check if the component is printing (private flag IS_PRINTING)
int bw,bh;
boolean printing = getFlag(IS_PRINTING);
//If the component is not printing its contents, and if the repain manager is double buffered, AND if not ancestor (subclass) is buffering AND if the components is buffered....
//JavaDoc says for RepaintManager.isDoubleBufferingEnabled(): "Returns true if this RepaintManager is double buffered. The default value for this property may vary from platform to platform."
if(!printing && repaintManager.isDoubleBufferingEnabled() &&
!getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
//... then start painting the Graphics
repaintManager.beginPaint();
try {
repaintManager.paint(this, this, co, clipX, clipY, clipW, clipH);
} finally {
repaintManager.endPaint();
}
//if there is an exception, a try/finally is required to avoid the RepaintManager being "left in a state in which the screen is not updated" (JavaDoc)
}
else {
// Will ocassionaly happen in 1.2, especially when printing.
if (clipRect == null) {
co.setClip(clipX, clipY, clipW, clipH);
}
//Checks if the rectangle at the specified coordinates if obscured
if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
//Then paint the graphics (or print if printing is true)
if (!printing) {
paintComponent(co);
paintBorder(co);
} else {
printComponent(co);
printBorder(co);
}
}
//Also paint the children (eg: a JPanel has a JLabel and a JButton as children if you add them to the panel) (or print if printing is true)
if (!printing) {
paintChildren(co);
} else {
printChildren(co);
}
}
} finally {
//Clean up!!
co.dispose();
if(shouldClearPaintFlags) {
setFlag(ANCESTOR_USING_BUFFER,false);
setFlag(IS_PAINTING_TILE,false);
setFlag(IS_PRINTING,false);
setFlag(IS_PRINTING_ALL,false);
}
}
}
Других слова, есть много кода, участвующих в живописи Graphics
объектов, но шаги довольно просты, как только вы проанализировали код:
- Создать новый
Graphics
объект с переданного в параметре;
- Инициализировать RepaintManager для запросов на перерисовку;
- Проверьте, можно ли покрасить графику и по возможности сделать это;
- Завершить, перекрасив детей;
- Все готово!
Если вы хотите узнать больше о том, как применяется процесс покраски, а затем в соответствии с Oracle's Java documentation:
В Swing, картина начинается с методом краски, который затем вызывает paintComponent, paintBorder и paintChildren. Система будет ссылаться на это автоматически, когда компонент будет сначала окрашен, изменен или будет открыт после того, как будет скрыто другим окном.
Программные перекраски выполняются путем вызова метода перекраски компонента; не вызывайте его paintComponent напрямую. Вызов repaint заставляет подсистему рисования предпринять необходимые шаги для обеспечения того, чтобы ваш метод paintComponent был вызван в соответствующее время.
Вы можете вызвать repaint несколько раз из одного и того же обработчика событий, но Swing примет эту информацию и перекрасит компонент всего за одну операцию.
Для компонентов с делегатом пользовательского интерфейса вы должны передать графический параметр с строкой super.paintComponent (g) в качестве первой строки кода в вашем переопределении paintComponent. Если вы этого не сделаете, ваш компонент будет нести ответственность за ручную окраску фона. Вы можете поэкспериментировать с этим, комментируя эту строку и перекомпилируя, чтобы увидеть, что фон больше не раскрашен.
Я принял код от here. Я надеюсь, что я был в состоянии помочь вам,
Приветствия
Спасибо за ваши комментарии в коде. Это идет в сторону моего вопроса, но все же: как суперкласс (JComponent) знает, какие значки имеет подкласс (JButton), а какой из них должен быть окрашен в этот момент (т. Е. При наведении и т. Д.), ? – PeterE
Я предполагаю, что когда суперкласс добавляет подкласс (например, jpanel.add (jbutton);), он проверяет графику подкласса и сохраняет его в памяти. Ссылка http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/awt/Container.java#Container.addImpl%28java.awt.Component%2Cjava. lang.Object% 2Cint% 29 показывает, как это работает. Что касается того, когда он нарисован в нужный момент, я не уверен, мне придется заглянуть в него –
Привет, извините за задержку, я просто добавил несколько пояснений относительно того, как работают краски (и другие производные). Текст, который я публикую, берется прямо из примера, пожалуйста, просмотрите ссылку, которую я предоставил для более подробной информации. Дайте мне знать, если это имеет смысл сейчас! –