Существует общее правило: апплет организует вывод в свое окно только тогда, когда AWT вызывает его методы update() или paint() . Это поднимает интересный вопрос: как сам апплет может вызвать модификацию своего окна, когда его информация изменяется? Например, если апплет отображает движущийся заголовок, какой механизм используется для обновления окна каждый раз, когда этот заголовок прокручивается? Запомните одно из фундаментальных архитектурных ограничений, наложенных на апплет: он должен быстро возвратить управление в исполняющую систему AWT. Он не может создавать цикл внутри paint(), который, например, повторно прокручивает заголовок. Это помешало бы передаче управления обратно в AWT. При данном ограничении может показаться, что вывод в окно апплета будет, в лучшем случае, затруднен. К счастью, дело обстоит не так. Всякий раз, когда апплет должен обновить информацию, отображенную в его окне, он просто вызывает repaint().
Метод repaint() определен в пакете AWT. Он заставляет исполняющую систему AWT вызывать метод update() апплета, который в его реализации по умолчанию вызывает paint(). Таким образом, в той части апплета, где требуется отобразить нечто в окне, просто сохраните вывод и затем вызовите repaint(). Тогда AWT выполнит вызов paint(), который может отображать сохраненную информацию. Например, если часть апплета должна вывести строку, она может сохранить эту строку в string-переменной и затем вызвать repaint(). Внутри paint() строка выводится методом drawString ().
Метод repaint() имеет четыре формы. Рассмотрим каждую по очереди. Самая простая версия repaint():
void repaint ()
Она вызывает перерисовку всего окна. Следующая версия определяет область, которая будет перерисована:
void repaint (int left, int top, int width, int height)
Здесь координаты верхнего левого угла области определены параметрами left и top, а ширина и высота области пересылается в width и height. Эти измерения определены в пикселах. При указании области для перерисовки экономится время, т. к. обновление окна — длительная операция. Если нужно обновить только маленькую часть окна, более эффективно перерисовать именно эту область.
Вызов repaint() — это, по существу, требование, чтобы ваш applet был перерисован несколько позднее. Однако, если ваша система "нетороплива" или занята, update(), возможно, не будет вызываться немедленно. Множественные запросы перерисовки, которые происходят в пределах короткого времени, могут быть отвергнуты AWT, так что update() вызывается только время от времени. Это может стать проблемой во многих ситуациях, включая мультипликацию, где постоянно требуется время для обновления. Одно из решений этой проблемы состоит в том, чтобы использовать следующие формы repaint():
void repaint (long maxDelay)
void repaint (long maxDelay, int x, int y, int width, int height)
Здесь maxDelay определяет максимальное число миллисекунд, на которое задерживается вызов update(). Однако, остерегайтесь. Если это время закончится прежде, чем update() может быть вызван, он вовсе не вызывается. У метода нет никакого возвращаемого значения или выброшенного исключения, так что вы должны быть внимательными.
Возможен вывод в окно апплета другим способом — не методами paint() или update(). Для этого следует получить графический контекст, вызывая getGraphics() (определенный в Component), и затем использовать этот контекст для вывода в окно. Однако для большинства приложений лучше и проще направлять вывод окна через paint() и вызывать repaint(), когда содержимое окна изменяется.
Для демонстрации repaint() разработан апплет с бегущим заголовком, который прокручивает сообщение через окно апплета справа налево. Так как прокрутка сообщения — повторяющаяся задача, она выполняется отдельным потоком, создаваемым апплетом во время инициализации. Исходный код этого апплета: