#java #swing #colors #background #applet
#java #swing #Цвет #фон #апплет
Вопрос:
Я только что наткнулся на пример — учебник в книге, который я не совсем понимаю.
Итак, вот код
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.util.GregorianCalendar;
import javax.swing.JApplet;
public class Watch extends JApplet {
private final Color butterscotch = new Color(255, 204, 102);
Rectangle2D.Float background;
// Whats is purpose of following line, here on this place? Applet works well even without it?
Graphics2D screen2D;
@Override
public void init() {
setBackground(Color.black);
}
@Override
public void paint(Graphics screen) {
super.paint(screen);
Graphics2D screen2D = (Graphics2D) screen;
Font type = new Font("Monospaced", Font.BOLD, 20);
screen2D.setFont(type);
screen2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (background == null) {
// set up the background rectangle
// Whats is purpose of following line? Applet works well even without parameters?
background = new Rectangle2D.Float(0F, 0F, getSize().width, getSize().height);
// But if previous line is omit then background color is not set - why?
// background = new Rectangle2D.Float(0F, 0F, 0F, 0F);
// background = new Rectangle2D.Float();
}
screen2D.fill(background);
GregorianCalendar day = new GregorianCalendar();
String time = day.getTime().toString();
screen2D.setColor(butterscotch);
screen2D.drawString(time, 5, 25);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// do nothing
}
repaint();
}
}
Мои вопросы:
-
Какова цель этого объявления (строка 16) здесь, в этом месте кода:
Graphics2D screen2D;
код работает даже без него? Чтобы быть более точным, объект Graphics2D, конечно, будет объявлен позже с тем же именем объекта (screen2D) позже в paint() (строка 26).
- Какова цель
getSize().width, getSize().height
в этой строке (33):
background = new Rectangle2D.Float(0F, 0F, getSize().width, getSize().height);
Я имею в виду, как он может даже получить размер вновь созданного объекта, если размер не определен (до) создания этого объекта? Хорошо, я полагаю, что, поскольку Eclipse дает начальное значение 200 x 200, это может иметь смысл, так что getSize().width, getSize().height получает эти значения? Я прав насчет этого?
Более того, любая из следующих (подстановочных) строк кода работает хорошо, вместо этой:
background = new Rectangle2D.Float(0F, 0F, 0F, 0F);
или
background = new Rectangle2D.Float();
НО здесь возникает другой вопрос
- Если
background = new Rectangle2D.Float(0F, 0F, getSize().width, getSize().height);
заменяется на
background = новый прямоугольник2d.Float(0F, 0F, 0F, 0F);
или
background = new Rectangle2D.Float();
Тогда цвет фона НЕ будет черным, как определено в init() строка 20
setBackground(Color.black);
но это какой-то оттенок серого. Почему? Чего мне здесь не хватает?
Еще одно замечание: я использую Eclipse IDE Kepler, если это имеет значение в данном случае в любом случае (я знаю, что размер апплета по умолчанию равен 200 x 200, который можно изменить в Run configuration -> parameters )
Комментарии:
1. Совет этой книги мне не кажется разумным. Это поле Graphics2D, на мой взгляд, является приглашением к неудаче. Если кто-то попытается использовать его вне метода рисования, он рискует получить NPE или несуществующий рисунок. Код также обращается непосредственно к контейнеру верхнего уровня, апплету, чего в целом следует избегать, и в коде есть как a
Thread.sleep(...)
, так и вызовrepaint()
внутри метода paint !2. Хотя некоторые «плохие методы» могут быть приемлемыми для достижения быстрых, мотивирующих результатов, Swing в целом настолько прост, что в них не должно быть необходимости, и плохие методы, на которые указал Hovercraft Full Of Eels, очевидная опечатка, вызвавшая этот вопрос, и такие детали, как использование
getSize().width
вместоgetWidth()
, не являются «упрощения», но просто неправильный способ сделать это. Я всегда думал, что эти книги «… за 21 день» подозрительны … abstrusegoose.com/2493. @Marco13 Я читаю последние 30 с лишним страниц, так что в любом случае пора двигаться дальше. Поэтому, пожалуйста, не стесняйтесь рекомендовать мне любую JAVA-книгу по вашему выбору.
Ответ №1:
В этом примере есть два объекта с именем screen2D . Первая, которая объявляется в строке 16, является переменной-членом, которая является закрытой для пакета (может быть доступна всем классам в данном пакете). Как вы указали, эта переменная, похоже, вообще не используется.
Вторая screen2D — это локальная переменная, объявленная в строке 26 и используемая только в функции рисования.
Вероятно, это опечатка, и для примера требуется только одна из этих переменных.
функция getSize() наследуется от суперкласса JApplet, поэтому getSize.width() получает ширину апплета, а не ширину вновь созданного объекта.
Поэтому, когда вы меняете фон на размер 0, а затем устанавливаете его цвет, вы устанавливаете цвет объекта, который не имеет никакого размера. Поскольку этот объект не имеет никакого размера, не имеет значения, какой цвет вы ему задаете, поскольку вы на самом деле его не увидите.
Комментарии:
1. Да, я понимаю это, просто мне кажется неразумным, почему он объявляется впервые, за исключением случаев, когда автор просто игнорирует это или что-то еще ..?
2. Я обновил ответ, но да, похоже, автор просто забыл, что это переменная-член, и также создал локальную переменную
3. Хорошо, я полагаю, что, поскольку Eclipse дает начальное значение 200 x 200, это может иметь смысл, так что getSize().width, getSize().height получает эти значения? Я прав насчет этого? И методу fill (позже) действительно есть что заполнить, но если это похоже на background = new Rectangle2D.Float(); тогда размер прямоугольника равен нулю, поэтому фон не заполнен, я правильно понял? Конечно, позже размер апплета будет изменен на 200×200 для Eclipse по умолчанию при вызове метода drawString (строка 43)?
4. Да, вы правы, когда говорите, что фону нужен размер, чтобы вы могли видеть его цвет. Я не вижу, откуда берутся значения по умолчанию 200, но метод drawString() используется только для отображения текста на экране, поэтому он не должен оказывать никакого влияния на фоновый прямоугольник.