zoukankan      html  css  js  c++  java
  • 使用绘图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】

  • 相关阅读:
    生成Ptc文件时候使用top camera比较好
    3delight 上关于ptex的讨论,3delight的开发者最后说ptex的内存表现并不比普通的贴图差,不知道是不是因为3delight不支持而故意说的
    闲来无事,写个算法关于11000放在含有1001个元素。。。
    寻最优数字筛选算法找出 “排列数列“ 对应的 “组合数列“
    入住博客园
    日常工作中收集整理的MSSQL 技巧
    序列化 和 反序列化 类
    对Singleton Pattern的一点修改
    快速幂 & 取余运算 讲解
    JDK动态代理实现
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6669047.html
Copyright © 2011-2022 走看看