用Java寫一個PC端的WIFI-ADB管理軟件

廢話

    一直在用android studio做android開發,偶然一次機會接觸到了wifi adb,試了好幾個支持android studio的插件,各有優缺點,有一個本來用着好好的,突然就用不了,不懂啥情況,於是就萌生了自己寫一個的想法。然後查了一下,感覺寫android studio插件的話,會有點麻煩,寫一個小型PC桌面程序,相對簡單一些,但我也從來沒寫過,當然,有着多年的Java基礎,也不慫,索性就,盤他。

    先上源碼地址:https://gitee.com/imxiaoyu_admin/WIFI-ADB.git

    然後附上運行之後的效果圖:

程序邏輯

參考了一下其他的插件,大概就是幾個功能點:

1、用戶手動輸入ip和端口號,直接連接設備

2、用戶先用usb連接手機,然後一鍵切換至wifi連接

3、連接過的手機可以保存起來(如果不保存的話,下次打開需要有限連接一次才能切換wifi連接,比較麻煩)

4、連接、斷開等常規操作

5、手動設置adb程序的路徑(懶得寫自動檢測的,索性就寫個手動的,反正設置一次永久使用,問題不大)

開發環境

    操作系統是win10,其他一些Jdk等必要的東西,就不列舉了

1、開發工具Intellij Idea

2、adb.exe

開始編碼

1、新建一個java程序

2、簡單分一下包

3、引用gson工具包

    網上下載一個gson.jar,然後複製到lib文件夾

    點擊 File->Project Structure->Libraries,然後點加號並找到gson.jar,導入完成之後如下圖所示:

4、相關工具類

    緩存邏輯:

    因爲程序比較簡單,這裏就不搞數據庫這種花裏胡哨的東西了,數據存儲的方式,就採用txt文件+json的形式,即在本機的某個固定路徑(這裏寫死D://wifi-adb-settings.txt)生成一個txt文件,用於存放相關數據的json字符串。

    需要保存的,僅有adb路徑和歷史設備數據兩項,設備詳細信息我也不新建對象了,直接用Map<String,Objec>來處理了,一切從簡。

    跟adb的交互,則是通過命令行的方式交互,通過執行命令行並解析結果,來完成相關的交互工作。

    下面放工具類,具體邏輯不多說了,都有註釋,仔細看即可。

(1)CmdUtils

package com.imxiaoyu.wifi.adb.utils;

import com.google.gson.Gson;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class CmdUtils {

    /**
     * 執行adb命令
     *
     * @param cmd 要執行的命令  參數
     * @return 返回執行結果,區分換行
     */
    public static List<String> runCmd(String cmd) {
        System.out.print("\n執行命令:" + cmd);
        List<String> list = new ArrayList<>();
        Process proc = null;
        BufferedReader reader;
        String line = null;
        Runtime runtime = Runtime.getRuntime();
        try {
            proc = runtime.exec(cmd);

            if (proc != null) {
                reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                while ((line = reader.readLine()) != null) {
                    if (line.length() > 1) {
                        list.add(line);
                    }
                }
            }

        } catch (Exception e) {
            System.out.print("執行命令:" + cmd + "出錯啦!");
            return null;
        }

        System.out.print("執行結果:" + new Gson().toJson(list));
        return list;
    }
}

(2)ConnectUtils

package com.imxiaoyu.wifi.adb.utils;

import com.google.gson.Gson;

import javax.swing.*;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class ConnectUtils {


    /**
     * 鏈接設備
     * @param name
     * @return
     */
    public static boolean connect(String name) {
        String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe " + "connect " + name;
        List<String> list = CmdUtils.runCmd(cmd);
        String str = new Gson().toJson(list);
        if (str.indexOf("connected to") > -1) {
            //鏈接成功
            return true;
        }

        JOptionPane.showMessageDialog(null, "目標設備拒接,無法鏈接。", "鏈接失敗", JOptionPane.ERROR_MESSAGE);
        return false;
    }

    /**
     * 斷開設備
     * @param name
     * @return
     */
    public static boolean disconnect(String name) {
        String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe " + "disconnect " + name;
        List<String> list = CmdUtils.runCmd(cmd);
        String str = new Gson().toJson(list);
        if (str.indexOf("disconnected") > -1) {
            //斷開成功
            return true;
        }

        JOptionPane.showMessageDialog(null, "設備不存在。", "斷開鏈接失敗", JOptionPane.ERROR_MESSAGE);
        return false;
    }

    /**
     * 解析一個usb設備的ip地址,不帶端口號
     *
     * @return
     */
    public static String getDeviceIp(String name) {
        String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe" + " -s " + name + " shell ifconfig wlan0 ";
        List<String> list = CmdUtils.runCmd(cmd);
        if (list.size() < 2) {
            return null;
        }
        String str = list.get(1);//ip地址在第二行,實例參數:  inet addr:192.168.22.11  Bcast:192.168.22.255  Mask:255.255.255.0

        Pattern p = Pattern.compile("\\s+");
        Matcher m = p.matcher(str);
        str = m.replaceAll(" ");//將多個連續的空格只保留一個

        str = str.replace(":", " ");
        String[] strList = str.split(" ");
        System.out.print("\n讀取到的ip地址:" + strList[3]);
        return strList[3];
    }

    /**
     * 給一個設備設置一個默認端口,默認5555,設置好了之後就可以直接通過ip+端口鏈接
     *
     * @param name
     * @param port
     * @return
     */
    public static void setDevicePort(String name, String port) {
        String cmd = SettingsUtils.getSettings().getWifiAdbPath() + "/adb.exe" + " -s " + name + " tcpip " + port;
        CmdUtils.runCmd(cmd);
    }

    /**
     * 判定一個設備是否是usb鏈接
     *
     * @param name
     * @return true-usb鏈接  false-wifi鏈接
     */
    public static boolean isUsb(String name) {
        if (name.indexOf(":") == -1) {
            //如果設備的名稱帶有冒號的,證明是帶有端口的,也就不是usb的方式鏈接的了
            return true;
        }
        return false;
    }


    /**
     * 判定一個usb設備是否已經鏈接了wifi
     *
     * @param deviceList
     * @param name
     * @return true-usb鏈接  false-wifi鏈接
     */
    public static boolean isUsbConnectWifi(List<Map<String, Object>> deviceList, String name) {
        //判定邏輯:先獲取這個有線設備的ip地址,如果現有的設備列表已經存在了這個ip地址,證明這個有線設備已經通過wifi鏈接了
        String ip = getDeviceIp(name);
        for (int i = 0; i < deviceList.size(); i++) {
            String deviceName = deviceList.get(i).get("name") + "";
            if (deviceName.startsWith(ip)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判定一個wifi設備是否已經鏈接了
     *
     * @param deviceList
     * @param name
     * @return true-usb鏈接  false-wifi鏈接
     */
    public static boolean isWifiConnect(List<Map<String, Object>> deviceList, String name) {
        //邏輯:如果這個wifi設備已經在當前的設備列表裏,那就是已連接了
        for (int i = 0; i < deviceList.size(); i++) {
            String deviceName = deviceList.get(i).get("name") + "";
            if (deviceName.startsWith(name)) {
                return true;
            }
        }
        return false;
    }
}

(3)SettingsEntity

package com.imxiaoyu.wifi.adb.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class SettingsEntity {
    private String wifiAdbPath = "";
    private List<Map<String, Object>> phoneList=new ArrayList<>();

    public String getWifiAdbPath() {
        return wifiAdbPath;
    }

    public void setWifiAdbPath(String wifiAdbPath) {
        this.wifiAdbPath = wifiAdbPath;
    }

    public List<Map<String, Object>> getPhoneList() {
        return phoneList;
    }

    public void setPhoneList(List<Map<String, Object>> phoneList) {
        this.phoneList = phoneList;
    }
}

(4)SettingsUtils

package com.imxiaoyu.wifi.adb.utils;

import com.google.gson.Gson;

import javax.swing.*;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SettingsUtils {
    private static Gson gson = new Gson();
    private static final String SETTINGS_PATH = "D://wifi-adb-settings.txt";//用於保存數據的txt文件的目錄


    /**
     * 獲取當前鏈接的設備的設備列表
     *
     * @return
     */
    public static List<Map<String, Object>> getAllDevice() {
        List<Map<String, Object>> deviceList = new ArrayList<>();
        SettingsEntity entity = getSettings();
        String cmd = entity.getWifiAdbPath() + "/adb.exe " + "devices -l";//獲取列表的命令
        List<String> cmdList = CmdUtils.runCmd(cmd);

        //運行adb.exe devices -l 這個命令之後,從返回的結果中解析出設備的相關信息

        for (int i = 1; i < cmdList.size(); i++) {
            //跳過第一行
            Pattern p = Pattern.compile("\\s+");
            Matcher m = p.matcher(cmdList.get(i));
            String str = m.replaceAll(" ");//將多個連續的空格只保留一個
            str = str.replace(":", " ");//將冒號抓換成空格,方便解析
            if (str.indexOf(".") > -1) {
                //如果包含有小數點,證明名字是帶端口的,這時候需要把第一個空格還原爲冒號
                str = str.replaceFirst(" ", ":");
            }
            System.out.print("\n解析前:" + str);

            Map<String, Object> map = new HashMap<>();
            String[] list = str.split(" ");
            map.put("name", list[0]);
            map.put("device_product", list[3]);
            map.put("model", list[5]);
            map.put("device", list[7]);
            map.put("transport_id", list[9]);
            deviceList.add(map);
        }

        return deviceList;
    }

    /**
     * 將一個已連接的設備保存起來
     *
     * @param map
     */
    public static void saveDevice(Map<String, Object> map) {

        if (isHaveDevice(map)) {
            JOptionPane.showMessageDialog(null, "設備已存在", "保存失敗", JOptionPane.ERROR_MESSAGE);
            return;
        }

        SettingsEntity entity = getSettings();
        map.put("id", UUID.randomUUID().toString());//保存的時候給加一個唯一id,方便刪除
        entity.getPhoneList().add(map);
        setSettings(entity);
        //保存成功
    }

    /**
     * 根據id,刪除一個已保存的設備
     *
     * @param id
     */
    public static void removeDevice(String id) {
        SettingsEntity entity = getSettings();
        List<Map<String, Object>> list = getSettings().getPhoneList();

        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).get("id").equals(id)) {
                list.remove(i);
            }
            entity.setPhoneList(list);
            setSettings(entity);
            return;
        }
        //刪除成功
    }


    /**
     * 判定一個設備是否已經存在
     *
     * @param map
     * @return
     */
    public static boolean isHaveDevice(Map<String, Object> map) {

        List<Map<String, Object>> deviceList = getSettings().getPhoneList();
        if (deviceList == null) {
            deviceList = new ArrayList<>();
        }
        boolean isHave = false;//是否存在
        for (int i = 0; i < deviceList.size(); i++) {
            if (deviceList.get(i).get("name").equals(map.get("name")) && deviceList.get(i).get("model").equals(map.get("model"))) {
                isHave = true;//這個設備已存在
            }
        }
        return isHave;
    }


    /**
     * 獲取保存的數據
     *
     * @return
     */
    public static SettingsEntity getSettings() {
        SettingsEntity settingsEntity;
        String str = readString();
        settingsEntity = gson.fromJson(str, SettingsEntity.class);
        if (settingsEntity == null) {
            settingsEntity = new SettingsEntity();
        }
        return settingsEntity;
    }

    /**
     * 寫入保存數據
     *
     * @param entity
     */
    public static void setSettings(SettingsEntity entity) {
        writeString(gson.toJson(entity));
    }

    /**
     * 從文件中讀取保存數據的json字符串
     *
     * @return
     */
    private static String readString() {

        File file = new File(SETTINGS_PATH);
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        try (FileReader reader = new FileReader(SETTINGS_PATH);
             BufferedReader br = new BufferedReader(reader) // 建立一個對象,它把文件內容轉成計算機能讀懂的語言
        ) {
            String allStr = "";
            String line;
            //網友推薦更加簡潔的寫法
            while ((line = br.readLine()) != null) {
                // 一次讀入一行數據
//                System.out.println(line);
                allStr += line;
            }
            return allStr;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 將json字符串寫入到txt文件中
     *
     * @param settingsStr
     */
    private static void writeString(String settingsStr) {
        try {
            File writeName = new File(SETTINGS_PATH); // 相對路徑,如果沒有則要建立一個新的output.txt文件
            writeName.createNewFile(); // 創建新文件,有同名的文件的話直接覆蓋
            try (FileWriter writer = new FileWriter(writeName);
                 BufferedWriter out = new BufferedWriter(writer)
            ) {
                out.write(settingsStr); // \r\n即爲換行
                out.flush(); // 把緩存區內容壓入文件
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

5、寫頁面交互

    其實寫頁面是我耗時最久的地方,可能是寫習慣android了,切換到這邊,寫列表的時候,習慣性使用jlist這個控件,後來試了挺多次了,效果不太滿意,後來查了一下,才轉過來用jtabel,對是用對了,但是這個坑也挺坑的,反正就是遇到各種問題,耗費了不少時間。

    編寫過程也不多少了,直接看代碼吧,都有註釋,先上一張截圖,然後是源碼。

    頁面相關的操作邏輯,我都放到了IndexView這個頁面裏,可能會顯得稍亂一些。

package com.imxiaoyu.wifi.adb.view;

import com.imxiaoyu.wifi.adb.utils.ConnectUtils;
import com.imxiaoyu.wifi.adb.utils.SettingsEntity;
import com.imxiaoyu.wifi.adb.utils.SettingsUtils;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class IndexView {


    private JPanel jPanel;

    private JTextField tf_adb_path;
    private JButton btn_adb_path;
    private JButton btn_refresh;
    private JTable tb_now;
    private JTable tb_history;
    private JButton btn_test_connect;
    private JTextField tf_ip_port;

    private List<Map<String, Object>> nowDeviceList = new ArrayList<>();
    private List<Map<String, Object>> historyDeviceList = new ArrayList<>();

    public void startView() {
        JFrame frame = new JFrame("Wifi Adb");
        frame.setContentPane(jPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
        frame.setSize(new Dimension(880, 500));

        btn_adb_path.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //設置一下adb.exe的路徑
                JFileChooser fileChooser = new JFileChooser("D:\\");
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                int returnVal = fileChooser.showOpenDialog(fileChooser);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    String filePath = fileChooser.getSelectedFile().getAbsolutePath();//這個就是你選擇的文件夾的路徑
                    tf_adb_path.setText(filePath);
                    System.out.print("\n選中的路徑:" + filePath);
                    SettingsEntity entity = SettingsUtils.getSettings();
                    entity.setWifiAdbPath(filePath);
                    SettingsUtils.setSettings(entity);
                }
            }
        });

        btn_test_connect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //通過手動輸入ip和端口的形式,直接連接設備
                String deviceName=tf_ip_port.getText();
                ConnectUtils.connect(deviceName);
                initList();
            }
        });

        btn_refresh.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //刷新列表
                initList();
            }
        });

        //初始化adv.exe的路徑信息
        SettingsEntity entity = SettingsUtils.getSettings();
        tf_adb_path.setText(entity.getWifiAdbPath());

        initList();
    }


    private void initList() {

        nowDeviceList = SettingsUtils.getAllDevice();
        NowListModel listModel = new NowListModel();

        tb_now.setModel(listModel);//設置需要顯示的數據
        tb_now.setRowHeight(36);

        //這個setCellEditor和setCellRenderer必須分別new,不然的話點擊按鈕的時候會有點小問題
        tb_now.getColumnModel().getColumn(3).setCellEditor(new NowListEditor());//加入點擊監聽
        tb_now.getColumnModel().getColumn(3).setCellRenderer(new NowListEditor());//加入操作按鈕

        tb_now.setRowSelectionAllowed(false);


        historyDeviceList = SettingsUtils.getSettings().getPhoneList();

        HistoryListModel historyListModel = new HistoryListModel();

        tb_history.setModel(historyListModel);
        tb_history.setRowHeight(36);

        tb_history.getColumnModel().getColumn(3).setCellEditor(new HistoryListEditor());
        tb_history.getColumnModel().getColumn(3).setCellRenderer(new HistoryListEditor());

        tb_history.setRowSelectionAllowed(false);

    }


    public class NowListModel extends AbstractTableModel {


        /**
         * 得到表格行數
         */
        @Override
        public int getRowCount() {
            if (nowDeviceList.size() == 0) {
                //列表空的話,標題也不顯示
                return 0;
            }
            return nowDeviceList.size() + 1;
        }

        /**
         * 重寫方法,得到表格列數
         */
        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (rowIndex == 0) {
                if (columnIndex == 0) {
                    return "型號";
                }
                if (columnIndex == 1) {
                    return "設備名稱";
                }
                if (columnIndex == 2) {
                    return "transport_id";
                }
                if (columnIndex == 3) {
                    return "操作";
                }
            }

            if (columnIndex == 0) {
                return nowDeviceList.get(rowIndex - 1).get("model");
            }
            if (columnIndex == 1) {
                return nowDeviceList.get(rowIndex - 1).get("name");
            }
            if (columnIndex == 2) {
                return nowDeviceList.get(rowIndex - 1).get("transport_id");
            }
            return "";
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            // 帶有按鈕列的功能這裏必須要返回true不然按鈕點擊時不會觸發編輯效果,也就不會觸發事件。
            if (column == 3) {
                return true;
            } else {
                return false;
            }
        }

    }

    public class HistoryListModel extends AbstractTableModel {


        /**
         * 得到表格行數
         */
        @Override
        public int getRowCount() {
            if (historyDeviceList.size() == 0) {
                return 0;
            }
            return historyDeviceList.size() + 1;
        }

        /**
         * 重寫方法,得到表格列數
         */
        @Override
        public int getColumnCount() {
            return 4;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            if (rowIndex == 0) {
                if (columnIndex == 0) {
                    return "型號";
                }
                if (columnIndex == 1) {
                    return "設備名稱";
                }
                if (columnIndex == 3) {
                    return "操作";
                }
                if (columnIndex == 2) {
                    return "transport_id";
                }
            }

            if (columnIndex == 1) {
                return historyDeviceList.get(rowIndex - 1).get("name");
            }
            if (columnIndex == 0) {
                return historyDeviceList.get(rowIndex - 1).get("model");
            }
            if (columnIndex == 2) {
                return historyDeviceList.get(rowIndex - 1).get("transport_id");
            }
            return "";
        }

        @Override
        public boolean isCellEditable(int row, int column) {
            // 帶有按鈕列的功能這裏必須要返回true不然按鈕點擊時不會觸發編輯效果,也就不會觸發事件。
            if (column == 3) {
                return true;
            } else {
                return false;
            }
        }

    }

    public class NowListEditor extends AbstractCellEditor implements TableCellRenderer,
            TableCellEditor {

        private JPanel panel;
        private JButton btnSave = null;
        private JButton btnDis = null;
        private JButton btnConnect = null;
        private int clickRow;

        public NowListEditor() {
            initButton();

            initPanel();

            panel.add(btnConnect);
            panel.add(btnDis);
            panel.add(btnSave);
        }

        private void initButton() {
            /**
             * 初始化按鈕
             */
            btnConnect = new JButton("鏈接");
            btnDis = new JButton("斷開");
            btnSave = new JButton("保存");

            /**
             * 設置按鈕監聽
             */
            btnConnect.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.print("\n鏈接");
                    System.out.print(";clickRow:" + clickRow);

                    String deviceName = nowDeviceList.get(clickRow - 1).get("name") + "";
                    String ip = ConnectUtils.getDeviceIp(deviceName);
                    String port = "5555";
                    ConnectUtils.setDevicePort(deviceName, port);
                    ConnectUtils.connect(ip + ":" + port);
                    initList();
                }
            });
            btnDis.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.print("\n斷開");
                    System.out.print(";clickRow:" + clickRow);
                    ConnectUtils.disconnect(nowDeviceList.get(clickRow - 1).get("name") + "");
                    initList();
                }
            });
            btnSave.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.print("\n保存");
                    System.out.print(";clickRow:" + clickRow);
                    SettingsUtils.saveDevice(nowDeviceList.get(clickRow - 1));
                    initList();
                }
            });
        }

        /**
         * 初始化畫板
         */
        private void initPanel() {
            panel = new JPanel();
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            /**
             * 這裏是處理顯示
             */
            panel.setBackground(new Color(255, 255, 255));
            if (row != 0) {
                panel.removeAll();

                String deviceName = nowDeviceList.get(row - 1).get("name") + "";

                if (ConnectUtils.isUsb(deviceName)) {
                    //這是一個有線設備
                    if (!ConnectUtils.isUsbConnectWifi(nowDeviceList, deviceName)) {
                        //這個有限設備還沒鏈接wifi
                        panel.add(btnConnect);
                    }
                } else {
                    //這是一個wifi設備
                    panel.add(btnDis);

                    if (!SettingsUtils.isHaveDevice(nowDeviceList.get(row - 1))) {
                        //這個wifi設備還沒有保存
                        panel.add(btnSave);
                    }
                }
                return panel;
            }
            return null;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value,
                                                     boolean isSelected, int row, int column) {
            /**
             * 這裏是處理點擊
             */
            clickRow = row;
            panel.setBackground(new Color(255, 255, 255));
            if (row != 0) {
                panel.removeAll();

                String deviceName = nowDeviceList.get(row - 1).get("name") + "";
                if (ConnectUtils.isUsb(deviceName)) {
                    System.out.print("\n有線設備:"+deviceName);
                    //這是一個有線設備
                    if (!ConnectUtils.isUsbConnectWifi(nowDeviceList, deviceName)) {
                        //這個有限設備還沒鏈接wifi
                        panel.add(btnConnect);//顯示連接按鈕
                    }
                    //如果有線設備已經鏈接了,就不再顯示連接按鈕
                } else {
                    //這是一個wifi設備
                    panel.add(btnDis);//如果列表裏面有wifi設備,證明肯定是鏈接狀態了的,所以只需要顯示斷開按鈕

                    if (!SettingsUtils.isHaveDevice(nowDeviceList.get(row - 1))) {
                        //這個wifi設備還沒有保存
                        panel.add(btnSave);//沒保存就顯示保存按鈕,已保存則不顯示
                    }
                }

                return panel;
            }
            return null;
        }

        @Override
        public Object getCellEditorValue() {
            return null;
        }
    }

    public class HistoryListEditor extends AbstractCellEditor implements TableCellRenderer,
            TableCellEditor {

        private JPanel panel;
        private JButton btnSave = null;
        private JButton btnDis = null;
        private JButton btnConnect = null;
        private int clickRow;

        public HistoryListEditor() {
            initButton();

            initPanel();

            panel.add(btnConnect);
            panel.add(btnDis);
            panel.add(btnSave);
        }

        private void initButton() {
            /**
             * 初始化按鈕
             */
            btnConnect = new JButton("鏈接");
            btnDis = new JButton("斷開");
            btnSave = new JButton("刪除");

            /**
             * 監聽點擊
             */
            btnConnect.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.print("\n鏈接");
                    ConnectUtils.connect(historyDeviceList.get(clickRow - 1).get("name") + "");
                    System.out.print(";clickRow:" + clickRow);
                    initList();
                }
            });
            btnDis.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.print("\n斷開");
                    ConnectUtils.disconnect(historyDeviceList.get(clickRow - 1).get("name") + "");
                    System.out.print(";clickRow:" + clickRow);
                    initList();
                }
            });
            btnSave.addActionListener(new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    System.out.print("\n刪除");
                    System.out.print(";clickRow:" + clickRow);
                    SettingsUtils.removeDevice(historyDeviceList.get(clickRow - 1).get("id") + "");
                    initList();
                }
            });

        }

        /**
         * 初始化畫板
         */
        private void initPanel() {
            panel = new JPanel();
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            panel.setBackground(new Color(255, 255, 255));
            if (row != 0) {
                panel.removeAll();

                String deviceName=historyDeviceList.get(row-1).get("name")+"";
                if(ConnectUtils.isWifiConnect(nowDeviceList,deviceName)){
                    System.out.print("wifi已連接");
                    //這個wifi設備已經鏈接
                    panel.add(btnDis);//已連接,顯示斷開按鈕
                }else{
                    //還沒鏈接
                    panel.add(btnConnect);//未連接,顯示連接按鈕
                }
                panel.add(btnSave);//顯示刪除按鈕
                return panel;
            }
            return null;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value,
                                                     boolean isSelected, int row, int column) {
            clickRow = row;
            panel.setBackground(new Color(255, 255, 255));
            if (row != 0) {
                panel.removeAll();

                String deviceName=historyDeviceList.get(row-1).get("name")+"";
                if(ConnectUtils.isWifiConnect(nowDeviceList,deviceName)){
                    //這個wifi設備已經鏈接
                    panel.add(btnDis);//已連接,顯示斷開按鈕
                }else{
                    //還沒鏈接
                    panel.add(btnConnect);//未連接,顯示連接按鈕
                }
                panel.add(btnSave);//顯示刪除按鈕
                return panel;
            }
            return null;
        }

        @Override
        public Object getCellEditorValue() {
            return null;
        }
    }

}

6、導出可運行的jar程序

    點擊Build->Build Artifacts->All Artifacts->Build

   

    Idea會自動在out目錄中生成jar包

    

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章