共享模仿QQ好友列表,点击表头展开对应Tab的源码。
Tab的展开使用动画,有兴趣的还可以去看看Easing的各种动画效果。
package com.tur.demo;import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;/**
* 模仿QQ好友列表的布局, 展开一个tab的同时,其他tab被隐藏.
*
* 主要使用API:
* 1. addTab: 添加一个新的tab
* 2. removeTab: 删除一个tab,这个方法有待改进
* 3. setExpandedTabIndex: 指定要展开的tab,默认所有的tab都是收缩起来的。界面初始化的时候经常有必要调用这个方法设置一个tab是展开的.
*
* tab的标题栏如果想要好看一些,可以使用图片美化,也可以手动绘制好一点的样式。
*/
public class ScrollingTabPane extends JComponent {
private TableLayout layout;
private List<Tab> tabs;
private MouseListener mouseListener; private int expandedTabIndex = 0; // 被展开的tab的index
public static final int COLLAPSE_TAB_HEIGHT = 30; // 收陇的tab标签的高度 public ScrollingTabPane() {
tabs = new LinkedList<Tab>();
mouseListener = new TabMouseListener();
layout = new TableLayout(new double[]{TableLayout.FILL}, new double[]{});
setLayout(layout);
} /**
* 添加一个新的tab
* @param com - 要添加到tab里的组件
*/
public void addTab(JComponent com, String title) {
Tab tab = new Tab(com, title);
tabs.add(tab); int rowCount = layout.getNumRow();
layout.insertRow(rowCount, COLLAPSE_TAB_HEIGHT);
add(tab, "0, " + rowCount);
} /**
* 删除第index个tab
* @param index - 删除的tab的index
*/
public void removeTab(int index) {
if (index < 0 || index >= tabs.size()) { return; } Container tab = tabs.get(index);
int row = layout.getConstraints(tab).row1; // 必须同时从layout和component中移除
remove(tab);
tabs.remove(tab);
layout.deleteRow(row); if (row == expandedTabIndex) {
// 如果删除的是展开的tab,则展开它下面的tab
setExpandedTabIndex(expandedTabIndex);
} else if (row < expandedTabIndex) {
// 如果删除的tab在展开的tab上面,则展开的tab的index减一
--expandedTabIndex;
} invalidate();
validate();
} /**
* 取得当前展开的tab的index
* @return - 当前展开的tab的index
*/
public int getExpandedTabIndex() {
return expandedTabIndex;
} /**
* 设置展开的tab的index,然后展开此tab并把其他的tab的高度设置为TAB_HEIGHT.
* @param expandedTabIndex - 需要被展开的tab的index
*/
public void setExpandedTabIndex(int expandedTabIndex) {
this.expandedTabIndex = expandedTabIndex; for (int i = 0; i < layout.getNumRow(); ++i) {
layout.setRow(i, COLLAPSE_TAB_HEIGHT);
} layout.setRow(expandedTabIndex, TableLayout.FILL); invalidate();
validate();
} /**
* 使用动画展开tab
* @param tab - 需要展开的tab
*/
private synchronized void expandingTab(Tab tab) {
TableLayoutConstraints constraints = layout.getConstraints(tab);
int row = constraints.row1; if (row == expandedTabIndex) { return; } int delay = 1000 / 250;
int counter = 0;
double height = 0;
double tabHeight = layout.getRow(row);
double maxTabHeight = getHeight() - COLLAPSE_TAB_HEIGHT * (layout.getNumRow() - 1);
double deltaHeight = maxTabHeight - tabHeight;
double stepRadian = Math.PI * 0.01; while (height < maxTabHeight) {
// sin的函数趋势是先快后慢, sin值的范围是[-1, 1].
// 使用sin是为了展开tab结束的时候比开展的过程中慢一些,以致展开动画结束的效果平滑一些.
height = tabHeight + deltaHeight * Math.sin(stepRadian * counter++);
layout.setRow(row, height); invalidate();
validate(); try { Thread.sleep(delay); } catch(InterruptedException e) {}
} layout.setRow(row, TableLayout.FILL);
layout.setRow(expandedTabIndex, COLLAPSE_TAB_HEIGHT);
expandedTabIndex = row; invalidate();
validate();
} /**
* 鼠标点击tab时的事件
*/
private class TabMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
final TabTitleBar titleBar = (TabTitleBar) e.getSource();
final Tab tab = (Tab) titleBar.getParent();
final TableLayoutConstraints constraints = layout.getConstraints(tab); if (expandedTabIndex != constraints.row1) {
new Thread() {
public void run() {
expandingTab(tab);
}
}.start();
}
}
} /**
* 第个tab包含标题栏和内容区域
*/
private class Tab extends Container {
JLabel titleBar; public Tab(JComponent com, String title) {
titleBar = new TabTitleBar(title); double[] row = {TableLayout.FILL};
double[] col = {COLLAPSE_TAB_HEIGHT, TableLayout.FILL};
setLayout(new TableLayout(row, col)); add(titleBar, "0, 0");
add(com, "0, 1");
}
} /**
* 每个tab的标题栏
*/
private class TabTitleBar extends JLabel {
public TabTitleBar(String title) {
super(title); setHorizontalAlignment(SwingConstants.CENTER);
setOpaque(true);
setBorder(BorderFactory.createEtchedBorder());
addMouseListener(mouseListener);
}
} /**
* 创建frame并显示
*/
private static void createAndShowGui() {
JFrame frame = new JFrame("Scrolling TabPane Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(270, 600);
frame.setLocationRelativeTo(null); ScrollingTabPane tabPane = new ScrollingTabPane();
List<JComponent> coms = new ArrayList<JComponent>(); JPanel panel = new JPanel();
panel.add(new JButton("Button"));
panel.add(new JSlider(0, 100, 40));
panel.add(new JCheckBox("Check Box"));
panel.add(new JRadioButton("Radio Button")); coms.add(panel);
coms.add(new JPanel());
coms.add(new JPanel());
coms.add(new JPanel());
coms.add(new JTextArea("Text Area"));
coms.add(new JPanel()); Random rand = new Random(System.nanoTime());
for (int i = 0; i < coms.size(); ++i) {
JComponent com = coms.get(i); tabPane.addTab(com, "Tab " + i); // Add a new tab // Set the tab's background using random color
if (com instanceof JPanel) {
com.setBackground(new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)));
}
} // Expanding the second tab
tabPane.setExpandedTabIndex(0); tabPane.removeTab(2); // 删除第2个tab frame.getContentPane().add(tabPane);
frame.setVisible(true);
} public static void main(String[] args) {
createAndShowGui();
}
}
qq
Tab的展开使用动画,有兴趣的还可以去看看Easing的各种动画效果。
package com.tur.demo;import info.clearthought.layout.TableLayout;
import info.clearthought.layout.TableLayoutConstraints;import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;/**
* 模仿QQ好友列表的布局, 展开一个tab的同时,其他tab被隐藏.
*
* 主要使用API:
* 1. addTab: 添加一个新的tab
* 2. removeTab: 删除一个tab,这个方法有待改进
* 3. setExpandedTabIndex: 指定要展开的tab,默认所有的tab都是收缩起来的。界面初始化的时候经常有必要调用这个方法设置一个tab是展开的.
*
* tab的标题栏如果想要好看一些,可以使用图片美化,也可以手动绘制好一点的样式。
*/
public class ScrollingTabPane extends JComponent {
private TableLayout layout;
private List<Tab> tabs;
private MouseListener mouseListener; private int expandedTabIndex = 0; // 被展开的tab的index
public static final int COLLAPSE_TAB_HEIGHT = 30; // 收陇的tab标签的高度 public ScrollingTabPane() {
tabs = new LinkedList<Tab>();
mouseListener = new TabMouseListener();
layout = new TableLayout(new double[]{TableLayout.FILL}, new double[]{});
setLayout(layout);
} /**
* 添加一个新的tab
* @param com - 要添加到tab里的组件
*/
public void addTab(JComponent com, String title) {
Tab tab = new Tab(com, title);
tabs.add(tab); int rowCount = layout.getNumRow();
layout.insertRow(rowCount, COLLAPSE_TAB_HEIGHT);
add(tab, "0, " + rowCount);
} /**
* 删除第index个tab
* @param index - 删除的tab的index
*/
public void removeTab(int index) {
if (index < 0 || index >= tabs.size()) { return; } Container tab = tabs.get(index);
int row = layout.getConstraints(tab).row1; // 必须同时从layout和component中移除
remove(tab);
tabs.remove(tab);
layout.deleteRow(row); if (row == expandedTabIndex) {
// 如果删除的是展开的tab,则展开它下面的tab
setExpandedTabIndex(expandedTabIndex);
} else if (row < expandedTabIndex) {
// 如果删除的tab在展开的tab上面,则展开的tab的index减一
--expandedTabIndex;
} invalidate();
validate();
} /**
* 取得当前展开的tab的index
* @return - 当前展开的tab的index
*/
public int getExpandedTabIndex() {
return expandedTabIndex;
} /**
* 设置展开的tab的index,然后展开此tab并把其他的tab的高度设置为TAB_HEIGHT.
* @param expandedTabIndex - 需要被展开的tab的index
*/
public void setExpandedTabIndex(int expandedTabIndex) {
this.expandedTabIndex = expandedTabIndex; for (int i = 0; i < layout.getNumRow(); ++i) {
layout.setRow(i, COLLAPSE_TAB_HEIGHT);
} layout.setRow(expandedTabIndex, TableLayout.FILL); invalidate();
validate();
} /**
* 使用动画展开tab
* @param tab - 需要展开的tab
*/
private synchronized void expandingTab(Tab tab) {
TableLayoutConstraints constraints = layout.getConstraints(tab);
int row = constraints.row1; if (row == expandedTabIndex) { return; } int delay = 1000 / 250;
int counter = 0;
double height = 0;
double tabHeight = layout.getRow(row);
double maxTabHeight = getHeight() - COLLAPSE_TAB_HEIGHT * (layout.getNumRow() - 1);
double deltaHeight = maxTabHeight - tabHeight;
double stepRadian = Math.PI * 0.01; while (height < maxTabHeight) {
// sin的函数趋势是先快后慢, sin值的范围是[-1, 1].
// 使用sin是为了展开tab结束的时候比开展的过程中慢一些,以致展开动画结束的效果平滑一些.
height = tabHeight + deltaHeight * Math.sin(stepRadian * counter++);
layout.setRow(row, height); invalidate();
validate(); try { Thread.sleep(delay); } catch(InterruptedException e) {}
} layout.setRow(row, TableLayout.FILL);
layout.setRow(expandedTabIndex, COLLAPSE_TAB_HEIGHT);
expandedTabIndex = row; invalidate();
validate();
} /**
* 鼠标点击tab时的事件
*/
private class TabMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
final TabTitleBar titleBar = (TabTitleBar) e.getSource();
final Tab tab = (Tab) titleBar.getParent();
final TableLayoutConstraints constraints = layout.getConstraints(tab); if (expandedTabIndex != constraints.row1) {
new Thread() {
public void run() {
expandingTab(tab);
}
}.start();
}
}
} /**
* 第个tab包含标题栏和内容区域
*/
private class Tab extends Container {
JLabel titleBar; public Tab(JComponent com, String title) {
titleBar = new TabTitleBar(title); double[] row = {TableLayout.FILL};
double[] col = {COLLAPSE_TAB_HEIGHT, TableLayout.FILL};
setLayout(new TableLayout(row, col)); add(titleBar, "0, 0");
add(com, "0, 1");
}
} /**
* 每个tab的标题栏
*/
private class TabTitleBar extends JLabel {
public TabTitleBar(String title) {
super(title); setHorizontalAlignment(SwingConstants.CENTER);
setOpaque(true);
setBorder(BorderFactory.createEtchedBorder());
addMouseListener(mouseListener);
}
} /**
* 创建frame并显示
*/
private static void createAndShowGui() {
JFrame frame = new JFrame("Scrolling TabPane Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(270, 600);
frame.setLocationRelativeTo(null); ScrollingTabPane tabPane = new ScrollingTabPane();
List<JComponent> coms = new ArrayList<JComponent>(); JPanel panel = new JPanel();
panel.add(new JButton("Button"));
panel.add(new JSlider(0, 100, 40));
panel.add(new JCheckBox("Check Box"));
panel.add(new JRadioButton("Radio Button")); coms.add(panel);
coms.add(new JPanel());
coms.add(new JPanel());
coms.add(new JPanel());
coms.add(new JTextArea("Text Area"));
coms.add(new JPanel()); Random rand = new Random(System.nanoTime());
for (int i = 0; i < coms.size(); ++i) {
JComponent com = coms.get(i); tabPane.addTab(com, "Tab " + i); // Add a new tab // Set the tab's background using random color
if (com instanceof JPanel) {
com.setBackground(new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)));
}
} // Expanding the second tab
tabPane.setExpandedTabIndex(0); tabPane.removeTab(2); // 删除第2个tab frame.getContentPane().add(tabPane);
frame.setVisible(true);
} public static void main(String[] args) {
createAndShowGui();
}
}
解决方案 »
- java 集合
- 请高手帮忙写下大数的四则运算
- java图像到视频
- C# 和 Java 本是同根生,相煎何太急!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!!!!!!!!!!!
- 菜鸟问 public void actionPerformed(ActionEvent e)中的e表示什么!?
- 问高手一个问题,求如下功能的代码
- 求解高效方案:一个程序实现5000个线程?
- 高分求助,如何用java写一个抓屏程序。
- javascript中的“window.document.images[the_image].src = "ant.gif";”语句中的.src是意思?
- JAVA可否操作内存以及寄存器
- 运行包含junit测试的jar
- javaSE 能做什么创新软件?
不过这在windows下,很难看美化一下
不过需要添加苹果风格的美化jar包
下载地址:
http://download.csdn.net/detail/kiritor/5109445代码中main方法中添加:
public static void main(String[] args) {
System.setProperty("Quaqua.tabLayoutPolicy", "wrap");
if (!System.getProperty("os.name").toLowerCase().startsWith("mac")) { // 如果不是Mac
// os
// x,则更改窗体样式。
try {
Methods.invokeStatic(JFrame.class,
"setDefaultLookAndFeelDecorated", Boolean.TYPE,
Boolean.TRUE); // 主窗体样式
Methods.invokeStatic(JDialog.class,
"setDefaultLookAndFeelDecorated", Boolean.TYPE,
Boolean.TRUE); // 子窗体样式
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
try {
UIManager
.setLookAndFeel("ch.randelshofer.quaqua.QuaquaLookAndFeel");
} catch (Exception e) {
}
createAndShowGui();
}
以前用XP的主题美化效果也只能达到这样了。
要想更好的效果,得用WindowBlinds了。