Прозрачный фон JToolTip вне рамки в LinuxJAVA

Программисты JAVA общаются здесь
Anonymous
Прозрачный фон JToolTip вне рамки в Linux

Сообщение Anonymous »

Я работаю над приложением Java Swing (я использую JDK 22), в котором настраиваю практически каждый компонент графического интерфейса.
Проблема, с которой я столкнулся, заключается в том, что я создал собственный класс пользовательского интерфейса всплывающей подсказки, в котором я рисую его в виде скругленного прямоугольника, чтобы соответствовать общей эстетике программы:

Код: Выделить всё

public class CustomToolTipUI extends ToolTipUI {

@SuppressWarnings("java:S1172")
public static ComponentUI createUI(JComponent component) {
return new CustomToolTipUI();
}

@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2 = (Graphics2D) g.create();

RoundRectangle2D roundedRect = new RoundRectangle2D.Float(0, 0, c.getWidth(), c.getHeight(),
Constants.ROUNDED_BORDER_ARC_TOOLTIP,
Constants.ROUNDED_BORDER_ARC_TOOLTIP);

// Round rectangle configuration
g2.setRenderingHints(Constants.MAP_RENDERING_HINTS);
g2.setComposite(AlphaComposite.Clear);
g2.fill(roundedRect);

// Background painting
g2.setComposite(AlphaComposite.Src);
g2.setColor(Constants.COLOR_GREEN_DARK_MEDIUM);
g2.fill(roundedRect);

// Text painting
FontMetrics fm = g2.getFontMetrics();

String text = ((JToolTip) c).getTipText();

g2.setColor(Color.WHITE);
g2.drawString(text, (c.getWidth() - fm.stringWidth(text)) / 2, (c.getHeight() - fm.getHeight()) / 2 + fm.getAscent());
g2.dispose();
}

@Override
public Dimension getPreferredSize(JComponent c) {
FontMetrics fm = c.getFontMetrics(c.getFont());

Insets insets = c.getInsets();

return new Dimension(fm.stringWidth(((JToolTip) c).getTipText()) + insets.left + insets.right,
fm.getHeight() + insets.top + insets.bottom);
}
}
Я заметил, что если всплывающая подсказка выходит за границы фрейма, она отображается внутри компонента, а это означает наличие обычного белого прямоугольника с нарисованным внутри него прямоугольником со скругленными углами:
Изображение
Здесь я попробовал много вещей и не мог это исправить, пока не наткнулся на этот пост!
Я попробовал то, что там написано, но сначала мне пришлось создать собственный класс всплывающей подсказки, который использует мой собственный пользовательский интерфейс, но для достижения этой цели переопределяет метод addNotify:

Код: Выделить всё

public class CustomToolTip extends JToolTip {

public CustomToolTip(JComponent component) {
setOpaque(false);
setComponent(component);
setUI(new CustomToolTipUI());
}

@Override
@SuppressWarnings("java:S1190")
public void addNotify() {
super.addNotify();

setOpaque(false);

Component parent = this.getParent();

if (parent instanceof JComponent) {
((JComponent) parent).setOpaque(false);
}

try {
Window window = SwingUtilities.windowForComponent(this);

if (window != null) {
window.setBackground(new Color(0, 0, 0, 0));
}
} catch (IllegalComponentStateException | UnsupportedOperationException _) {
CommonFunctions.exitProgram(Error.ERROR_INTERNAL);
}
}

@Override
public Insets getInsets() {
return Constants.INSETS_TOOLTIP;
}
}
теперь я могу переопределить метод createToolTip в моем пользовательском классе меток следующим образом:

Код: Выделить всё

@Override
public JToolTip createToolTip() {
return new CustomToolTip(this);
}
и это работает! вот пример:
Изображение

Жизнь была хороша, пока я не попытался запустить это в Linux, чтобы убедиться, что моя кросс-платформенная совместимость не нарушена... но в Linux Mint 21.3 Cinnamon белый фон, показанный на первом снимке экрана, все еще присутствует... >
Я пробовал МНОГО вещей (например: переключение isOpaque, изменение непрозрачности окна, изменение альфа-канала цвета, изменение форма оконного контейнера...), но я не могу заставить его работать в Linux, и у меня заканчиваются идеи. Кроме того, в Интернете почти нет примеров создания чего-то подобного, поэтому я могу полагаться только на документацию, которую я прочитал, но не уверен, в чем может быть проблема.
Согласно документации java.awt.Window.setBackground(Color):

Код: Выделить всё

All the following conditions must be met to enable the per-pixel transparency mode for this window:

- The PERPIXEL_TRANSLUCENT translucency must be supported by the graphics device where this window is located
- The window must be undecorated (see Frame.setUndecorated and Dialog.setUndecorated)
- The window must not be in full-screen mode (see GraphicsDevice.setFullScreenWindow(Window))
Если какое-либо из этих условий не выполнено, значение альфа будет игнорироваться (нет прозрачности). Я проверил эти значения, и все в порядке. В моей системе Linux поддерживается прозрачность.
Что здесь можно сделать или что я могу попытаться решить? Заранее большое спасибо!

Подробнее здесь: https://stackoverflow.com/questions/786 ... e-in-linux

Вернуться в «JAVA»