Java 使用swing创建滑出工具面板
我真的不知道怎么做。我想有一个面板“滑出”从下面的当前一个当用户点击一个按钮。然后,当他们再次单击按钮时,它将滑回 这是我的意思的一个例子。请注意,它看起来像是在左侧窗口的“下方”,并且它没有完全(但几乎)延伸到底部和顶部: 这是它不在外时的一张图片(背景中的第二个窗口只是第一个图像[上面的一个],因为我拍摄屏幕快照时浏览器在框架中): 有两种方法:Java 使用swing创建滑出工具面板,java,eclipse,swing,user-interface,Java,Eclipse,Swing,User Interface,我真的不知道怎么做。我想有一个面板“滑出”从下面的当前一个当用户点击一个按钮。然后,当他们再次单击按钮时,它将滑回 这是我的意思的一个例子。请注意,它看起来像是在左侧窗口的“下方”,并且它没有完全(但几乎)延伸到底部和顶部: 这是它不在外时的一张图片(背景中的第二个窗口只是第一个图像[上面的一个],因为我拍摄屏幕快照时浏览器在框架中): 有两种方法: 使用JLayeredPane。好的一面是你得到了你想要的重叠效果。缺点是JLP使用空布局,这意味着您的UI在不付出额外努力的情况下无法很好地调整
JLayeredPane
。好的一面是你得到了你想要的重叠效果。缺点是JLP使用空布局,这意味着您的UI在不付出额外努力的情况下无法很好地调整大小卡片布局
。有利的一面是,如果调整大小,您的布局将按照您的要求进行操作。缺点是你不会得到重叠效果。您的滑出式面板右侧将只有空白BorderLayout
来实现效果。我看到这个演示和截图之间的最大区别是:
JLayeredPane
。好的一面是你得到了你想要的重叠效果。缺点是JLP使用空布局,这意味着您的UI在不付出额外努力的情况下无法很好地调整大小卡片布局
。有利的一面是,如果调整大小,您的布局将按照您的要求进行操作。缺点是你不会得到重叠效果。您的滑出式面板右侧将只有空白BorderLayout
来实现效果。我看到这个演示和截图之间的最大区别是:
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和一个滑动JDialog。调试代码花了我几个小时
下面是一个测试运行,显示JOptionPane滑出了一部分
一路走来
基本上,我使用了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();
}
}
}
这是我用来创建测试框架的图像
或跨平台?一个问题是Swing无法在JFrame外部喷漆。如果您的滑动区域滑过面板,而不是滑过面板下方,您的运气可能会更好。否则,你的JFrame中必须有一个空白区域来为滑动区域保留空间。@GilbertLeBlanc好的,让我们假设它像一个或跨平台一样从侧面滑入?一个问题是Swing不能在JFrame外绘画。如果您的滑动区域滑过面板,而不是滑过面板下方,您的运气可能会更好。否则你就必须在JFrame中有一个空白区域来为滑动区域保留空间。@GilbertLeBlanc好的,让我们假设它像+1(但可能是4:-)3那样从侧面滑入。不带分隔符的JSplitPane,从Swing计时器4调用。JLayer(基于JXayer-Java6)我不知道;这看起来像是对等组件房地产。它被锚定在主框架上,因为它应该随主框架一起移动。如果有帮助的话,它不需要,也不应该是可调整大小的。我怎样才能使它滑出呢?@mKorbel,可能是跨平台的。更多关于滑动;更多关于分割窗格动画的信息。+1(但可能是四个:-)3。不带分隔符的JSplitPane,从Swing计时器4调用。JLayer(基于JXayer-Java6)我不知道;这看起来像是对等组件房地产。它被锚定在主框架上,因为它应该随主框架一起移动。如果有帮助的话,它不需要,也不应该是可调整大小的。我怎样才能使它滑出呢?@mKorbel,可能是跨平台的。更多关于滑动;有关拆分窗格动画的详细信息。