zoukankan      html  css  js  c++  java
  • 【Java】Swing-LookAndFeel 初解

    参考:

    https://blog.csdn.net/sureyonder/article/details/5695420?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-14&spm=1001.2101.3001.4242

    https://www.cnblogs.com/zhchoutai/p/8726824.html

     

    Swing/LookAndFeel 优美的 MVC 模式会给你一个良好的编程思想。

    Swing 是什么?

    Swing 是 Java 官方推出的,绝大部分控件都由 Graphics2D 绘制的一种轻量级 GUI 方案。其全部的轻量级控件都继承自 JComponent 类。

    须要注意的是,Swing 中依旧有三个重量级控件:JFrame,JDialog,JWindow。只是它们都是窗口,他们都继承自 Window 类。

    而不管是 JComponent 还是 Window 它们都继承自 Container 类,这事实上也就意味着:全部的 Swing 控件,都能够做控件容器

    Swing 是怎样通过 Graphics2D 绘制这些控件的呢?

    答案就是 LookAndFeel 机制。

    通俗的说,这就是皮肤

    从功能上说。这是一种批量管理 Swing 控件外观的机制;

    从根源来说,这是 Swing 的核心。

    官方在 Java 7 中正式推出的 NimbusLookAndFeel 则要美观的多。

    你问怎样换 LookAndFeel?

    在启动你的程序前:

    UIManager.setLookAndFeel(…);

    就可以

    假设是在程序已经启动之后再换 LookAndFeel,那在上面那句之后,建议再加上:

    SwingUtilities.updateComponentTreeUI(…);

    所谓 MVC 就是:模型(Model)、视图(View)、控制器(Controller)这种一种结构。

    Swing 中,差点儿全部的控件都能够清晰的分解成这三大部分。

    就拿 JButton 来举例,我们能够这样分解:

    JButton——控制器;

    ButtonModel——模型。其最常见的详细实现类是:DefaultButtonModel。

    ButtonUI——视图,其最常见的详细实现类是:MetalButtonUI;

    JButton 负责控制,ButtonModel 提供模型,而 ButtonUI 实现展示。

    也就是说,基本上全部的 Swing 控件都是由一个 Control 类、一个 Model 类、一个 UI 类组成的。

    部分过于简单和数据无关的控件无 Model 类,比如 JPanel……

    Swing 是怎样通过 UI 类来绘制控件的呢?

     Swing 控件在 UI 线程中的绘制过程:

    会产生一个 PaintEvent 然后排入 UI 线程的事件处理序列;

    而 UI 线程在处理 Swing 控件的 PaintEvent 时,终于都会调用到控件的 paint 方法。

    通过源码分析,总结如下:

    一个控件要绘制,就必定调用到它的 paint 方法;

    而默认的 paint 方法中会调用到 paintComponent 方法;

    paintComponent 方法中又会调用 UI 类的 update 方法;

    也就是说,一个控件的绘制,和其 UI 类中的 update 方法是息息相关的。

    看,UI 类成功的和控件绘制关联上了。

    各个控件的 UI 类又是怎么被设置到 Control 类中的呢?

    这里要提到一个非常重要的类——UIManager

    在 LookAndFeel 机制中,会有大量的键值对存放在一个 UIDefaults(事实上就是个 HashTable)中。

    这些键值对记录了控件的边框、各种部分的颜色、字体等等,当中也包含了这个控件相应的 UI 类的类名。

    而 UIManager 就是方便我们调用或替换这些键值对的一个管理工具类。

    通过源码分析,原来是通过控件类中的 getUIClassID 返回的“键”。来获得 UI 类的类名在 UIDefaults 中的“值”。然后反射生成 UI 类的对象。

    总结如下:

    在控件构造时,都会去调用 updateUI 方法;

    在控件的 updateUI 方法中,会通过 UIManager.getUI 去获取 ui 对象;

    而 getUIClass(target.getUIClassID(), uiClassLoader),是通过控件的 uiClassID 这个“键”去获得 UIDefaults 中的相应的“值”;

    而最后依据返回的类名,反射生成一个 UI 类的对象(PanelUI),返回给 updateUI 方法;

    再通过 setUI 方法赋值给 ui 成员变量。

    假设你打算自己写一套 LookAndFeel,当你写了一个 UI 类之后应该怎么和控件相应上呢?

    答案就是改写 LookAndFeel 类中的 initClassDefaults 方法,设置相应的组件对。

    例如源码:MetalLookAndFeel 类,initClassDefaults 方法:

    protected void initClassDefaults(UIDefaults table)
        {
            super.initClassDefaults(table);
            final String metalPackageName = "javax.swing.plaf.metal.";
            Object[] uiDefaults = {
                       "ButtonUI", metalPackageName+ "MetalButtonUI",
                     "CheckBoxUI", metalPackageName+ "MetalCheckBoxUI",
                     "ComboBoxUI", metalPackageName + "MetalComboBoxUI",
                  "DesktopIconUI", metalPackageName + "MetalDesktopIconUI",
                  "FileChooserUI", metalPackageName + "MetalFileChooserUI",
                "InternalFrameUI", metalPackageName + "MetalInternalFrameUI",
                        "LabelUI", metalPackageName + "MetalLabelUI",
           "PopupMenuSeparatorUI", metalPackageName + "MetalPopupMenuSeparatorUI",
                  "ProgressBarUI", metalPackageName + "MetalProgressBarUI",
                  "RadioButtonUI", metalPackageName + "MetalRadioButtonUI",
                    "ScrollBarUI", metalPackageName + "MetalScrollBarUI",
                   "ScrollPaneUI", metalPackageName + "MetalScrollPaneUI",
                    "SeparatorUI", metalPackageName + "MetalSeparatorUI",
                       "SliderUI", metalPackageName + "MetalSliderUI",
                    "SplitPaneUI", metalPackageName + "MetalSplitPaneUI",
                   "TabbedPaneUI", metalPackageName + "MetalTabbedPaneUI",
                    "TextFieldUI", metalPackageName + "MetalTextFieldUI",
                 "ToggleButtonUI", metalPackageName + "MetalToggleButtonUI",
                      "ToolBarUI", metalPackageName + "MetalToolBarUI",
                      "ToolTipUI", metalPackageName + "MetalToolTipUI",
                         "TreeUI", metalPackageName + "MetalTreeUI",
                     "RootPaneUI", metalPackageName + "MetalRootPaneUI",
            };
            table.putDefaults(uiDefaults);
        }
  • 相关阅读:
    java实现文件上传下载至ftp服务器
    理解java代理模式
    [置顶] 理解java中的线程池
    wait,notify,非阻塞队列实现生产者,消费者模型
    理解java阻塞队列BlockingQueue
    CentOS下安装配置Nginx
    putty笔记
    CentOs下安装jdk、MySql、Redis笔记
    简述yum和apt-get的区别
    Linux 文件颜色说明
  • 原文地址:https://www.cnblogs.com/cathygx/p/14350736.html
Copyright © 2011-2022 走看看