这篇还是继续讲Swing的常识,主要是针对想成为Swing“高手”的新接触的朋友。在这里想说一下题外话,Swing这种技术虽然很“老旧”,但是又有几个人能完完全全熟透Swing呢,在很多人的眼里都认为Swing很复杂,但是如果把Swing弄懂了之后,其他的JavaFX、SWT、Android的界面开发,其实也不再话下。其实界面开发都是差不多的,一个样。在这里想告诉大家一个道理,别看到新技术就一头扎进去。如果熟练掌握Swing,而又熟悉JavaFX的朋友,可能会发现JDK下的com.sun.java.swing包下的很多东西都和JavaFX的特效相似.
上两篇文章介绍完了两个非常好用的LayoutManager(MigLayout和TableLayout),今天在这里将会讲述一下CardLayout,介绍它如何使用,哪些地方存在不足。
先看看API对CardLayout的描述:它将容器中的每个组件看作一张卡片。一次只能看到一张卡片,容器则充当卡片的堆栈。当容器第一次显示时,第一个添加到 CardLayout
对象的组件为可见组件。然后我们再看看它的方法,不难发现,它的几个重要的方法如下:
first(Container) :Flips to the first card of the container.
last(Container): Flips to the last card of the container.
next(Container):Flips to the next card of the specified container.
previous(Container
)
:
Flips to the previous card of the specified container.
show(Container):Flips to the component that was added to this layout with the specified name
, using addLayoutComponent
.
下面先来看一个例子:
package org.dui.sample; import java.awt.CardLayout; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import net.miginfocom.swing.MigLayout; /** * <code>CardLayoutSample</code> demonstrates how to use the * <code>CardLayout</code> * * @author Jimmy * @since <i> DUI v1.0.0 (Apr 1,2013)</i> */ public class CardLayoutSample extends JPanel { private static final long serialVersionUID = 1L; /**Cache the index of the current displaying component*/ private int m_iCurrent = 0; { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.put("Label.font", new Font("", Font.BOLD, 20)); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Just create an instance. * */ public CardLayoutSample() { initGUI(); } /** * Init the UI * * @since <i>DUI v.1.0.0 (Apr 1, 2013)</i> */ public void initGUI() { this.setLayout(new MigLayout("ins 5", "grow,fill", "[grow,fill][fill]")); this.setPreferredSize(new Dimension(400,300)); final CardLayout layoutCard = new CardLayout(); final JPanel pnlCard = new JPanel(layoutCard); JButton btnPrev = new JButton("Prev"); JButton btnNext = new JButton("Next"); this.add(pnlCard, "cell 0 0") .add(btnPrev, "cell 0 1, gapleft push") .add(btnNext, "cell 0 1, gapright push"); final String[] aNames = {"card1","card2", "card3", "card4"}; pnlCard.add(new JLabel("Card1"), aNames[0]); pnlCard.add(new JLabel("Card2"), aNames[1]); pnlCard.add(new JLabel("Card3"), aNames[2]); pnlCard.add(new JLabel("Card4"), aNames[3]); btnPrev.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { m_iCurrent = m_iCurrent >= 1 ? --m_iCurrent : m_iCurrent; layoutCard.show(pnlCard, aNames[m_iCurrent]); } }); btnNext.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { m_iCurrent = m_iCurrent < 3 ? ++m_iCurrent : m_iCurrent; layoutCard.show(pnlCard, aNames[m_iCurrent]); } }); } /** * Add a Component specify by <code>oComp</code> to the container <code>self</code> * @param oComp * @param oConstraints * @return self * * @since <i>DUI v.1.0.0 (Apr 1, 2013)</i> */ public CardLayoutSample add(JComponent oComp, Object oConstraints){ super.add(oComp, oConstraints); return this; } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JFrame oFrame = new JFrame(); oFrame.setTitle("CardLayoutSample"); oFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); oFrame.setResizable(true); oFrame.setContentPane(new CardLayoutSample()); oFrame.pack(); oFrame.setVisible(true); oFrame.setLocationRelativeTo(null); } }); } }
看了上面的例子,细心的你可能会发现,在程序中要用m_iCurrent来记录当前CarLayout所显示的组件,其实CardLayout有两个做得不够好的地方:
1)CardLayout没有提供方法去获取当前正在显示的组件。
2)当开始显示的整个Container的时候,CardLayout里面的组件没有得到聚焦。
为了解决上面两个问题,在这里提供一个增强版的CardLayout 命名为RCardLayout。例子在这里就不再写了,如果不会使用的朋友,可以留言。
package org.dui.sample; import java.awt.CardLayout; import java.awt.Component; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.util.ArrayList; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JComponent; /** * The <code>RCardLayout</code> provides some extensions to the CardLayout * class. In particular adding support for: * * a) setting focus on the card when it is displayed b) getting the currently * displayed Card c) Next and Previous Actions This added support will only work * when a JComponent is added as a Card. * * @since <i> DUI v1.0.0 (Apr 1,2013)</i> * */ public class RCardLayout extends CardLayout implements HierarchyListener { private static final long serialVersionUID = 1L; private ArrayList<JComponent> cards = new ArrayList<JComponent>(); private JComponent firstCard; private JComponent lastCard; private JComponent currentCard; private boolean isRequestFocusOnCard = true; private Action nextAction; private Action previousAction; /** * Creates a new card layout with gaps of size zero. */ public RCardLayout() { this(0, 0); } /** * Creates a new card layout with the specified horizontal and vertical * gaps. The horizontal gaps are placed at the left and right edges. The * vertical gaps are placed at the top and bottom edges. * * @param hgap * the horizontal gap. * @param vgap * the vertical gap. */ public RCardLayout(int hgap, int vgap) { super(hgap, vgap); } // Overridden methods public void addLayoutComponent(Component comp, Object constraints) { super.addLayoutComponent(comp, constraints); if (!(comp instanceof JComponent)) return; JComponent component = (JComponent) comp; cards.add(component); if (firstCard == null) firstCard = component; lastCard = component; component.addHierarchyListener(this); } public void removeLayoutComponent(Component comp) { super.removeLayoutComponent(comp); if (!(comp instanceof JComponent)) return; JComponent component = (JComponent) comp; component.removeHierarchyListener(this); cards.remove(component); if (component.equals(firstCard) && cards.size() > 0) { firstCard = cards.get(0); } if (component.equals(lastCard) && cards.size() > 0) { lastCard = cards.get(cards.size() - 1); } } // New methods public JComponent getCurrentCard() { return currentCard; } public Action getNextAction() { return getNextAction("Next"); } public Action getNextAction(String name) { if (nextAction == null) { nextAction = new CardAction(name, true); nextAction.putValue(Action.MNEMONIC_KEY, (int) name.charAt(0)); nextAction.setEnabled(isNextCardAvailable()); } return nextAction; } public Action getPreviousAction() { return getPreviousAction("Previous"); } public Action getPreviousAction(String name) { if (previousAction == null) { previousAction = new CardAction(name, false); previousAction.putValue(Action.MNEMONIC_KEY, (int) name.charAt(0)); previousAction.setEnabled(isNextCardAvailable()); } return previousAction; } public boolean isNextCardAvailable() { return currentCard != lastCard; } public boolean isPreviousCardAvailable() { return currentCard != firstCard; } public boolean isRequestFocusOnCard() { return isRequestFocusOnCard; } public void setRequestFocusOnCard(boolean isRequestFocusOnCard) { this.isRequestFocusOnCard = isRequestFocusOnCard; } // Implement Hierarchy Listener @Override public void hierarchyChanged(HierarchyEvent e) { JComponent component = (JComponent) e.getSource(); if ((HierarchyEvent.SHOWING_CHANGED & e.getChangeFlags()) != 0 && component.isShowing()) { currentCard = component; if (isRequestFocusOnCard) currentCard.transferFocus(); if (nextAction != null) nextAction.setEnabled(isNextCardAvailable()); if (previousAction != null) previousAction.setEnabled(isPreviousCardAvailable()); } } class CardAction extends AbstractAction { private static final long serialVersionUID = 1L; private boolean isNext; public CardAction(String text, boolean isNext) { super(text); this.isNext = isNext; putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME)); } public void actionPerformed(ActionEvent e) { Container parent = getCurrentCard().getParent(); if (isNext) next(parent); else previous(parent); } } }
相关推荐
本篇文章将深入探讨Java Swing中的布局管理器,以及如何有效地利用它们来构建用户界面。 首先,我们需要理解Swing中的几种基本布局管理器。每个容器都有一个默认的LayoutManager,例如JFrame使用的是BorderLayout,...
Java Swing是Java GUI(图形用户界面)库的一部分,它提供了丰富的组件和工具,用于构建桌面应用程序。这个"Java-Swing-exercises.rar"压缩包显然包含了作者在大学期间编写的Swing控件练习,旨在帮助学习者熟悉并...
文档"javaswing教程.doc"应该包含了详细的步骤、实例代码以及最佳实践,帮助你深入理解和掌握Java Swing的界面设计技巧。 总之,Java Swing不仅是一个强大的工具集,也是开发者实现桌面应用创新设计的关键。通过这...
Swing Explorer是一款基于Java Swing库开发的辅助工具,旨在帮助开发者更轻松地理解和调试Swing应用程序。这个压缩包包含了Swing Explorer的完整源代码,为Java开发者提供了一个深入学习Swing组件和布局管理器的实践...
本篇文章将深入讲解Java Swing的基础知识、核心组件、事件处理以及实际案例应用。 一、Java Swing基础知识 1. 轻量级与重量级组件:Swing组件是轻量级的,基于Java的AWT(Abstract Window Toolkit)组件,比AWT...
BorderLayout 是 Java Swing 中的一个布局管理器,继承自 java.awt.LayoutManager 类。BorderLayout 提供了一个基本的布局管理,可以用来布局组件。在上面的代码中,我们可以看到 BorderLayout 的使用,实现了一个...
本篇将深入探讨Java Swing工具箱中的关键概念和技术。 首先,Swing 提供了大量组件(JComponents),这些组件用于构建用户界面,例如按钮(JButton)、文本框(JTextField)、列表(JList)、表格(JTable)和面板...
Java Swing 是Java GUI(图形用户界面)库的一部分,用于构建桌面应用程序。它提供了丰富的组件集合,使得开发者可以创建复杂的、交互式的用户界面。在Java Swing组件全演示中,我们将深入探讨Swing的核心概念、组件...
Java Swing 是Java平台上的一个图形用户界面(GUI)工具包,它是Java Foundation Classes (JFC)的一部分,用于构建桌面应用程序。本项目"java swing实时时钟"是一个基于Swing的简单应用,旨在帮助初学者理解如何在Java...
Java Swing是Java GUI(图形用户界面)开发的重要库,它属于Java Foundation Classes (JFC)的一部分,用于构建桌面应用程序。本资源"深入浅出Java Swing程序设计_11394260.rar"显然是一个关于Java Swing编程的详细...
在Java编程领域,中级界面篇通常涉及的是图形用户界面(GUI)的设计与开发。Java提供了丰富的库和工具来创建美观且功能强大的用户界面,其中最常用的就是Java Swing和JavaFX。下面将详细介绍这两个库以及相关的知识...
本资源包主要涵盖了两个核心库:AWT(Abstract Window Toolkit)和Swing,它们都是Java Foundation Classes (JFC) 的一部分,用于构建桌面应用程序。 **AWT** 是Java早期提供的图形用户界面(GUI)工具包,它直接与...
### Java Swing 概述 Java Swing 是 Java 平台中用于构建图形用户界面(GUI)的一个强大库。它是在 Java 2.0 版本中引入的,作为对早期 Java AWT(Abstract Window Toolkit)库的增强和扩展。Swing 的主要优势在于...
Java Swing 是Java GUI编程的重要部分,它提供了丰富的组件和功能,使得开发者能够创建美观且功能齐全的桌面应用程序。本资源“java swing(影印版)”是一部针对Java Swing的学习教材,旨在帮助学习者掌握Swing的...
Java应用程序-日记本是一款基于Java Swing开发的桌面应用,它为用户提供了一个集日记书写、截图和音乐播放功能于一体的平台。Swing是Java Standard Edition (Java SE)的一部分,用于构建图形用户界面(GUI)的库,...
Java Swing 是Java GUI(图形用户界面)开发的一个重要库,它是Java AWT(抽象窗口工具包)的扩展,提供了更多丰富的组件和功能。在Swing中,`JPanel`是常用的一种容器组件,用于组合其他组件,实现复杂的用户界面。...