使用绘图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自定义组件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QT学习笔记之QTableView设置属
- 下一篇: 常用的三联动实现