本帖最后由 徘徊消逝中 于 2014-4-19 19:52 编辑
项目背景:目前正在学习java se,同时在做毕业设计——单片机光立方的上位机部分,上位机实现两个功能,1、图形化界面实现算法:LED点阵各种自定义图形对应的IO口的数据。2、串口通信。本身这类工具,大多数是在vc下开发的,也具有很多MFC的实例,但是我觉得练手一下java。
发现问题:我决定采取16个JButton,作为4*4的一层光立方的LED点阵。但是问题是,java中提供的JButton组件是方形的,且颜色固定。
解决方案:通过网络学习,最终解决了问题。方案如下: 采用重写JButton继承的paintComponent方法和paintBorder方法以及contains方法
1、paintComponent方法:重画button的背景和标签
- protected void paintComponent(Graphics g) {
- if (getModel().isArmed()) {
- // getModel方法返回鼠标的模型ButtonModel
- // 如果鼠标按下按钮,则buttonModel的armed属性为真
- g.setColor(Color.LIGHT_GRAY);
- } else {
- // 其他事件用默认的背景色显示按钮
- g.setColor(getBackground());
- }
- // fillOval方法画一个矩形的内切椭圆,并且填充这个椭圆
- // 当矩形为正方形时,画出的椭圆便是圆
- g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);
- // 调用父类的paintComponent画按钮的标签和焦点所在的小矩形
- super.paintComponents(g);
- }
复制代码
2、paintBorder方法,画button边界
- // 用简单的弧充当按钮的边界
- protected void paintBorder(Graphics g) {
- g.setColor(getForeground());
- // drawOval方法画矩形的内切椭圆,但不填充,只画出一个边界
- g.drawOval(0, 0, getSize().width - 1, getSize().height - 1);
- }
复制代码
3、contains方法:button的检测(因为图形变了,检测按钮也要重写),判断鼠标是否在button上
- public boolean contains(int x, int y) {
- // 如果按钮边框,位置发生改变,则产生一个新的形状对象
- if ((shape == null) || (!shape.getBounds().equals(getBounds()))) {
- // 构造椭圆型对象
- shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
- }
- // 判断鼠标的x,y坐标是否落在按钮形状内
- return shape.contains(x, y);
- }
复制代码
4、完整代码
- package testButton;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.FlowLayout;
- import java.awt.Graphics;
- import java.awt.Shape;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.geom.Ellipse2D;//注意此包加载
- import javax.swing.JButton;
- import javax.swing.JFrame;
- /**
- * 制作一个圆形按钮时,需要做两件事: 第一件事是重载一个适合的绘图方法以画出一个图形 第二件事是设置一些事件使得只有当单击图形按钮的范围中的时候才会做出响应
- */
- @SuppressWarnings("serial")
- public class CircleButtonOrig extends JButton {
- public CircleButtonOrig(String label) {
- super(label);
- Dimension size = getPreferredSize();// 获取按钮的最佳大小
- // 调整按钮的大小,使之变成一个方形
- size.width = size.height = Math.max(size.width, size.height);
- setPreferredSize(size);
- // 使jbutton不画背景,即不显示方形背景,而允许我们画一个圆的背景
- setContentAreaFilled(false);
- }
- // 画图的按钮的背景和标签
- protected void paintComponent(Graphics g) {
- if (getModel().isArmed()) {
- // getModel方法返回鼠标的模型ButtonModel
- // 如果鼠标按下按钮,则buttonModel的armed属性为真
- g.setColor(Color.LIGHT_GRAY);
- } else {
- // 其他事件用默认的背景色显示按钮
- g.setColor(getBackground());
- }
- // fillOval方法画一个矩形的内切椭圆,并且填充这个椭圆
- // 当矩形为正方形时,画出的椭圆便是圆
- g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);
- // 调用父类的paintComponent画按钮的标签和焦点所在的小矩形
- super.paintComponents(g);
- }
- // 用简单的弧充当按钮的边界
- protected void paintBorder(Graphics g) {
- g.setColor(getForeground());
- // drawOval方法画矩形的内切椭圆,但不填充,只画出一个边界
- g.drawOval(0, 0, getSize().width - 1, getSize().height - 1);
- }
- Shape shape;// 用于保存按钮的形状,有助于侦听单击按钮事件
- // 判断鼠标是否点在按钮上
- public boolean contains(int x, int y) {
- // 如果按钮边框,位置发生改变,则产生一个新的形状对象
- if ((shape == null) || (!shape.getBounds().equals(getBounds()))) {
- // 构造椭圆型对象
- shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
- }
- // 判断鼠标的x,y坐标是否落在按钮形状内
- return shape.contains(x, y);
- }
- public static void main(String[] args) {
- final JButton button = new CircleButtonOrig("Click me");// 产生一个圆形按钮
- button.setBackground(Color.green);// 设置背景色为绿色
- // 产生一个框架显示这个按钮
- JFrame frame = new JFrame("图形按钮");
- frame.getContentPane().setBackground(Color.yellow);
- frame.getContentPane().setLayout(new FlowLayout());
- frame.getContentPane().add(button);
- frame.setSize(200, 200);
- frame.setVisible(true);
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- }
- }
复制代码
总结:以上提供的是button的自定义形状的方法,类似的思路可以尝试在其他的组件上。
原创内容,手打不易,且行且珍惜。
附:程序运行效果如下(只截取LED点阵部分,学过单片机的同学或是知道光立方的应该能看懂)
ps:涉及到毕业设计,我是不是应该强调一下版权问题 “ 0”
|