使用绘图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】

时间: 2024-10-29 18:18:57

使用绘图API自定义组件的相关文章

进阶篇-用户界面:5.android绘图api自定义View(视图)

1.自定义视图并为其添加属性     我们平时用的Button啊 TextView啊都是安卓中系统自带的控件供开发者使用,但是,这些事远远不够的,有时候我们需要自定义控件. (1)新建一个类MyView使其继承View 类 import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; /** * C

3. 使用绘图API自定义视图 --- 旋转的方块

1 import android.content.Context; 2 import android.graphics.Canvas; 3 import android.graphics.Color; 4 import android.graphics.Paint; 5 import android.util.AttributeSet; 6 import android.view.View; 7 8 /** 9 * 旋转的方块 10 * 11 * @author dr 12 */ 13 publ

【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件

博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.com/han1202012/WheelViewDemo.git -- CSDN : http://download.csdn.net/detail/han1202012/8208997 ; 博客总结 : 博文内容 : 本文完整地分析了 WheelView 所有的源码, 包括其适配器类型, 两种回调接

Vue结合原生js实现自定义组件自动生成

就目前三大前端主流数据驱动框架(vue,ng,react)而言,均具有创建自定义组件的api,但都是必须先做到事先写好挂载点,这个挂载点可以是原有静态元素标签也可以是自定义模板:对于多种组件通过同一数据流生成的,如果事先在页面上写好挂载点(mounted),然后通过dom操作去动态添加,会遇到类似这样一条错误提示信息:Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.(…).这又是为何呢,下一

【ExtJS】关于自定义组件(一)

一.目的: ExtJS中提供了下拉日期选择控件Ext.form.field.Date与下拉时间选择控件Ext.form.field.Time.不过没有一个在选择日期时选择时间的控件datetimefield.目的就是运用自定义组件的方法,来扩展下拉日期选择控件Ext.form.field.Date,在下拉框中添加时间选择的组件.目标效果: 二.一些知识的梳理: 当自定义创建一个新类时,最好根据需要继承一个功能相近的基类,这是因为Ext JS 提供的自动化生命周期管理将会被合适的布局管理器管理并且

自定义组件-preference 自定义(设置-关于-系统更新)的preference

有些用户在安装好Android SDK后,打开Android SDK Manager下载API时一直显示"Done loading packages"却迟迟不能前进.自己也出现了这种情况,把自己成功解决此问题的方法分享给大家. 方法/步骤 用户需要首先打开已下载的安卓SDK管理器"Android SDK Manager",然后点击菜单栏中的"Tools"菜单选项,接下来只需选择"Options"选项即可打开设置窗体. 接下来,

自定义组件------带删除功能的EditText

以前在为EditText添加左侧图标,以及右侧一个删除按钮时,经常是使用FrameLayout,当这样代码复用差,维护也麻烦.最好的方法是重写EditText实现该功能.现在看看效果图,后面再讲解实现方式. 重写之后的组件有如下功能,只有当EditText内容不为空,而且获得焦点,才会出现删除按钮,点击删除按钮则清空内容.代码如下: public class CleanableEditText extends EditText { //回调函数 private TextWatcherCallBa

Android开发——构建自定义组件

Android中,你的应用程序程序与View类组件有着一种固定的联系,例如按钮(Button). 文本框(TextView), 可编辑文本框(EditText), 列表框(ListView), 复选框(CheckBox), 单选框(RadioButton), 滚动条(Gallery), 微调器(Spinner), 等等,还有一些比较先进的有着特殊用途的View组件,例如 AutoCompleteTextView, ImageSwitcher和 TextSwitcher.除此之外,种类繁多的像 线

Android 自定义组件之如何实现自定义组件

参考链接:http://blog.csdn.net/jjwwmlp456/article/details/41076699 简介 Android提供了用于构建UI的强大的组件模型.两个基类:View和ViewGroup. 可用Widget的部分名单包括Button, TextView, EditText, ListView, CheckBox,RadioButton, Gallery, Spinner,以及一些有特别作用的组件: AutoCompleteTextView, ImageSwitch