用摇摆创建滑出工具面板

时间:2013-05-10 14:15:58

标签: java eclipse swing user-interface

我真的不知道该怎么做。当用户点击按钮时,我希望从当前的一个面板“滑出”。然后,当他们再次单击该按钮时,它将重新滑入。

这是我的意思的一个例子。注意它看起来像是在左边的窗口“下面”以及它是如何完全(但几乎)延伸到底部和顶部的:

enter image description here

这是没有出局时的照片(背景中的第二个窗口只是第一个图像[上面的那个],因为当我拍摄屏幕时浏览器在框架中): enter image description here

2 个答案:

答案 0 :(得分:2)

两种方法:

  1. 使用JLayeredPane。好处是你得到了你正在寻找的重叠效应。缺点是JLP使用空布局,这意味着如果没有额外的努力,您的UI将无法很好地调整大小。

  2. 使用CardLayout。好处是你的布局会像你要求的那样调整大小。缺点是你不会得到重叠效应。你的滑出式面板只有一个空白区域。

  3. 编辑:我刚注意到您的滑出不重叠,而是向外延伸到右侧。我原本以为你的意思就像旧的Outlook UI。在这种情况下,它可以是任何滑出,还是必须固定在框架上?

    这是一个粗略的演示,只使用BorderLayout来表示效果。我在这个演示和屏幕截图之间看到的最大区别是:

    1. 框架的边框随着演示
    2. 中的滑出而延伸
    3. 幻灯片中的幻灯片未在演示中偏移。
    4. 代码:

      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      import javax.swing.border.*;
      
      public class SlideOutPanelDemo
      {
        private JPanel pnlMain;
        private JPanel pnlTools;
        private JFrame frame;
      
        public static void main(String[] args)
        {
          SwingUtilities.invokeLater(new Runnable()
          {
            public void run()
            {
              new SlideOutPanelDemo().createAndShowGUI();
            }
          });
        }
      
        public void createAndShowGUI()
        {
          JButton button = new JButton("Tools");    
          button.addActionListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent event)
            {
              boolean visible = pnlTools.isVisible();
              pnlTools.setVisible(! visible);
              frame.pack();
            }
          });
      
          pnlTools = createToolsPanel();
          pnlMain = createMainPanel();
      
          JToolBar toolBar = new JToolBar();
          toolBar.add(button);
      
          JPanel contentPane = new JPanel();
          contentPane.setLayout(new BorderLayout());
          contentPane.setOpaque(true);
          contentPane.add(toolBar, BorderLayout.NORTH);
          contentPane.add(pnlMain, BorderLayout.WEST);
          contentPane.add(pnlTools, BorderLayout.EAST);
      
          pnlMain.setVisible(true);
          pnlTools.setVisible(false);
      
          JFrame.setDefaultLookAndFeelDecorated(true);
          frame = new JFrame("Slide Out Panel Demo");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.setContentPane(contentPane);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
        }
      
        private JPanel createMainPanel()
        {
          JPanel panel = new JPanel();
          panel.setBorder(BorderFactory.createTitledBorder("Main"));
          panel.add(new JLabel("Field 1"));
          panel.add(new JTextField(20));
          panel.add(new JLabel("Field 2"));
          panel.add(new JTextField(20));
          panel.setSize(1000, 600);
      
          return panel;
        }
      
        private JPanel createToolsPanel()
        {
          JPanel panel = new JPanel();
          panel.setBackground(Color.YELLOW);
          Border b1 = BorderFactory.createTitledBorder("Tools");
          Border b2 = BorderFactory.createLineBorder(Color.BLUE, 2);
          panel.setBorder(BorderFactory.createCompoundBorder(b2, b1));
          panel.add(new JLabel("Thing 1"));
          panel.add(new JLabel("Thing 2"));
          panel.setSize(400, 600);
      
          return panel;
        }
      }
      

答案 1 :(得分:2)

借助于书籍Swing Hacks,我创建了一个滑动JFrame和一个滑动JDialog。我花了几个小时来调试代码。

这是一个测试运行,显示JOptionPane滑出部分。

Sheet Test Partial

一路走来。

Sheet Test Out

基本上,我使用了JOptionPane的内容窗格,并将其设置为图像。

您左键单击幻灯片按钮以滑出JOptionPane。您在JOptionPane上单击“是”或“否”以向后滑动JOptionPane。

这是创建动画JFrame和动画JDialog的代码。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;

import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.LineBorder;

public class AnimatedJFrame extends JFrame implements ActionListener {

    private static final long   serialVersionUID    = 6462856212447879086L;

    public static final int     INCOMING            = 1;
    public static final int     OUTGOING            = -1;
    public static final float   ANIMATION_DURATION  = 600F;
    public static final int     ANIMATION_SLEEP     = 5;

    JComponent                  sheet;
    JPanel                      glass;
    AnimatingSheet              animatingSheet;
    boolean                     animating;
    int                         animationDirection;
    Timer                       animationTimer;
    long                        animationStart;
    BufferedImage               offscreenImage;

    public AnimatedJFrame(String name) {
        super(name);
        glass = (JPanel) getGlassPane();
        glass.setLayout(new GridBagLayout());
        animatingSheet = new AnimatingSheet();
        animatingSheet.setBorder(new LineBorder(Color.BLACK, 1));
    }

    public JComponent showJDialogAsSheet(JDialog dialog) {
        sheet = (JComponent) dialog.getContentPane();
        sheet.setBorder(new LineBorder(Color.BLACK, 1));
        glass.removeAll();
        animationDirection = INCOMING;
        startAnimation();
        return sheet;
    }

    public void hideSheet() {
        animationDirection = OUTGOING;
        startAnimation();
    }

    private void startAnimation() {
//      glass.repaint();

        // Clear glass pane and set up animatingSheet
        animatingSheet.setSource(sheet);
        glass.removeAll();
        setGridBagConstraints(animatingSheet);
        glass.setVisible(true);

        // Start animation timer
        animationStart = System.currentTimeMillis();
        if (animationTimer == null) {
            animationTimer = new Timer(ANIMATION_SLEEP, this);
        }
        animating = true;
        animationTimer.start();
    }

    private void stopAnimation() {
        animationTimer.stop();
        animating = false;
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        if (animating) {
            // Calculate height to show
            float animationPercent = (System.currentTimeMillis() - animationStart)
                    / ANIMATION_DURATION;
            animationPercent = Math.min(1.0F, animationPercent);
            int animatingWidth = 0;
            if (animationDirection == INCOMING) {
                animatingWidth = (int) (animationPercent * sheet.getWidth());
            } else {
                animatingWidth = (int) ((1.0F - animationPercent) * sheet
                        .getWidth());
            }

            // Clip off that much from the sheet and blit it
            // into the animatingSheet
            animatingSheet.setAnimatingWidth(animatingWidth);
            animatingSheet.repaint();

            if (animationPercent >= 1.0F) {
                stopAnimation();
                if (animationDirection == INCOMING) {
                    finishShowingSheet();
                } else {
                    glass.removeAll();
                    glass.setVisible(false);
                }
            }
        }
    }

    private void finishShowingSheet() {
        glass.removeAll();
        setGridBagConstraints(sheet);
        glass.revalidate();
        glass.repaint();
    }

    private void setGridBagConstraints(JComponent sheet) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.anchor = GridBagConstraints.NORTHWEST;
        glass.add(sheet, gbc);
        gbc.gridy = 1;
        gbc.weighty = Integer.MAX_VALUE;
        glass.add(Box.createGlue(), gbc);
    }

}

class AnimatingSheet extends JPanel {

    private static final long   serialVersionUID    = 3958155417286820827L;

    Dimension       animatingSize   = new Dimension(0, 1);
    JComponent      source;
    BufferedImage   offscreenImage;

    public AnimatingSheet() {
        super();
        setOpaque(true);
    }

    public void setSource(JComponent source) {
        this.source = source;
        animatingSize.height = source.getHeight();
        makeOffscreenImage(source);
    }

    public void setAnimatingWidth(int width) {
        animatingSize.width = width;
        setSize(animatingSize);
    }

    private void makeOffscreenImage(JComponent source) {
        GraphicsConfiguration gfxConfig = GraphicsEnvironment
                .getLocalGraphicsEnvironment().getDefaultScreenDevice()
                .getDefaultConfiguration();
        offscreenImage = gfxConfig.createCompatibleImage(source.getWidth(),
                source.getHeight());
        Graphics2D offscreenGraphics = (Graphics2D) offscreenImage
                .getGraphics();
        source.paint(offscreenGraphics);
        offscreenGraphics.dispose();
    }

    @Override
    public Dimension getPreferredSize() {
        return animatingSize;
    }

    @Override
    public Dimension getMinimumSize() {
        return animatingSize;
    }

    @Override
    public Dimension getMaximumSize() {
        return animatingSize;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        BufferedImage fragment = offscreenImage.getSubimage(
                offscreenImage.getWidth() - animatingSize.width, 0,
                animatingSize.width, source.getHeight());
        g.drawImage(fragment, 0, 0, this);
    }
}

以下是测试动画JFrame的代码。

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SheetTest implements PropertyChangeListener, Runnable {

    JOptionPane     optionPane;
    AnimatedJFrame  frame;

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

    @Override
    public void run() {
        // Build JOptionPane dialog
        optionPane = new JOptionPane("Do you want to save?",
                JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_OPTION);
        optionPane.addPropertyChangeListener(this);

        frame = new AnimatedJFrame("Sheet Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Put an image in the frame's content pane
        ImageIcon icon = new ImageIcon("images/Google Tile.jpg");
        JLabel label = new JLabel(icon);
        frame.getContentPane().add(label, BorderLayout.CENTER);

        JButton dropButton = new JButton("Slide sheet");
        dropButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                JDialog dialog = optionPane.createDialog(frame, "Irrelevant");
                frame.showJDialogAsSheet(dialog);
            }
        });

        frame.getContentPane().add(dropButton, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    public void propertyChange(PropertyChangeEvent event) {
        if (event.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)) {
            frame.hideSheet();
        }

    }

}

这是我用来创建测试JFrame的图像。

Google Tile