这篇还是继续讲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); } } }
相关推荐
NULL 博文链接:https://jimmyhr.iteye.com/blog/1836639
NULL 博文链接:https://jimmyhr.iteye.com/blog/1839473
BorderLayout 是 Java Swing 中的一个布局管理器,继承自 java.awt.LayoutManager 类。BorderLayout 提供了一个基本的布局管理,可以用来布局组件。在上面的代码中,我们可以看到 BorderLayout 的使用,实现了一个...
Java Swing开发LayoutManager的应用以及各种Layout的比较
集合原始java org.htmllayout HtmlLayout-出色的Java LayoutManager版权所有(C)1998 Paul Buchheit HtmlLayout是一个Java LayoutManager,它允许您使用简单的类似html的语法(无需学习其他语言)来指定组件的布局...
促进和加快涉及Java swing的GUI开发。 在花了数小时的时间来尝试选择正确的LayoutManager并使它按照您希望的方式工作之后,您感到沮丧了多少次。 多少次哟
使构建Java GUI程序变得容易。 易于构建的菜单,工具栏,向导等。提供了一些LayoutManager来简化UI的构建。
在本文中,引入的类库包括 java.awt、java.awt.event、java.applet、javax.swing、java.io.PrintStream、javax.swing.JComponent、javax.swing.JPanel 等。 二、Swing 图形用户界面编程 1. JFrame 和 JPanel 组件...
这是一个 LayoutManager 支持调整大小并尊重组件的最小和最大尺寸。
Swing 组件是建立在 AWT 之上的一个高级 GUI 组件,提供了更多的 GUI 设计工具。 二、事件处理模型 事件处理模型是 GUI 组件的核心,负责处理用户的交互事件,如按钮点击、鼠标移动、键盘输入等。Java 语言中的...
在Java GUI设计中,还有很多辅助类,例如Graphics类、Color类、Font类、FontMetrics类、Dimension类和LayoutManager接口等。这些类都不是Component的子类,它们用来描述GUI组件的属性,例如颜色、字体、大小等。 ...
Java 的 GUI 界面定义是由 AWT 类包和 Swing 类包来完成的。它在布局管理上采用了容器和布局管理分离的方案。容器只管将其他组件放入其中,而不管这些组件是如何放置的。对于布局的管理交给专门的布局管理器类 ...
Java的GUI界面定义是由awt类和swing类来完成的。它在布局管理上面采用了容器和布局管理分离的方案。也是说,容器只管将其他小件放入其中,而不管这些小件是如何放置的。对于布局的管理交给专门的布局管理器类...
Swing 是 Java 的一个图形用户界面(GUI)库,提供了许多图形组件,例如按钮、标签、文本框等。 在登录界面中,使用了 JTextField 组件作为用户名和密码的输入框,使用了 JButton 组件作为登录按钮。登录按钮的点击...
BaggieLayout是一个Java swing LayoutManager,功能与GridBagLayout一样强大,但非常易于使用。 使用简单的XML或JavaBean约束进行定位。 与其他LayoutManager不同,服从最小/最大/首选大小,并且在调整大小时组件...
MSBLayout是用于Java AWT和Swing的LayoutManager,它结合了BoxLayout的嵌套框方法和GridBagLayout使用的灵活约束。 简洁的API可以最大限度地减少获得具有最佳尺寸调整行为的良好布局所需的代码
在swing里,this.setLayout(null);可以让你随意放置控件,但是resize后不会比例缩放。NullScaleLayoutManager解决该问题,在this.setLayout(null);的基础上,你的控件可以在resize后按比例缩放。 ok,try.