Java學習之AWT GUI編程
Java學習之AWT GUI編程
0x00 前言
既然前面提到了要重寫冰蠍和一些反序列化工具,當然就不能隨便說說而已。在編寫這些工具還是要使用圖形化工具來的方便一些,所以提前把GUI的框架給學習一遍。
其實重寫webshell工具這個也就是實現部分,現在就差個gui框架。
這裡其實是已經完善了單向加密和雙向加密的功能,並且服務端aes動態密鑰加密也寫好了,且可以定義128和256位aes的加密。
0x01 AWT概述
當 JDK 1.0發布時, Sun 提供了 一套基本的GUI類庫,這個GUI類庫希望可以在所有平台下都能運行 , 這套基本類庫被稱為”抽象窗口工具集 CAbstract Window Toolkit )”,它為Java應用程式提供了基本的圖形組件 。 AWT是窗口框架,它從不同平台的窗口系統中抽取出共同組件 , 當程式運行時,將這些組件的創建和動作委託給程式所在的運行平台 。 簡而言之 ,當使用 AWT 編寫圖形介面應用 時, 程式僅指定了介面組件的位置和行為,並未提供真正的實現,JVM調用作業系統本地的圖形介面來創建和平台 一致的對等體 。
使用AWT創建的圖形介面應用和所在的運行平台有相同的介面風格 , 比如在 Windows 作業系統上,它就表現出 Windows 風格 ; 在 UNIX 作業系統上,它就表現出UNIX 風格 。 Sun 希望採用這種方式來實現 ” Write Once, Run Anywhere “(一次編寫多次運行) 的目標 。
0x02 AWT體系
所有和 AWT 編程相關的類都放在 java.awt 包以及它的子包中, AWT 編程中有兩個基類 :Component和 MenuComponent。
Component:代表一個能以圖形化方式顯示出來,並可與用戶交互的對象,例如 Button 代表一個按鈕,TextField 代表 一個文本框等;
MenuComponent:則代表圖形介面的菜單組件,包括 MenuBar (菜單條)、 Menultem (菜單項)等子類。
多的體系什麼的就不看了,主要是實用為主。
0x03 AWT程式碼實現
Frame
第一個GUI介面
package com.test;
import java.awt.*;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
frame.setVisible(true);
frame.setSize(400,400);
frame.setLocation(500,500);
}
}
Panel面板
Panel可以看成是一個面板,簡單來說就是一個容器。
程式碼實例:
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
//設置布局
frame.setLayout(null);
//窗口可見
frame.setVisible(true);
//設置坐標
frame.setBounds(300,300,500,500);
Panel panel = new Panel();
//設置panel坐標,相對於frame
panel.setBounds(50,50,400,400);
panel.setBackground(new Color(219, 185, 185));
frame.add(panel);
//
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
//結束程式
System.exit(0);
}
});
}
}
布局管理器
流式布局
程式碼:
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
Button button1 = new Button("submit");
Button button2 = new Button("submit");
Button button3 = new Button("submit");
frame.setSize(500,500);
//設置布局
frame.setLayout(null);
//窗口可見
frame.setVisible(true);
//設置流式布局
frame.setLayout(new FlowLayout(FlowLayout.RIGHT));
//添加按鈕
frame.add(button1);
frame.add(button2);
frame.add(button3);
}
}
東西南北中布局
程式碼:
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
Button button1 = new Button("submit");
Button button2 = new Button("submit");
Button button3 = new Button("submit");
Button button4 = new Button("submit");
Button button5 = new Button("submit");
frame.setSize(500,500);
//添加按鈕
frame.add(button1,BorderLayout.EAST);
frame.add(button2,BorderLayout.WEST);
frame.add(button3,BorderLayout.SOUTH);
frame.add(button4,BorderLayout.NORTH);
frame.add(button5,BorderLayout.CENTER);
frame.setVisible(true);
}
}
表格布局
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
Button button1 = new Button("submit");
Button button2 = new Button("submit");
Button button3 = new Button("submit");
Button button4 = new Button("submit");
Button button5 = new Button("submit");
frame.setSize(500,500);
//設置表格布局
frame.setLayout(new GridLayout(3,2));
frame.add(button1);
frame.add(button2);
frame.add(button3);
frame.add(button4);
frame.add(button5);
//自動布局
frame.pack();
frame.setVisible(true);
}
}
文本框
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
Panel panel=new Panel();
Button button = new Button("submit");
TextField textField = new TextField();
textField.setText("普通文本框");
textField.setVisible(true);
frame.setVisible(true);
frame.setSize(500,500);
panel.add(button);
panel.add(textField);
frame.add(panel);
}
}
常用組件
組件名 | 功能 |
---|---|
Button | Button |
Canvas | 用於繪圖的畫布 |
Checkbox | 複選框組件(也可當做單選框組件使用) |
CheckboxGroup | 用於將多個Checkbox 組件組合成一組, 一組 Checkbox 組件將只有一個可以 被選中 , 即全部變成單選框組件 |
Choice | 下拉選擇框 |
Frame | 窗口 , 在 GUI 程式里通過該類創建窗口 |
Label | 標籤類,用於放置提示性文本 |
List | JU表框組件,可以添加多項條目 |
Panel | 不能單獨存在基本容器類,必須放到其他容器中 |
Scrollbar | 滑動條組件。如果需要用戶輸入位於某個範圍的值 , 就可以使用滑動條組件 ,比如調 色板中設置 RGB 的三個值所用的滑動條。當創建一個滑動條時,必須指定它的方向、初始值、 滑塊的大小、最小值和最大值。 |
ScrollPane | 帶水平及垂直滾動條的容器組件 |
TextArea | 多行文本域 |
TextField | 單行文本框 |
對話框 Dialog
方法名稱 | 方法功能 |
---|---|
Dialog(Frame owner, String title, boolean modal) | 創建一個對話框對象: owner:當前對話框的父窗口 title:當前對話框的標題 modal:當前對話框是否是模式對話框,true/false |
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
final Dialog d1 = new Dialog(frame, "command", true);
final Dialog d2 = new Dialog(frame, "connection", true);
// 往對話框中添加內容
Box vBox = Box.createVerticalBox();
vBox.add(new TextField(15));
vBox.add(new Button("submit"));
d1.add(vBox);
// 設置對話框大小
Button b1 = new Button("open");
Button b2 = new Button("close");
// 給b1按鈕綁定事件
d1.setBounds(20,30,300,100);
d2.setBounds(20,30,300,400);
b1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
d1.setVisible(true);
}
});
b2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
d2.setVisible(true);
}
});
//把按鈕添加到frame中
frame.add(b1);
frame.add(b2,BorderLayout.SOUTH);
//設置frame最佳大小並可見
frame.pack();
frame.setVisible(true);
frame.setSize(1024,700);
}
}
FileDialog
Dialog 類還有 一個子類 : FileDialog ,它代表一個文件對話框,用於打開或者保存 文件,需要注意的是FileDialog無法指定模態或者非模態,這是因為 FileDialog 依賴於運行平台的實現,如果運行平台的文件對話框是模態的,那麼 FileDialog 也是模態的;否則就是非模態的 。
方法名稱 | 方法功能 |
---|---|
FileDialog(Frame parent, String title, int mode) | 創建一個文件對話框: parent:指定父窗口 title:對話框標題 mode:文件對話框類型,如果指定為FileDialog.load,用於打開文件,如果指定為FileDialog.SAVE,用於保存文件 |
String getDirectory() | 獲取被打開或保存文件的絕對路徑 |
String getFile() | 獲取被打開或保存文件的文件名 |
程式碼:
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
// 載入文件
final FileDialog load_file = new FileDialog(frame, "load_file", FileDialog.LOAD);
final FileDialog save_file = new FileDialog(frame, "save_file", FileDialog.SAVE);
Button open_file_b = new Button("open_file");
Button save_file_b = new Button("save_file");
//給按鈕添加事件
open_file_b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
load_file.setVisible(true);
// 列印用戶選擇的文件路徑和名稱
System.out.println(load_file.getDirectory());
System.out.println(load_file.getFile());
}
});
save_file_b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(save_file.getDirectory());
System.out.println(save_file.getFile());
}
});
// 配置完按鈕事件,將按鈕添加到frame中
frame.add(open_file_b);
frame.add(save_file_b,BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
}
事件監聽器
定義:
當在某個組件上發生某些操作的時候,會自動的觸發一段程式碼的執行。
在GUI事件處理機制中涉及到4個重要的概念需要理解:
事件源(Event Source):操作發生的場所,通常指某個組件,例如按鈕、窗口等;
事件(Event):在事件源上發生的操作可以叫做事件,GUI會把事件都封裝到一個Event對象中,如果需要知道該事件的詳細資訊,就可以通過Event對象來獲取。
事件監聽器(Event Listener):當在某個事件源上發生了某個事件,事件監聽器就可以對這個事件進行處理。
註冊監聽:把某個事件監聽器(A)通過某個事件(B)綁定到某個事件源(C)上,當在事件源C上發生了事件B之後,那麼事件監聽器A的程式碼就會自動執行。
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class test {
Frame frame = new Frame("nwebshell");
Button button = new Button("submit");
TextField textField = new TextField(30);
public void init(){
button.addActionListener(new MyActionLitst());
frame.add(textField);
frame.add(button,BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private class MyActionLitst implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
textField.setText("Hello World");
}
}
public static void main(String[] args) {
new test().init();
}
}
程式碼二:
package com.test;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class test {
public static void main(String[] args) {
Frame frame = new Frame("nwebshell");
final TextField textField = new TextField(30);
textField.addTextListener(new TextListener() {
@Override
public void textValueChanged(TextEvent e) {
System.out.println(textField.getText());
}
});
frame.add(textField);
frame.pack();
frame.setVisible(true);
}
}
菜單組件
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class SimpleMenu {
//創建窗口
private Frame frame = new Frame("這裡測試菜單相關組件");
//創建菜單條組件
private MenuBar menuBar = new MenuBar();
//創建文件菜單組件
private Menu fileMenu = new Menu("文件");
//創建編輯菜單組件
private Menu editMenu = new Menu("編輯");
//創建新建菜單項
private MenuItem newItem = new MenuItem("新建");
//創建保存菜單項
private MenuItem saveItem = new MenuItem("保存");
//創建退出菜單項
private MenuItem exitItem = new MenuItem("退出");
//創建自動換行選擇框菜單項
private CheckboxMenuItem autoWrap = new CheckboxMenuItem("自動換行");
//創建複製菜單項
private MenuItem copyItem = new MenuItem("複製");
//創建粘貼菜單項
private MenuItem pasteItem = new MenuItem("粘貼");
//創建格式菜單
private Menu formatMenu = new Menu("格式");
//創建注釋菜單項
private MenuItem commentItem = new MenuItem("注釋");
//創建取消注釋菜單項
private MenuItem cancelItem = new MenuItem("取消注釋");
//創建一個文本域
private TextArea ta = new TextArea(6, 40);
public void init(){
//定義菜單事件監聽器
ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
ta.append("單擊「"+command+"」菜單\n");
if (command.equals("退出")){
System.exit(0);
}
}
};
//為注釋菜單項和退出菜單項註冊監聽器
commentItem.addActionListener(listener);
exitItem.addActionListener(listener);
//為文件菜單fileMenu添加菜單項
fileMenu.add(newItem);
fileMenu.add(saveItem);
fileMenu.add(exitItem);
//為編輯菜單editMenu添加菜單項
editMenu.add(autoWrap);
editMenu.add(copyItem);
editMenu.add(pasteItem);
//為格式化菜單formatMenu添加菜單項
formatMenu.add(commentItem);
formatMenu.add(cancelItem);
//將格式化菜單添加到編輯菜單中,作為二級菜單
editMenu.add(new MenuItem("-"));
editMenu.add(formatMenu);
//將文件菜單和編輯菜單添加到菜單條中
menuBar.add(fileMenu);
menuBar.add(editMenu);
//把菜單條設置到frame窗口上
frame.setMenuBar(menuBar);
//把文本域添加到frame中
frame.add(ta);
//設置frame最佳大小並可見
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new SimpleMenu().init();
}
}
PopupMenu
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class PopupMenuTest {
private Frame frame = new Frame("這裡測試PopupMenu");
//創建PopubMenu菜單
private PopupMenu popupMenu = new PopupMenu();
//創建菜單條
private MenuItem commentItem = new MenuItem("注釋");
private MenuItem cancelItem = new MenuItem("取消注釋");
private MenuItem copyItem = new MenuItem("複製");
private MenuItem pasteItem = new MenuItem("保存");
//創建一個文本域
private TextArea ta = new TextArea("!!!", 6, 40);
//創建一個Panel
private Panel panel = new Panel();
public void init(){
//把菜單項添加到PopupMenu中
popupMenu.add(commentItem);
popupMenu.add(cancelItem);
popupMenu.add(copyItem);
popupMenu.add(pasteItem);
//設置panel大小
panel.setPreferredSize(new Dimension(300,100));
//把PopupMenu添加到panel中
panel.add(popupMenu);
//為panel註冊滑鼠事件
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
boolean flag = e.isPopupTrigger();
//判斷當前滑鼠操作是不是觸發PopupMenu的操作
if (flag){
//讓PopupMenu顯示在panel上,並且跟隨滑鼠事件發生的地方顯示
popupMenu.show(panel,e.getX(),e.getY());
}
}
});
//把ta添加到frame中間區域中
frame.add(ta);
//把panel添加到frame底部
frame.add(panel,BorderLayout.SOUTH);
//設置frame最佳大小,並可視;
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
new PopupMenuTest().init();
}
}
0x04 結尾
其實,在開發中會發現,Java寫gui介面真挺繁雜的。配置頁面都得手工去適配,就沒有像C#這些這麼方便,直接畫框,配置事件就完事了。AWT這個類其實不能夠做到跨平台,因為他是藉助windows的介面。後面會接著學習Swing框架。