如何在另一个JComponent上添加半透明JPanel

时间:2015-12-29 16:45:22

标签: java swing

我正在尝试为应用添加功能。我的目标是用半透明的JPanel覆盖 JFrame的 JComponent(它将在中间包含一个JXBusyLabel)。

假设我们有这样的事情:

img1

点击上的

我们希望有以下JPanel,但是semitrasparent(这意味着它应该允许或多或少地看到它的内容):

img2

我尝试使用glassPane。任何关于如何实现这一点的建议都将受到赞赏。 此外,我注意到JXBusyLabel的背景是不同的,如果它的工作方式与semitrasparent jpanel背景相同,那将是很好的。 蛋糕上的樱桃就是将装载轮放在那个jpanel的中间。

我们会在解决每个问题后立即更新以下代码。 任何有关如何实现这一目标的建议都将受到赞赏。

这是一个故意写的示例代码:

public class Main {


    public static void main(String[] args)  {       
        SwingUtilities.invokeLater(new TestApp());      
    }

}

class TestApp implements Runnable {
    @Override
    public void run(){  
        JFrame mainWindow = new JFrame("MyFrame");
        mainWindow.setLayout(new BorderLayout());
        mainWindow.setMinimumSize(new Dimension(300,300));

//      mainWindow.add(initView(),BorderLayout.CENTER);
      mainWindow.add(initLoadingPanel(),BorderLayout.CENTER);
        mainWindow.add(initButton(),BorderLayout.PAGE_END);

        mainWindow.setVisible(true);
    }

    private JPanel initView() {
        JPanel viewPort = new JPanel();
        viewPort.setLayout(new BoxLayout(viewPort, BoxLayout.Y_AXIS));
        viewPort.add(new JLabel("label 1"));
        viewPort.add(new JLabel("label 2"));
        viewPort.add(new JLabel("label 3"));
        viewPort.add(new JLabel("label ..."));
        viewPort.add(new JLabel("label N"));
        return viewPort;
    }

    private JPanel initLoadingPanel() {
        JPanel trasparentPanel = new JPanel();
        trasparentPanel.setOpaque(true);
        trasparentPanel.setBackground(new Color(200,230,250,100));
        trasparentPanel.add(initLoadingWheel());
        return trasparentPanel;
    }

    private Component initLoadingWheel() {
        JXBusyLabel loadingWheel = new JXBusyLabel(new Dimension(80,80));
        loadingWheel.setBackground(new Color(200,230,250,100));
        loadingWheel.setOpaque(true);
        loadingWheel.setBusy(true);
        return loadingWheel;
    }

    private JButton initButton() {
        JButton button = new JButton("Start & Stop Loading");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

            }
        });
        return button;
    }
}

2 个答案:

答案 0 :(得分:2)

  

我尝试使用glassPane

对我来说很好。阅读Root Panes上的Swing教程并下载工作示例。发布展示问题的SSCCE

您还可以查看Disabled Glass Pane以获取简单的API。当前代码仅显示文本,但您可以轻松修改类以显示图像,因为代码只使用JLabel作为文本。

您还可以使用JLayer来装饰您的面板。

答案 1 :(得分:1)

  

阅读Root Panes上的Swing教程并下载正常工作   例。
[...]还可以查看Disabled Glass Pane的简单内容   API。
您也可以使用JLayer 来装饰您的面板。

正如Camickr建议的那样,GlassPanel会起作用。

结果如下:

loadingWheel on a GlassPane

以下代码表示必须为JFrame设置为glassPane的GlassPane的istance。

@SuppressWarnings("serial")
public class GlassPane extends JComponent implements KeyListener {

    private static Cursor WAIT_CURSOR = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);

    private JXBusyLabel wheel;

    public GlassPane()  {
        super.setOpaque( false );
        super.setLayout( new GridBagLayout() );
        super.setBackground(initBackground());
        initWheel();
        addEventCatchers();
    }

    private void addEventCatchers() {
        addMouseListener( new MouseAdapter() {} );
        addMouseMotionListener( new MouseMotionAdapter() {} );
        addKeyListener(this);
        setFocusTraversalKeysEnabled(false);        
    }

    private Color initBackground() {
        Color base = UIManager.getColor("inactiveCaptionBorder");
        Color background = new Color(base.getRed(), base.getGreen(), base.getBlue(), 128);
        return background;
    }

    private void initWheel() {
        wheel = new JXBusyLabel();
        add(wheel, new GridBagConstraints());
    }

    /*
     *  The component is transparent but we want to paint the background
     *  to give it the disabled look.
     */
    @Override
    protected void paintComponent(Graphics g)   {
        g.setColor( getBackground() );
        g.fillRect(0, 0, getSize().width, getSize().height);
    }

    /*
     *  Make the glass pane visible, start the wheel and change the cursor to the wait cursor
     */
    public void activate(boolean toggle) {
        wheel.setVisible(toggle);
        wheel.setBusy(toggle);
        super.setVisible( toggle );
        setCursor(getCursor());
        if(super.isVisible()){
            requestFocusInWindow();
        }
    }

    @Override
    public Cursor getCursor(){
        Cursor cursor = this.isVisible() ? GlassPane.WAIT_CURSOR : null; 
        return cursor;
    }

    /*
    *  Implement the KeyListener to consume events
    */
    public void keyPressed(KeyEvent e)  {
        e.consume();
    }
    public void keyReleased(KeyEvent e) {
        e.consume();
    }

    public void keyTyped(KeyEvent e) {}

}

这是一个可用于测试上述类的主要方法:

public class Main {

    public static GlassPane glass;
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        JFrame frame = new JFrame("GlassPaneDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(200,200));

        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new BorderLayout());
        contentPane.add(new JLabel("asdasda"),BorderLayout.CENTER);
        GlassPane myGlassPane = new GlassPane();
        JButton myButton =  initButton(myGlassPane);

        contentPane.add(myButton,BorderLayout.PAGE_END);
        frame.setGlassPane(myGlassPane);
        frame.pack();
        frame.setVisible(true);
    }

    private static JButton initButton(final GlassPane myGlassPane) {
        JButton button = new JButton("Start & Stop Loading");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                    myGlassPane.activate(!myGlassPane.isVisible());
            }
        });
        return button;
    }

}