为组件设定UI
-----------------siwuxie095
工程名:CustomizeSwing
包名:com.siwuxie095.swing
类名:MyFrame.java(主类)、MyPanel.java、MyButtonUI.java
工程结构目录如下:
MyFrame.java(主类):
package com.siwuxie095.swing; import java.awt.Color; import java.awt.Component; import java.awt.EventQueue; import java.awt.Point; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import javax.swing.GroupLayout; import javax.swing.GroupLayout.Alignment; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.border.EmptyBorder; public class MyFrame extends JFrame { //将原本声明的 JPanel 注释掉,改为 MyPanel //private JPanel contentPane; private MyPanel contentPane;
//坐标:记录鼠标(mouse)的位置和窗体(JFrame)的位置 int mx,my,jfx,jfy; //鼠标的初始位置 Point orgin=new Point(); /** * Launch the application. */ public static EventQueue.invokeLater(new Runnable() { public try { MyFrame frame = new MyFrame(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public MyFrame() {
//为 JFrame 添加鼠标按下和拖拽的事件:在窗体上按下鼠标可以拖拽窗体 //(如果给 contentPane 添加同样的事件是等效的) //注意:(1)(2)是一组设置方法,(3)(4)是另一组设置方法 //(3)(4)要优于(1)(2) addMouseListener(new MouseAdapter() { @Override public
// //(1)鼠标按下的瞬间在屏幕中的坐标值 // mx=e.getXOnScreen(); // my=e.getYOnScreen(); // //当前窗体的坐标值 // jfx=e.getX(); // jfy=e.getY();
//(3) 鼠标按下的时候在窗口的位置 orgin.x=e.getX(); orgin.y=e.getY();
} });
addMouseMotionListener(new MouseMotionAdapter() { @Override public // //(2)在每一次移动鼠标时,对比移动后的坐标和移动前的坐标的差别 // //将这个差值加到窗体上即可,即鼠标移动多少,窗体就移动多少 // setLocation(jfx+(e.getXOnScreen()-mx), jfy+(e.getYOnScreen()-my));
//(4) 当鼠标拖动时获取窗口当前位置 Point p=getLocation(); // 窗口当前的位置 + 鼠标当前在窗口的位置 - 鼠标按下的时候在窗口的位置 setLocation(p.x+e.getX()-orgin.x, p.y+e.getY()-orgin.y); } });
//为 JFrame 添加 keyTyped 事件 //当点击 Esc 和 Space 键时退出程序 addKeyListener(new KeyAdapter() {
@Override public if (e.getKeyCode()==0) { System.exit(0); } } });
//设定成不使用系统自带的窗体装饰 setUndecorated(true);
//将背景设定成全透明 //前三个是 rgb 值,最后一个是透明度 ,整个 JFrame 就完全透明了 ,前三个 rgb 值实际不起作用) //因为 JFrame 被 contentPane 挡住了 //所以运行后"窗体"依然不透明, //再去 MyPanel.java 中设置 contentPane 的透明度即可 setBackground(new Color(0,0,0,0));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300);
//将原本的实例化方式注释掉,改为 MyPanel() //contentPane = new JPanel(); contentPane = new MyPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane);
JPanel panel = new JPanel(); panel.setOpaque(false); panel.setAlignmentX(Component.LEFT_ALIGNMENT);
//下面一大段代码由系统自动生成,不用管 GroupLayout gl_contentPane = new GroupLayout(contentPane); gl_contentPane.setHorizontalGroup( gl_contentPane.createParallelGroup(Alignment.LEADING) .addComponent(panel, GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE) ); gl_contentPane.setVerticalGroup( gl_contentPane.createParallelGroup(Alignment.LEADING) .addGroup(gl_contentPane.createSequentialGroup() .addGap(25) .addComponent(panel, GroupLayout.PREFERRED_SIZE, 264, GroupLayout.PREFERRED_SIZE) .addContainerGap(29, Short.MAX_VALUE)) );
JButton btnExit = new JButton("Exit"); //为 EXIT 关闭按钮指定UI btnExit.setUI(new MyButtonUI()); btnExit.setFocusable(false); //添加鼠标点击事件 //当点击 Exit 按钮时退出程序 btnExit.addMouseListener(new MouseAdapter() { @Override public System.exit(0); } });
JButton btnMax = new JButton("MAX"); //为 MAX 最大化/向下还原按钮指定UI btnMax.setUI(new MyButtonUI()); btnMax.setFocusable(false); btnMax.addMouseListener(new MouseAdapter() { @Override public //向下还原:如果已经最大化,就还原成正常大小 if (getExtendedState()==JFrame.MAXIMIZED_BOTH) { setExtendedState(JFrame.NORMAL); }else { //最大化:将JFrame设置成横向和纵向都最大化 setExtendedState(JFrame.MAXIMIZED_BOTH); } } });
JButton btnMin = new JButton("MIN"); //为 MIN 最小化按钮指定UI btnMin.setUI(new MyButtonUI()); btnMin.setFocusable(false); btnMin.addMouseListener(new MouseAdapter() { @Override public //最小化 setExtendedState(JFrame.ICONIFIED); } });
//下面一大段代码由系统自动生成,不用管 GroupLayout gl_panel = new GroupLayout(panel); gl_panel.setHorizontalGroup( gl_panel.createParallelGroup(Alignment.TRAILING) .addGroup(gl_panel.createSequentialGroup() .addContainerGap(217, Short.MAX_VALUE) .addComponent(btnMin) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(btnMax) .addPreferredGap(ComponentPlacement.RELATED) .addComponent(btnExit) .addContainerGap()) ); gl_panel.setVerticalGroup( gl_panel.createParallelGroup(Alignment.TRAILING) .addGroup(Alignment.LEADING, gl_panel.createSequentialGroup() .addContainerGap() .addGroup(gl_panel.createParallelGroup(Alignment.BASELINE) .addComponent(btnExit) .addComponent(btnMax) .addComponent(btnMin)) .addContainerGap(231, Short.MAX_VALUE)) ); panel.setLayout(gl_panel); contentPane.setLayout(gl_contentPane); } } |
MyPanel.java:
package com.siwuxie095.swing; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import javax.swing.JPanel; //MyPanel 继承自 JPanel public class MyPanel extends JPanel {
//需要复写父类 JPanel 的 paintComponent() 方法 @Override protected
//使用 Java2D,创建 Graphics2D 对象,让绘制效果更好 //需要强制类型转换 Graphics2D g2d=(Graphics2D) g;
//打开抗锯齿效果 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//前三个是 rgb 值,最后一个是透明度
//使用 Graphics2D 填充一个圆角矩形(作背景) //需要指定 X Y 坐标,宽度,高度,圆角的弧宽,圆角的弧高 //宽度和高度直接调用 JPanel 的 getWidth() 和 getHeight() 方法来获取 // //绘制边框时要注意:如果绘制的宽度和高度 //那么右方和下方的边框不会显示出来(即不会显示出深灰色) //因为绘制边框时是在指定宽度的右侧、指定高度的下侧来绘制的 ,这样右边界和下边界才不会被绘制到界面之外 ,宽高又减 6,详见:(5)关于笔触的注释) // //绘制一个半透明的窗体,填充的是浅浅的白色 //(这里虽然绘制的是 contentPane,但后面的 JFrame //已经被设为全透明,所以 contentPane 就决定了 //g2d.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 20, 20); g2d.fillRoundRect(3, 3, getWidth()-7, getHeight()-7, 20, 20);
//绘制标题区域 //虽然 fill 的区域很大,但超出 setClip() 的部分不会被绘制 //(主要是 getHeight()-1 超出了范围) g2d.setClip(0,0,getWidth(),30); g2d.setColor(Color.white); g2d.fillRoundRect(1, 3, getWidth()-2, getHeight()-1, 20, 20); //因为 setClip() 仅针对这个标题栏有效,所以绘制完成后需要移除它,传入空值即可 g2d.setClip(null);
//(5) //设定笔触,传入匿名对象,指定笔触宽度 //笔触宽度变大时,窗体的边角就会变的凸出 // //这是因为在为当前的形状来绘制上边缘和左边缘时, //每一个像素的宽度都会同时向内和同时向外扩张半个像素 //而绘制下边缘和右边缘时,每一个像素的宽度则是同时向外扩张一个像素 // //如:当前的圆角矩形是从(0,0)开始绘制的,如果是 6 个宽度的话, //上边缘和左边缘会向里绘制 3 个像素和向外绘制 3 个像素, //而下边缘和右边缘则是向外绘制 6 个像素。 //所以要想完全显示该笔触(实际应用于边框,使四周宽度相同), //绘制时需要将起始点加上宽度的一半,宽高都减去宽度 g2d.setStroke(new BasicStroke(6));
g2d.setColor(Color.darkGray); //使用 Graphics2D 绘制一个圆角矩形(作边框) //g2d.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 20, 20); g2d.drawRoundRect(3, 3, getWidth()-7, getHeight()-7, 20, 20);
//绘制文字,先设定字体 g2d.setFont(new Font("Arial", Font.BOLD, 16)); g2d.drawString("Swing UI Test", 15, 24);
} } |
MyButtonUI.java:
package com.siwuxie095.swing; import java.awt.Color; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Rectangle; import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.JComponent; import javax.swing.LookAndFeel; import javax.swing.plaf.basic.BasicButtonUI; import sun.swing.SwingUtilities2; /** * 定制 ButtonUI,修改样式 * 法一:创建 MyButtonUI,继承自 BasicButtonUI,对按钮进行 setUI() * 法二:创建 MyButton,继承自 JButton,同时覆盖 paintComponent()方法(就像 MyPanel 一样) * * 这两种方式都可以,且比较灵活,任意选用即可 */ //MyButtonUI 继承自 BasicButtonUI public class MyButtonUI extends BasicButtonUI {
//覆盖 BasicButtonUI 的一些方法, //右键->Source->Override/Implement Methods->BasicButtonUI
@Override protected super.installDefaults(b); //将 opaque 属性设为 false //(这是从父类中复制粘贴过来的) LookAndFeel.installProperty(b, "opaque", Boolean.FALSE); }
//绘制要有顺序,不然可能会覆盖之前绘制的元素 @Override public //设置按钮背景颜色为半透明红色 //前三个是 rgb 值,最后一个是透明度 g.setColor(new Color(255,0,0,150)); //填充圆角矩形的按钮背景 g.fillRoundRect(0, 0, c.getWidth(), c.getHeight(), 10, 10); super.paint(g, c); }
//绘制按钮中显示的文本,可以将父类中的代码复制粘贴过来,进行修改 @Override protected AbstractButton b = (AbstractButton) c; ButtonModel model = b.getModel(); FontMetrics fm = SwingUtilities2.getFontMetrics(c, g); int mnemonicIndex = b.getDisplayedMnemonicIndex(); /* Draw the Text */ if(model.isEnabled()) { /*** paint the text normally */ //按照平常的方式绘制按钮文本 //g.setColor(b.getForeground()); g.setColor(Color.WHITE);//将文本绘制成白色 SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex, textRect.x + getTextShiftOffset(), textRect.y + fm.getAscent() + getTextShiftOffset()); } else { /*** paint the text disabled ***/ //当前按钮被禁用后,文本如何绘制 g.setColor(b.getBackground().brighter()); SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex, textRect.x, textRect.y + fm.getAscent()); g.setColor(b.getBackground().darker()); SwingUtilities2.drawStringUnderlineCharAt(c, g,text, mnemonicIndex, textRect.x - 1, textRect.y + fm.getAscent() - 1); } } @Override protected //当按钮按下时,背景颜色发生变化:变成半透明蓝色 g.setColor(new Color(0,0,255,150)); g.fillRoundRect(0, 0, b.getWidth(), b.getHeight(), 10, 10); super.paintButtonPressed(g, b); }
} |
将
JFrame 的 undecorated 属性设为 true,即不使用系统自带的窗体装饰
将 JFrame 设为 全透明
为
JFrame 添加 keyTyped 事件,实现点击 Esc 和 Space 退出程序
为
JFrame 添加 mousePressed、mouseDragged 事件,实现窗体拖拽移动
「关于窗体拖拽移动,为
contentPane 添加同样事件也能达到同样效果」
修改 MyFrame.java(主类) 中的 contentPane 的声明与实例化方式
在
MyPanel.java 中覆盖 JPanel 类的 paintComponent() 方法,
使用
Java 2D 绘制
contentPane
在 contentPane 上添加一个新的 JPanel,将 contentPane 和这个 JPanel
的
opaque 属性设为 false,布局改为 Group Layout,并做好吸附
在新的
JPanel 的右上角添加三个 JButton,将其文本(text)分别改为:
MIN、MAX、EXIT,分别 Rename 为:btnMin、btnMax、btnExit,并
做好吸附
将三个
JButton 的 focusable 属性设为 false,并分别指定 UI:setUI(new MyButtonUI())
为三个
JButton 添加 mouseClicked 事件,实现 最小化、最大化/向下还原、关闭
在
MyButtonUI.java 中覆盖 BasicButtonUI 类的一些方法
右键->Source->Override/Implement Methods->BasicButtonUI
运行程序:
这是一个半透明的窗体,中间显示的是本人的桌面背景
(标题栏:Swing UI Test 所在,是白色,不是半透明)
按钮也是半透明的红色,按下按钮时变成半透明的蓝色
【made by siwuxie095】
为组件设定UI的更多相关文章
- Activity组件的UI实现
Activity组件的UI实现需要与WindowManagerService服务和SurfaceFlinger服务进行交互 1. Activity组件在启动完成后,会通过一个类型为Session的Bi ...
- Unity3D拖尾组件在Ui界面下正常显示
在项目中Canvas下UI添加拖尾效果,会发现Ui完全遮挡住了拖尾. 如果要正常显示通常需要对Canvas进行设置,Render Mode 我这里用的是-Camera模式 其次要对Material 下 ...
- 微信小程序UI组件--Lin UI
地址:http://doc.mini.7yue.pro/ Lin UI 是基于 微信小程序原生语法 实现的组件库
- JSP组件Telerik UI for JSP发布R1 2019 SP1|附下载
Telerik UI for JSP拥有由Kendo UI for jQuery支持的40+ JSP组件,同时通过Kendo UI for jQuery的支持能使用JSP封装包构建现代的HTML5和J ...
- 使用Vue简单的写组件的UI库
初始化项目vue create nature-ui 在根目录下面创建一个文件目录放置组件(我这里的创建packages) packages 目录下面创建个个组件的名称并创建index.js(用于输出所 ...
- 微信小程序组件构建UI界面小练手 —— 表单登录注册微信小程序
通过微信小程序中丰富的表单组件来完成登录界面.手机快速注册界面.企业用户注册界面的微信小程序设计. 将会用到view视图容器组件.button按钮组件.image图片组件.input输入框组件.che ...
- 微信小程序插件组件-Taro UI
微信小程序组件使用以下官网查看 ↓ ↓ ↓ https://taro-ui.jd.com/#/docs/fab
- 小记---------CDH版大数据组件--clouderManager UI界面
启动 /opt/cm-5.14.0/etc/init.d/clouder-scm-server start /opt/cm-5.14.0/etc/init.d/clouder-scm-agent st ...
- 11-Java 界面设计
(一)Java界面设计概述 1.Java 界面设计的用途 2.AWT 简介 (1)Abstract Windows Toolkit 是最原始的工具包. 3.Swing 简介 4.SWT 简介 5.如何 ...
随机推荐
- vue页面性能优化方案
个人在项目中用到的页面性能优化的方式总结. 一.均衡页面加载文件的大小和数量 1.项目中小图片图片转base64,通过工具如webpack进行图片压缩,文件进行压缩混淆等 2.vue-router 懒 ...
- html5 canvas做的图表插件
用highchart的时候发现它是用svg来画图的,那么用canvas来做怎么样的. 以前做AS图表插件的时候,绘制图画主要用容器的Graphics对象来绘制,而canvas的context和Grap ...
- 【LeetCode】:二叉树的Max,Min深度
一.最大深度问题 描述: Given a binary tree, find its maximum depth. The maximum depth is the number of nodes a ...
- 【Linux不需要磁盘碎片整理的真正原因是因为Linux只是一个内核,它没有磁盘可以整理】
[Linux不需要磁盘碎片整理的真正原因是因为Linux只是一个内核,它没有磁盘可以整理]
- EntityFramework 学习 一 Lazy Loading 1
延迟加载:延迟加载相关的数据 using (var ctx = new SchoolDBEntities()) { //Loading students only IList<Student&g ...
- 算法(Algorithms)第4版 练习 1.5.13
package com.qiusongde; import edu.princeton.cs.algs4.StdIn; import edu.princeton.cs.algs4.StdOut; pu ...
- ML二(决策树学习)
决策树学习 Decision Tree Learning 1 基本概念 属性(attribute):树上的每个结点说明了对实例的某个属性的测试,该结点的每一个后继分支对应该属性的一个可能值. 熵(en ...
- Fireworks(whole page)
<!DOCTYPE HTML> <html> <head> <title>Canvas 实现放烟花特效</title> <meta c ...
- Java之泛型深解
泛型的内容确实很多,在上一篇Java之泛型浅解讲到了一些常用的泛型,但是还远远不够,上一篇的内容比较容易理解,这一篇我自己觉得更加难理解一些,因此,我还得想办法让它更加接地气更加容易理解,方便我和源宝 ...
- Mybatis_学习_00_资源帖
源码:https://github.com/mybatis/mybatis-3 一.官方 (1)Mybatis官方文档中文版 (2)MyBatis 从入门到精通 书中指定的网络资源 (3)MyBat ...