Полупрозрачный JPopupMenu внутри полупрозрачного окна - альтернатива?

Я не уверен, возможно ли это, но есть ли способ безопасно сделать всплывающие окна полупрозрачными, даже если родительский контейнер также полупрозрачный?

Если нет, что было бы разумнее использовать или расширить вместо JPopupMenu?

Примечание. Прозрачный относится к компоненту, у которого нет фона, аналогично эффекту setOpaque(false);. Спасибо.



Из ответа на форуме пользователя camickr в 2009 году:

Я не знаю, изменилось ли рисование прозрачности в 1.6.0_10. До этого я полагал, что прозрачность может быть достигнута только в легких компонентах (т.е. Swing делает всю картину). JFrame, JWindow и JDialog не являются легковесными, поскольку используют компоненты ОС.

В случае всплывающего окна оно легковесно, когда полностью содержится в родительском фрейме. Но легкое всплывающее окно не может быть нарисовано за пределами рамки, поэтому JWindow (я полагаю) используется в качестве всплывающего окна, которое не может быть прозрачным.

SSCCE: отображение полупрозрачного JWindow поверх полупрозрачного JFrame.

import com.sun.awt.AWTUtilities;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class OpaqueWindowSSCCE {

    private int countdown = 5;

    public static void main(String[] args) {
        new OpaqueWindowSSCCE();
    }

    public OpaqueWindowSSCCE() {
        final JFrame frame = new JFrame("OpaqueWindowSSCCE");
        final JWindow window = new JWindow();

        new Timer(1000, new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent e) {
                if(--countdown == 0){
                    frame.dispose();
                    window.dispose();
                    System.exit(0);
                } else {
                    frame.repaint();
                }
            }

        }).start();

        frame.setContentPane(new JPanel() {

            @Override
            public void paintComponent(Graphics paramGraphics) {
                super.paintComponent(paramGraphics);
                Graphics2D g = (Graphics2D) paramGraphics.create();
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g.setColor(new Color(50, 50, 50));
                g.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
                g.setColor(new Color(180, 180, 180));
                g.drawString("Closing in " + countdown + " seconds", 20, 25);
            }
        });

        window.setContentPane(new JPanel() {

            @Override
            public void paintComponent(Graphics paramGraphics) {
                super.paintComponent(paramGraphics);
                Graphics2D g = (Graphics2D) paramGraphics.create();
                g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g.setColor(new Color(180, 180, 180));
                g.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
            }
        });

        frame.setUndecorated(true);

        ((JComponent) frame.getContentPane()).setOpaque(false);
        ((JComponent) window.getContentPane()).setOpaque(false);

        AWTUtilities.setWindowOpaque(frame, false);
        AWTUtilities.setWindowOpaque(window, false);

        window.setAlwaysOnTop(true);

        frame.setBounds(200,200,500,500);
        window.setBounds(600,600,200,200);
        frame.setVisible(true);
        window.setVisible(true);
    }
}

person rtheunissen    schedule 10.05.2012    source источник
comment
Я предполагаю, что это может быть достигнуто в данном контексте, который вы делаете, с помощью JWindow с помощью этой функции setOpacity().   -  person nIcE cOw    schedule 10.05.2012


Ответы (1)


Попробуйте эту часть кода, хотя я использовал JWindow

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class WindowExample
{
    private JWindow window;
    private JLabel updateLabel;
    private int count = 5;
    private Timer timer;
    private int x;
    private int y;
    private ActionListener timerAction = new ActionListener()
    {
        public void actionPerformed(ActionEvent ae)
        {
            updateLabel.setText("Closing Window in " + count + " seconds...");
            count--;
            if (count == 0)
            {
                timer.stop();
                window.setVisible(false);
                window.dispose();
            }   
        }
    };

    private void createAndDisplayGUI()
    {
        final JFrame frame = new JFrame("Window Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setUndecorated(true);
        frame.setOpacity(0.5f);
        frame.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent me)
            {
                x = me.getX();
                y = me.getY();
                window = new JWindow();
                JPanel contentPane = new JPanel();
                JLabel positionLabel = new JLabel(
                    "X : " + me.getX() + " Y : " + me.getY());
                updateLabel = new JLabel("TImer");  
                contentPane.setLayout(new BorderLayout(5, 5));
                contentPane.add(updateLabel, BorderLayout.CENTER);
                contentPane.add(positionLabel, BorderLayout.PAGE_END);
                window.setContentPane(contentPane);
                window.setOpacity(0.5f);
                window.setSize(200, 100);
                window.setLocation(x + window.getWidth(), y + window.getHeight());
                window.setVisible(true);
                count = 5;
                timer = new Timer(1000, timerAction);
                timer.start();
            }
        });

        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String... args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new WindowExample().createAndDisplayGUI();
            }
        });
    }
}

И вот вывод:

ПРОЗРАЧНЫЙ

ПРЕДУПРЕЖДЕНИЕ Я ПОЛУЧАЮ

C:\Mine\JAVA\J2SE>javac -d classes src\OpaqueWindowSSCCE.java
src\OpaqueWindowSSCCE.java:1: warning: AWTUtilities is internal proprietary API and may be removed i
n a future release
import com.sun.awt.AWTUtilities;
                  ^
src\OpaqueWindowSSCCE.java:68: warning: AWTUtilities is internal proprietary API and may be removed
in a future release
        AWTUtilities.setWindowOpaque(frame, false);
        ^
src\OpaqueWindowSSCCE.java:69: warning: AWTUtilities is internal proprietary API and may be removed
in a future release
        AWTUtilities.setWindowOpaque(window, false);
        ^
3 warnings
person nIcE cOw    schedule 10.05.2012
comment
Спасибо за SSCCE! Понятно, что JWindow способен правильно отображаться - недостаток в том, что мне придется реализовать отображение и скрытие, чтобы имитировать JPopupMenu, что было бы не слишком сложно. - person rtheunissen; 10.05.2012
comment
ДОБРО ПОЖАЛОВАТЬ И ПРОДОЛЖАТЬ УЛЫБАТЬСЯ :-), да, это правда, даже в JPopUpMenu, я думаю, вам нужно щелкнуть в каком-то другом месте, чтобы скрыть предыдущее :-), Преимущество JWindow в том, что мы можем добавить все, что захотим. добавить к нему, чтобы показать его пользователю :-) - person nIcE cOw; 10.05.2012
comment
Да, но JPopUpMenu очень хорошо справляется с фокусировкой, и нужно убедиться, что он работает хорошо. Почему-то я вообще не подумал о JWindow... спасибо, попробую и вернусь к вам. :D - person rtheunissen; 10.05.2012
comment
Хм, это не работает, потому что установка произвольного OPACITY здесь не проблема. Я бы хотел, чтобы всплывающее окно вообще не имело фона (чтобы круглые углы могли быть круглыми). Важно отметить, что JFrame не является непрозрачным, через AWTUtilities.setWindowOpaque(frame, false); - person rtheunissen; 10.05.2012
comment
@paranoid-android: извините за поздний ответ, возникли некоторые проблемы с сервером. Не могли бы вы предоставить небольшой рабочий код, который я могу попробовать, если это не большая проблема, было бы здорово :-) - person nIcE cOw; 10.05.2012
comment
@paranoid-android: Спасибо за это, МОЖЕТ ли я задать вам простой вопрос, почему это предупреждение приходит ко мне, проверьте мой ответ на это. Я рад, однако, что мой ответ помог вам где-то :-) WOWO, я тоже кое-что узнал из ваших материалов, как рисовать закругленные JWindow , это впечатляет :-) - person nIcE cOw; 10.05.2012