扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class TabbedPaneExample implements ActionListener { private JFrame frame; private JTabbedPane tabbedPane; private JButton addTabButton; private ImageIcon closeXIcon; private Dimension closeButtonSize; private int tabCounter = 0; public TabbedPaneExample() { //创建选项卡面板 tabbedPane = new JTabbedPane(); //创建一个按钮-用户可用来添加一个选项卡到选项卡面板 addTabButton = new JButton("Add Tab"); addTabButton.addActionListener(this); //创建一个框架来包含这个选项卡面板 frame = new JFrame(); //创建一个图像图标'X'以实现在每一个选项卡上的关闭功能。加载的gif是一个10x10图形(非黑色部分是透明的) closeXIcon = new ImageIcon("C:/CloseX.gif"); //创建一个Dimension用来调整close按钮的大小 closeButtonSize = new Dimension( closeXIcon.getIconWidth()+2, closeXIcon.getIconHeight()+2); //所选项卡面板添加到图形中央,把"Add Tab"按钮置于南面。然后包装它,调整其大小并显示它。 frame.add(tabbedPane, BorderLayout.CENTER); frame.add(addTabButton, BorderLayout.SOUTH); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setMinimumSize(new Dimension(300, 300)); frame.setVisible(true); } public void actionPerformed(ActionEvent e) { final JPanel content = new JPanel(); //创建一个描述该选项卡的面板并确保它是透明的 JPanel tab = new JPanel(); tab.setOpaque(false); //为该选项卡创建一个标签和一个Close按钮。一定要 //把它的尺寸设置为几乎该图标的大小,并且 //创建一个行为听取器-它将定位该选项卡并且从选项卡面板上删除它 JLabel tabLabel = new JLabel("Tab " + (++tabCounter)); JButton tabCloseButton = new JButton(closeXIcon); tabCloseButton.setPreferredSize(closeButtonSize); tabCloseButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int closeTabNumber = tabbedPane.indexOfComponent(content); tabbedPane.removeTabAt(closeTabNumber); } }); tab.add(tabLabel, BorderLayout.WEST); tab.add(tabCloseButton, BorderLayout.EAST); //把该选项卡添加到选项卡面板。注意, //第一个参数(它正常是一个描述选项卡标题的String //),为null. tabbedPane.addTab(null, content); //不是在选项卡上使用String/Icon的结合, //而是使用我们的面板。 tabbedPane.setTabComponentAt(tabbedPane.getTabCount()-1, tab); } public static void main(String[] args) { TabbedPaneExample main = new TabbedPaneExample(); } } |
结果显示于图1中。
图1.一个把多个JComponent用作选项卡的JTabbedPane
注意,Alexander Potochkin的博客中提供了另外一种不同的方法,它子类化JButton-重载paintComponent()并且画出它自己的("X")。如果你不想使用你的代码发布一个gif文件,那么使用这种更为复杂的方法是非常有用的。
四、 SwingWorker现在包含到Mustang中
大多数Swing程序员知道,无论什么时候编写事件驱动的代码,例如当一个按钮按下时调用ActionListener,都需要快速处理事件。你永远不需要花费比你必须处理事件驱动的线程更多的时间,否则,你的Swing GUI将成为不可响应并且不能有效地重绘它自己。在事件调度线程中实现一项较大的任务经常意味着你要从事件调度线程中"剔除"一个独立工作者线程并且让该线程运行于后台。这样以来,当使用Swing编写一个多线程的应用程序时,程序员需要牢记下面两条规则:
因为这意味着,至少有两个线程在同时运行,因此创建一个处理线程间通讯的类是很有帮助的。有一个消息是,最新的Mustang发行版本中加入了对SwingWorker类(它是前一段时间Swing程序员使用的一种流行的解决方案)的支持。
下面是来自于Javadoc的SwingWorker的正式声明。
public abstract class SwingWorker<T,V> extends Object
implements RunnableFuture<T>
注意,这里的声明包含了两个泛型类型变量:T和V。如果你还不熟悉泛型类型变量的话,那么你可以先读一下有关泛型的基础知识,这是在J2SE 5.0中引入的一种特性。下面是定义:
一会之后,我们再讨论这些方法。然而,首先,让我们介绍一下SwingWorker中所使用的线程架构。这里援引Javadoc的描述:在一个SwingWorker的生命周期中共包含三个线程:
典型地,你在其上实例化SwingWorker子类的当前线程是事件调度线程。这个SwingWorker通常响应下列一些事件:
当在doInBackground()方法中时,你可以设置一个整型的progress属性-它使用下列方法指示工作者线程的当前进度:
protected void setProgress(int progress); |
一旦调用这个方法,SwingWorker就向所有的已经登记的听者激发一个属性事件来通知它们已经得到更新的进度值。
你可以设置或添加工作者线程的最后结果-通过使用下面两个方法之一:
protected void process(V... chunks); protected void publish(V... chunks); |
第二个方法,publish(),将使用一些中间类型V的一些可变个数的对象并且把它们发送到process()方法中进行处理。典型情况下,你将从doInBackground()线程中调用process()方法。这个process()方法应该总是被重载以接收输入的V参数并且把这些中间对象以某种形式连接成一个T类型。当然,至于process()方法如何实现这一任务要依赖于参数类型-它在你的SwingWorker子类中指定。
同时,在当前线程中,你可以调用两个get()方法之一来检索工作者线程的结果。第一个get()方法,在工作者线程完成其任务之前将会无限地阻塞。第二个方法在检索已经被处理的结果宽之前将阻塞一段指定的时间。
public T get(); public T get(long timeout,TimeUnit unit); |
如果你希望取消这个工作者线程,那么在它完成执行之前,你可以从当前线程中调用cancel()方法。
public final boolean cancel(boolean mayInterruptIfRunning) |
这里的mayInterruptIfRunning参数指定,在试图停止这项任务时是否执行该任务的线程应该被中断。注意,调用cancel()方法将失败-如果该任务已经完成,如果该任务已经被取消或如果它因某些理由可能无法被取消。然而,如果该方法调用返回true并且当调用cancel()方法时这项任务还没有开始,那么SwingWorker永远不应该执行。
五、 结论
尽管本文中介绍的这些特征基本上相互独立,但是它们的确代表Mustang开发团队希望满足Java开发社区提出的一小部分实现请求。特别是,当创建Swing应用程序时,学习使用SwingWorker类是必须的-它可以把程序员从复杂的GUI线程问题中解脱出来。记住,和往常一样,这些特征在最终成为Java SE 6的最后发行版本之前要征得JSR 270专家组的同意。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者