0

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

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

在此处输入图像描述

这是它没有出现时的图片(背景中的第二个窗口只是第一个图像[上面的那个],因为当我拍摄屏幕截图时浏览器在框架中): 在此处输入图像描述

4

2 回答 2

2

两种方法:

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

  2. 使用CardLayout. 好处是您的布局将按照您询问是否调整大小的方式运行。缺点是你不会得到重叠效果。您的滑出式面板右侧将只有空白区域。

编辑:我刚刚注意到你的滑出没有重叠,而是向外延伸到右边。我最初以为您的意思是类似于旧的 Outlook UI。在那种情况下,它可以是滑出式的,还是必须固定在框架上?

这是一个粗略的演示,它简单地使用 aBorderLayout作为效果。我在这个演示和截图之间看到的最大区别是:

  1. 框架的边框随着演示中的滑出而延伸
  2. 滑出式面板在演示中没有偏移。

代码:

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;
  }
}
于 2013-05-10T14:24:46.317 回答
2

在一本书Swing Hacks的帮助下,我创建了一个可滑动的 JFrame 和一个可滑动的 JDialog。我花了几个小时来调试代码。

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

表测试部分

并且一路走来。

测试表

基本上,我采用了 JOptionPane 的内容窗格,并将其动画化为图像。

您左键单击幻灯片按钮以将 JOptionPane 滑出。您左键单击 JOptionPane 上的 Yes 或 No 以将 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 的图像。

谷歌瓷砖

于 2013-05-13T13:32:57.963 回答