Java Nimbus LAF с прозрачными текстовыми полями

У меня есть приложение, которое использует отключенные JTextFields в нескольких местах, которые должны быть прозрачными, что позволяет фоновому изображению вместо обычного текстового поля.

При запуске нового Nimbus LAF эти поля непрозрачны (несмотря на установку setOpaque (false)), и мой интерфейс нарушен. Как будто ЛАФ игнорирует непрозрачное свойство. Установка цвета фона явно трудна в нескольких местах, и менее оптимальная из-за фоновых изображений на самом деле не работает - она ​​по-прежнему рисует его фоном по умолчанию LAF сверху, оставляя пограничный вид (экран заставки ниже имеет фон, явно установленный для соответствия изображению).

Любые идеи о том, как я могу заставить Нимбус не рисовать фон для JTextField?

Примечание. Мне нужен JTextField, а не JLabel, потому что мне нужна потокобезопасная функция setText() и обертывания.

Примечание. Моим резервным положением является продолжение использования системы LAF, но Nimbus действительно выглядит значительно лучше.

См. примеры изображений ниже.


Выводы

Сюрприз в этом поведении вызван неправильной интерпретацией того, что должен делать setOpaque() - из отчета об ошибке Nimbus:

Это проблема оригинального дизайна Swing и того, как он запутывался годами. Проблема setOpaque (false) имела побочный эффект в выходе из LAF, который скрывает фон, который на самом деле не тот, для чего он предназначен. Можно сказать, что компонент my имеет прозрачные части и качели, должен покрасить за собой родительский компонент.

К сожалению, компоненты Nimbus также, похоже, не соблюдают setBackground (null), которые в противном случае были бы рекомендуемым способом остановить рисование фона. Установка полностью прозрачного фона кажется мне неинтуитивной.

По-моему, setOpaque()/isOpaque() является ошибочным публичным выбором API, который должен был быть только:

public boolean isFullyOpaque();

Я говорю это, потому что isOpaque() == true - это контракт с Swing, что компонентный подкласс возьмет на себя ответственность за покраску всего фона - это означает, что родитель может пропустить рисование этого региона, если он захочет (что является важным показателем повышение). Что-то внешнее не может напрямую изменить этот контракт (законно), чье выполнение может быть закодировано в компоненте.

Таким образом, непрозрачность компонента не должна быть установлена ​​с помощью setOpaque(). Вместо этого что-то вроде setBackground (null) должно приводить к тому, что многие компоненты "не имеют фона" и, следовательно, становятся не полностью непрозрачными. Например, в идеальном мире большинство компонентов должны иметь isOpaque(), который выглядит следующим образом:

public boolean isOpaque() { return (background!=null); }

Пример http://i41.tinypic.com/sviczq.png

alt text http://i44.tinypic.com/35d80ao.png

Ответ 1

Я столкнулся с этой проблемой на прошлой неделе, используя JTextPane. Метод setOpaque() работает так, как ожидалось, при использовании любого внешнего вида, кроме негобуса. По-видимому, внешний вид нимба меняет поведение, которое мы ожидаем с помощью setOpaque() для многих Компонентов. В зависимости от того, как вы смотрите на него, это можно считать ошибкой. Проверьте комментарии к этому sun bugid:

ошибка с nimbus opaque

Обходной путь, который работал у меня, был:

myPane.setOpaque(false); // added by OP
myPane.setBorder(BorderFactory.createEmptyBorder());
myPane.setBackground(new Color(0,0,0,0));

Примечание от OP: мне также нужно было обеспечить setOpaque (false) для JTextField, чтобы родительский фон был нарисован - просто хотел упомянуть об этом для других, которые следуют, если они экспериментировали с setOpaque (true), как и я.

Ответ 2

Эй, программная обезьяна.

mmhh, что касается установки подклассов пользовательского интерфейса, которые на самом деле уважают поведение setOpaque.

Я думаю, что это что-то вроде setUI или что-то в этом роде.

Вы можете захватить исходный код нимба и посмотреть, что там сломалось (если оно есть), подклассировать его и установить "фиксированный".

Звучит довольно интересно, есть ли у вас скриншот, который мы видим?

Ответ 3

Я думаю, что вопрос заключается в том, как интерпретировать "непрозрачный" и "фон". Для поля JText возникает вопрос: "Какие видимые части являются фоном?". Я бы определил "фон" как части ограничивающего прямоугольника, которые не нарисованы компонентом. Для "круглой" кнопки, например, это будут углы вне круга. Поэтому я бы сказал, что у JTextfield нет видимого фона! Он имеет прямоугольную форму и то, что вы принимаете в качестве фона, не является фоном поля, а полевым холстом.


Перезагрузка от OP

Это достаточно интересная идея, на которую стоит ответить в ответ будущим зрителям (в отличие от комментариев).

Я должен не согласиться. Я бы сказал, что часть компонента вне границы не является частью компонента - вне компонента. Поле с закругленными углами, по необходимости, непрозрачно, поскольку оно не может быть ответственным за покраску всей прямоугольной области - это побочный эффект всех компонентов, являющихся прямоугольными по размерам.

Я думаю, что это соображение делает аргумент для существующего (и непонятого) значения isOpaque(). Он также делает мой аргумент, что setOpaque() не должен существовать и что setBackground (null) должен заставить компонент не рисовать фон.

Я бы сказал, что фон текстового поля действительно является цветом области внутри его границ, и я не думаю, что вы найдете очень много людей, чтобы оспаривать это как интуитивный вывод - поэтому наличие фона применимо к этот регион подчиняется правилу наименьшего удивления для пользователя API.

Ответ 4

Из javadoc

public void setBackground (Цвет bg)

Устанавливает цвет фона этого компонента. Цвет фона используется, только если компонент непрозрачен, и только подклассами JComponent или ComponentUI. непосредственный подклассы JComponent должны переопределять paintComponent, чтобы почтить это свойство.

Это зависит от внешнего вида и качества этого объекта, некоторые могут выбрать чтобы игнорировать его.