-----------------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
void main(String[] args) {

EventQueue.invokeLater(new Runnable() {

public
void run() {

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
void mousePressed(MouseEvent e) {

 

// //(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
void mouseDragged(MouseEvent e) {

// //(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
void keyTyped(KeyEvent e) {

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
void mouseClicked(MouseEvent e) {

System.exit(0);

}

});

 

 

JButton btnMax = new JButton("MAX");

//为 MAX 最大化/向下还原按钮指定UI

btnMax.setUI(new MyButtonUI());

btnMax.setFocusable(false);

btnMax.addMouseListener(new MouseAdapter() {

@Override

public
void mouseClicked(MouseEvent arg0) {

//向下还原:如果已经最大化,就还原成正常大小

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
void mouseClicked(MouseEvent e) {

//最小化

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
void paintComponent(Graphics g) {

 

//使用 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
void installDefaults(AbstractButton b) {

super.installDefaults(b);

//将 opaque 属性设为 false

//(这是从父类中复制粘贴过来的)

LookAndFeel.installProperty(b, "opaque", Boolean.FALSE);

}

 
 

 

//绘制要有顺序,不然可能会覆盖之前绘制的元素

@Override

public
void paint(Graphics g, JComponent c) {

//设置按钮背景颜色为半透明红色

//前三个是 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
void paintText(Graphics g, JComponent c, Rectangle textRect, String text) {

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
void paintButtonPressed(Graphics g, AbstractButton b) {

//当按钮按下时,背景颜色发生变化:变成半透明蓝色

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的更多相关文章

  1. Activity组件的UI实现

    Activity组件的UI实现需要与WindowManagerService服务和SurfaceFlinger服务进行交互 1. Activity组件在启动完成后,会通过一个类型为Session的Bi ...

  2. Unity3D拖尾组件在Ui界面下正常显示

    在项目中Canvas下UI添加拖尾效果,会发现Ui完全遮挡住了拖尾. 如果要正常显示通常需要对Canvas进行设置,Render Mode 我这里用的是-Camera模式 其次要对Material 下 ...

  3. 微信小程序UI组件--Lin UI

    地址:http://doc.mini.7yue.pro/ Lin UI 是基于 微信小程序原生语法 实现的组件库

  4. 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 ...

  5. 使用Vue简单的写组件的UI库

    初始化项目vue create nature-ui 在根目录下面创建一个文件目录放置组件(我这里的创建packages) packages 目录下面创建个个组件的名称并创建index.js(用于输出所 ...

  6. 微信小程序组件构建UI界面小练手 —— 表单登录注册微信小程序

    通过微信小程序中丰富的表单组件来完成登录界面.手机快速注册界面.企业用户注册界面的微信小程序设计. 将会用到view视图容器组件.button按钮组件.image图片组件.input输入框组件.che ...

  7. 微信小程序插件组件-Taro UI

    微信小程序组件使用以下官网查看 ↓  ↓  ↓ https://taro-ui.jd.com/#/docs/fab

  8. 小记---------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 ...

  9. 11-Java 界面设计

    (一)Java界面设计概述 1.Java 界面设计的用途 2.AWT 简介 (1)Abstract Windows Toolkit 是最原始的工具包. 3.Swing 简介 4.SWT 简介 5.如何 ...

随机推荐

  1. Data Structure Linked List: Merge Sort for Linked Lists

    http://www.geeksforgeeks.org/merge-sort-for-linked-list/ #include <iostream> #include <vect ...

  2. css 行内元素 块元素 替换元素 非替换元素 以及这些元素的width height margin padding 特性

    一.各种元素的width height margin padding 特性(具体css元素的分来参看二) 1.块级元素 width. height. margin的四个方向. padding的四个方向 ...

  3. CSS3图片悬停放大动画

    在线演示 本地下载

  4. Python 注释和中文乱码

    Python 注释分为三种: 1.单行注释:# 2.多行注释:前后3个单引号,或者三个双引号: 如:''' 多行注释 ''', """或者 多行注释 '"&qu ...

  5. Myeclipse或者Eclipse恢复默认启动时显示选择workspace的问题

    [问题描述] 不知道是不是Myeclipse8.5的Bug,我最近安装了8.5之后,前面几天打开MyEclipse的时候都是让我自己选择工作空间的,但是最近突然每次打开的时候都自己打开了C盘下面工作空 ...

  6. jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别

    http://www.poluoluo.com/jzxy/201312/253059.html 在这个sprint中,因为要写前端UI,所以用到了jQuery,但是jQuery在向上遍历DOM树的AP ...

  7. Mybatis中collection与association的区别

    association是多对一的关系 collection是一个一对多的关系

  8. PL/SQL学习笔记_02_游标

    在 PL/SQL 程序中,对于处理多行记录的事务经常使用游标来实现. 为了处理 SQL 语句, ORACLE 必须分配一片叫上下文( context area )的区域来处理所必需的信息,其中包括要处 ...

  9. Oracle学习笔记_03_单行函数

    1.SQL函数: 单行函数.多行函数 单行函数:       操作数据对象       接受参数返回一个结果       只对一行进行变换       每行返回一个结果       可以转换数据类型  ...

  10. 关键字volidate和transient(转)

    Volatile修饰的成员变量在每次被线程访问时,都强迫从主内存中重读该成员变量的值.而且,当成员变量发生变化时,强迫线程将变化值回写到主内存.这样在任何时刻,两个不同的线程总是看到某个成员变量的同一 ...