使用绘图API自定义组件
-----------------siwuxie095
工程名:CustomizeSwing
包名:com.siwuxie095.swing
类名:MyFrame.java(主类)、MyPanel.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 值,最后一个是透明度 //透明度为 0,整个 JFrame 就完全透明了 //因为 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"); btnExit.setFocusable(false); //添加鼠标点击事件 //当点击 Exit 按钮时退出程序 btnExit.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { System.exit(0); } }); JButton btnMax = new JButton("MAX"); 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"); 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 值,最后一个是透明度 g2d.setColor(new Color(255,255,255,140));//白色,透明度为 140 //使用 Graphics2D 填充一个圆角矩形(作背景) //需要指定 X Y 坐标,宽度,高度,圆角的弧宽,圆角的弧高 //宽度和高度直接调用 JPanel 的 getWidth() 和 getHeight() 方法来获取 // //绘制边框时要注意:如果绘制的宽度和高度 与 真实边框的高度和宽度一样 , //那么右方和下方的边框不会显示出来(即不会显示出深灰色) //因为绘制边框时是在指定宽度的右侧、指定高度的下侧来绘制的 //所以宽度和高度都要减 1,这样右边界和下边界才不会被绘制到界面之外 //(至于为何起始点又加 3,宽高又减 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); } } |
将 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
为三个 JButton 添加 mouseClicked 事件,实现 最小化、最大化/向下还原、关闭
运行程序:
这是一个半透明的窗体,中间显示的是本人的桌面背景
(标题栏:Swing UI Test 所在,是白色,不是半透明)
【made by siwuixie095】
转载于:https://www.cnblogs.com/siwuxie095/p/6669047.html
使用绘图API自定义组件相关推荐
- 小程序高级电商前端第2周深入理解REST API开发规范 开启三端分离编程之旅<二>----scroll-view组件的灵活应用、async和await问题探讨、spu-scroll自定义组件
前言: 转眼距离上一次写博文又过去一个月了,今年的博文节奏已经彻底被打破了: 真的是有心无力了,其原因在之前也提到过,组织架构调整,各种考核(跨领域性质的考核)实行末尾淘汰制,说不出的酸楚,不过换个心 ...
- 微信小程序自定义组件使用canvas绘图,无法绘制以及fail canvas is empty问题
情况2:自定义组件引用canvas绘制,空白: 原因:查看文档,在自定义组件内需要手动传入当前实例的this,否则canvas指向的this为父组件所以无法找到正确canvas:<br / 情况 ...
- 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件
博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...
- 自定义组件开发六 自定义组件
概述 Android SDK 为我们提供了一套完整的组件库,数量多.功能强,涉及到方方面面,但是,我们依然看到软件市场上的每个 App 都有自己独特的东西,绝不是千遍一律的,而且也会和 IOS相互借鉴 ...
- 自定义组件开发五 阴影、 渐变和位图运算
介绍阴影.渐变和位图运算等技术 阴影只是一个狭义的说法,实际上也包括发光等效果:Android 也提供了强大的渐变功能,渐变能为物体带来更真实的质感,比如可以用渐变绘制一颗五子棋或一根金属圆棒:位图运 ...
- 第四章 自定义组件、动画
文章目录 第四章 自定义组件.动画 (一)View体系 (1)View简介 (2)Android坐标系 (3)视图坐标系 (二)自定义View (1)onMeasure:对当前View的尺寸进行测量 ...
- 微信小程序自定义组件之Picker组件
微信小程序开发交流qq群 173683895 承接微信小程序开发.扫码加微信. 需求: 通过JS条件判断,满足条件就弹出Picker给用户选择一个数组里面的数据. 有些朋友可能会有疑问: 1 ...
- 微信小程序之圆形进度条(自定义组件)
前言 昨天在微信小程序实现了圆形进度条,今天想把这个圆形进度条做成一个组件,方便以后直接拿来用. 根据官方文档自定义组件一步一步来 创建自定义组件 第一步创建项目结构 打开微信开发者工具创建一个项目, ...
- 【Android 内存优化】自定义组件长图组件 ( 长图滚动区域解码 | 手势识别 GestureDetector | 滑动计算类 Scroller | 代码示例 )
文章目录 一.GestureDetector 创建与设置 二.GestureDetector 触摸事件传递 三.触摸滑动操作 四.惯性滑动操作 五.长图滑动组件代码示例 六.运行效果 七.源码及资源下 ...
最新文章
- 降低网站跳出率的六个方法(亲身使用)
- IHttpHandler的学习(0)
- SQL 常用数据类型汇总
- Vs code自动生成Doxygen格式注释
- Java中语法分析器_语法分析器(java语法分析器)
- 台积电放大招:甩开英特尔 7nm和5nm芯片将诞生
- 第 11 个“世界备份日”刚过,《Veeam 2021 数据保护报告》为你解读全球数据备份现状
- android 休眠唤醒驱动流程分析,Android4.0.4休眠唤醒机制分析(基于MSM8260)
- 2.1.4 Python单例模式
- 计算机优秀大学生,应届计算机业优秀大学生的自我鉴定
- 运行HelloJersey遇到异常解决方法
- winHex创建指定大小二进制文件.bin(数据为全0或全FF或自己填充)并带winHex软件下载包
- android pickerview 多行,Android PickerView实现三级联动效果
- InstallShield打包程序
- Apple Compressor 4.4.4 中文特别版 Mac 电影视频后期制作工具
- CCPROXY漏洞利用
- 分享几个关于UG装配的小问题,干货满满!!!
- A/B 测试:数据驱动的产品优化
- 用计算机怎样搜wifi网,如何用电脑设置wifi?用电脑设置wifi方法介绍
- html td无边框颜色,table的td设置背景颜色后边框框消失
热门文章
- oracle pivoting insert 用法简介
- 深究AngularJS——校验(非form表单)
- 生成pfx文件需要在服务器上执行,PEM文件和private.key文件生成IIS服务器所需的pfx文件(配置SSL用)...
- linux 切换python版本_linux下多个python版本切换如何设置
- 哲学家就餐问题linux源代码,Linux下实现哲学家就餐问题
- 博图编写温度程序_NTC测量温度的两个不同的数值转换程序,你会选择哪一个
- mysql 查看最近的语句_查看MySQL最近执行的语句
- 一文看懂 K8s 日志系统设计和实践
- fetch 自动加cookie_如何在shell中动态获取chrome浏览器的cookie信息
- 计算机桌面是是在哪个盘,电脑虚拟内存是设置在哪个盘的