Как работает paintComponent?
Это может быть очень нубский вопрос. Я только начинаю изучать Java
Я не понимаю работу метода paintComponent. Я знаю, что если я хочу что-то нарисовать, я должен переопределить метод paintComponent.
public void paintComponent(Graphics g)
{
...
}
но когда это называется? Я никогда не вижу ничего подобного "объекту.paintComponent (g)" но все же он рисуется при запуске программы.
а что такое графический параметр? Откуда он взялся? Параметр должен быть указан, когда вызывается метод. Но, как я уже говорил, похоже, что этот метод никогда не вызывается явно. Так кто же предоставляет этот параметр? И почему мы должны бросить его в Graphics2D?
public void paintComponent(Graphics g)
{
...
Graphics2D g2= (Graphics2D) g;
...
}
4 ответа:
(очень) короткий ответ на ваш вопрос заключается в том, что
paintComponent
называется "когда это нужно."Иногда легче думать о системе Java Swing GUI как о "черном ящике", где большая часть внутренних элементов обрабатывается без слишком большой видимости.существует ряд факторов, которые определяют, когда компонент должен быть перекрашен, начиная от перемещения, изменения размера, изменения фокуса, скрытия другими кадрами и так далее и так далее. Многие из этих событий обнаружены авто-магически, и
paintComponent
называется внутренне, когда определено, что эта операция необходима.Я работал с Swing в течение многих лет, и я не думаю, что я когда-нибудь под названием
paintComponent
непосредственно, или даже видел, что он вызван непосредственно из чего-то другого. Ближе всего я пришел с помощьюrepaint()
методы для программного запуска перерисовки определенных компонентов (которые я предполагаю, вызывает правильныйpaintComponent
методы вниз по течению.в моем опыт,
paintComponent
редко переопределяется напрямую. Я признаю, что существуют пользовательские задачи рендеринга, требующие такой детализации, но Java Swing предлагает (довольно) надежный набор J-компонентов и макетов, которые можно использовать для выполнения большей части тяжелой работы без необходимости прямого переопределенияpaintComponent
. Я думаю, что моя точка зрения здесь заключается в том, чтобы убедиться, что вы не можете что-то сделать с собственными J-компонентами и макетами, прежде чем вы попытаетесь свернуть свои собственные пользовательские компоненты.
две вещи, которые вы можете сделать здесь:
- читать живопись в AWT и Swing
- используйте отладчик и поместите точку останова в метод paintComponent. Затем пройдите вверх по stacktrace и посмотрите, как предоставляет графический параметр.
просто для информации, вот stacktrace, который я получил из примера кода, который я опубликовал в конце:
Thread [AWT-EventQueue-0] (Suspended (breakpoint at line 15 in TestPaint)) TestPaint.paintComponent(Graphics) line: 15 TestPaint(JComponent).paint(Graphics) line: 1054 JPanel(JComponent).paintChildren(Graphics) line: 887 JPanel(JComponent).paint(Graphics) line: 1063 JLayeredPane(JComponent).paintChildren(Graphics) line: 887 JLayeredPane(JComponent).paint(Graphics) line: 1063 JLayeredPane.paint(Graphics) line: 585 JRootPane(JComponent).paintChildren(Graphics) line: 887 JRootPane(JComponent).paintToOffscreen(Graphics, int, int, int, int, int, int) line: 5228 RepaintManager$PaintManager.paintDoubleBuffered(JComponent, Image, Graphics, int, int, int, int) line: 1482 RepaintManager$PaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1413 RepaintManager.paint(JComponent, JComponent, Graphics, int, int, int, int) line: 1206 JRootPane(JComponent).paint(Graphics) line: 1040 GraphicsCallback$PaintCallback.run(Component, Graphics) line: 39 GraphicsCallback$PaintCallback(SunGraphicsCallback).runOneComponent(Component, Rectangle, Graphics, Shape, int) line: 78 GraphicsCallback$PaintCallback(SunGraphicsCallback).runComponents(Component[], Graphics, int) line: 115 JFrame(Container).paint(Graphics) line: 1967 JFrame(Window).paint(Graphics) line: 3867 RepaintManager.paintDirtyRegions(Map<Component,Rectangle>) line: 781 RepaintManager.paintDirtyRegions() line: 728 RepaintManager.prePaintDirtyRegions() line: 677 RepaintManager.access0(RepaintManager) line: 59 RepaintManager$ProcessingRunnable.run() line: 1621 InvocationEvent.dispatch() line: 251 EventQueue.dispatchEventImpl(AWTEvent, Object) line: 705 EventQueue.access0(EventQueue, AWTEvent, Object) line: 101 EventQueue.run() line: 666 EventQueue.run() line: 664 AccessController.doPrivileged(PrivilegedAction<T>, AccessControlContext) line: not available [native method] ProtectionDomain.doIntersectionPrivilege(PrivilegedAction<T>, AccessControlContext, AccessControlContext) line: 76 EventQueue.dispatchEvent(AWTEvent) line: 675 EventDispatchThread.pumpOneEventForFilters(int) line: 211 EventDispatchThread.pumpEventsForFilter(int, Conditional, EventFilter) line: 128 EventDispatchThread.pumpEventsForHierarchy(int, Conditional, Component) line: 117 EventDispatchThread.pumpEvents(int, Conditional) line: 113 EventDispatchThread.pumpEvents(Conditional) line: 105 EventDispatchThread.run() line: 90
графики, параметр приходит от здесь:
RepaintManager.paintDirtyRegions(Map) line: 781
фрагмент участвует в следующем:
Graphics g = JComponent.safelyGetGraphics( dirtyComponent, dirtyComponent); // If the Graphics goes away, it means someone disposed of // the window, don't do anything. if (g != null) { g.setClip(rect.x, rect.y, rect.width, rect.height); try { dirtyComponent.paint(g); // This will eventually call paintComponent() } finally { g.dispose(); } }
если вы посмотрите на него, вы увидите, что он извлекает графику из самого JComponent (косвенно с
javax.swing.JComponent.safelyGetGraphics(Component, Component)
), который сам берет его в конечном итоге из своего первого "тяжелого родителя" (обрезанного до границ компонента), который он сам берет его из своего соответствующего собственного ресурса.относительно того, что вы должны бросить
Graphics
доGraphics2D
, это просто происходит что при работе с window Toolkit, тоGraphics
на самом деле выходитGraphics2D
, но вы могли бы использовать другиеGraphics
которые "не должны" расширяетсяGraphics2D
(это происходит не очень часто, но AWT/Swing позволяет вам это делать).import java.awt.Color; import java.awt.Graphics; import javax.swing.JFrame; import javax.swing.JPanel; class TestPaint extends JPanel { public TestPaint() { setBackground(Color.WHITE); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); g.drawOval(0, 0, getWidth(), getHeight()); } public static void main(String[] args) { JFrame jFrame = new JFrame(); jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jFrame.setSize(300, 300); jFrame.add(new TestPaint()); jFrame.setVisible(true); } }
внутреннее устройство графического интерфейса пользователя системы вызова этого метода, и они проходят в
Graphics
параметр как графический контекст, на который вы можете рисовать.
вызов
object.paintComponent(g)
ошибка.вместо этого этот метод вызывается автоматически при создании панели. Элемент
paintComponent()
метод также может быть вызван явно с помощьюrepaint()
метод, определенный вComponent
класса.эффект вызова
repaint()
это качели автоматически очищает графику на панели и выполняетpaintComponent
метод для перерисовки графики на этой панели.