python3写一个exe程序,ping测试工具,界面漂亮好看

Python开发 阅读(8) 17小时前 发布 扫码查看网页

这个程序使用Python的tkinter库和ttkbootstrap主题来实现现代化界面。

完整的Python代码

python

import subprocess
import threading
import re
import sys
import os
from tkinter import *
from tkinter import scrolledtext, messagebox
import tkinter as tk

# 尝试导入ttkbootstrap,如果没有则回退到普通tkinter
try:
    import ttkbootstrap as ttk
    from ttkbootstrap.constants import *
    HAS_BOOTSTRAP = True
except ImportError:
    import tkinter.ttk as ttk
    HAS_BOOTSTRAP = False

class PingTool:
    def __init__(self, root):
        self.root = root
        self.root.title("网络Ping工具 - IP测试器")
        self.root.geometry("700x600")
        self.root.resizable(True, True)
        
        # 设置窗口图标(可选)
        try:
            self.root.iconbitmap(default='icon.ico')
        except:
            pass
        
        # 设置样式和颜色
        self.setup_styles()
        
        # 创建界面
        self.create_widgets()
        
        # 绑定回车键
        self.root.bind('<Return>', lambda event: self.start_ping())
        
        # 停止ping的标志
        self.stop_ping_flag = False
        self.current_process = None
        
    def setup_styles(self):
        """设置界面样式"""
        if HAS_BOOTSTRAP:
            # 使用ttkbootstrap主题
            self.style = ttk.Style(theme='darkly')  # 可选: 'darkly', 'superhero', 'solar', 'cosmo'
        else:
            # 自定义颜色方案(回退模式)
            self.bg_color = "#2b2b2b"
            self.fg_color = "#ffffff"
            self.accent_color = "#3c7fb0"
            self.entry_bg = "#3c3c3c"
            self.button_bg = "#3c7fb0"
            self.root.configure(bg=self.bg_color)
    
    def create_widgets(self):
        """创建所有界面组件"""
        
        # 主框架
        main_frame = Frame(self.root, bg=self.bg_color if not HAS_BOOTSTRAP else None)
        main_frame.pack(fill=BOTH, expand=True, padx=20, pady=20)
        
        # 标题
        title_label = self.create_label(
            main_frame, 
            "🌐 网络Ping工具", 
            font=("Microsoft YaHei", 20, "bold"),
            pady=10
        )
        title_label.pack()
        
        # 输入区域框架
        input_frame = self.create_frame(main_frame)
        input_frame.pack(fill=X, pady=10)
        
        # IP地址标签
        ip_label = self.create_label(
            input_frame, 
            "目标IP地址或域名:", 
            font=("Microsoft YaHei", 11)
        )
        ip_label.pack(side=LEFT, padx=(0, 10))
        
        # IP输入框
        self.ip_entry = self.create_entry(
            input_frame, 
            font=("Consolas", 12),
            width=30
        )
        self.ip_entry.pack(side=LEFT, padx=5, expand=True, fill=X)
        self.ip_entry.insert(0, "8.8.8.8")  # 默认IP
        
        # 按钮框架
        button_frame = self.create_frame(main_frame)
        button_frame.pack(fill=X, pady=10)
        
        # Ping按钮
        self.ping_btn = self.create_button(
            button_frame,
            text="▶ 开始Ping",
            command=self.start_ping,
            style="success" if HAS_BOOTSTRAP else None
        )
        self.ping_btn.pack(side=LEFT, padx=5, expand=True, fill=X)
        
        # 停止按钮
        self.stop_btn = self.create_button(
            button_frame,
            text="⏹ 停止",
            command=self.stop_ping,
            style="danger" if HAS_BOOTSTRAP else None,
            state=DISABLED
        )
        self.stop_btn.pack(side=LEFT, padx=5, expand=True, fill=X)
        
        # 清空按钮
        self.clear_btn = self.create_button(
            button_frame,
            text="🗑 清空",
            command=self.clear_output,
            style="secondary" if HAS_BOOTSTRAP else None
        )
        self.clear_btn.pack(side=LEFT, padx=5, expand=True, fill=X)
        
        # 结果输出区域
        output_label = self.create_label(
            main_frame,
            "📊 Ping结果:",
            font=("Microsoft YaHei", 11, "bold"),
            pady=(10, 5)
        )
        output_label.pack(anchor=W)
        
        # 创建带滚动条的文本框
        text_frame = self.create_frame(main_frame)
        text_frame.pack(fill=BOTH, expand=True, pady=5)
        
        self.output_text = scrolledtext.ScrolledText(
            text_frame,
            wrap=WORD,
            font=("Consolas", 10),
            bg="#1e1e1e" if not HAS_BOOTSTRAP else None,
            fg="#d4d4d4" if not HAS_BOOTSTRAP else None,
            insertbackground="white",
            relief=FLAT,
            borderwidth=0
        )
        self.output_text.pack(fill=BOTH, expand=True)
        
        # 配置输出文本框的标签样式
        self.output_text.tag_config("error", foreground="#f48771")
        self.output_text.tag_config("success", foreground="#6a9955")
        self.output_text.tag_config("info", foreground="#9cdcfe")
        self.output_text.tag_config("warning", foreground="#ce9178")
        
        # 状态栏
        self.status_var = StringVar()
        self.status_var.set("就绪 | 输入IP地址后点击'开始Ping'")
        status_bar = Label(
            main_frame,
            textvariable=self.status_var,
            font=("Microsoft YaHei", 9),
            bg="#3c3c3c" if not HAS_BOOTSTRAP else None,
            fg="#858585" if not HAS_BOOTSTRAP else None,
            relief=SUNKEN,
            anchor=W
        )
        status_bar.pack(fill=X, pady=(10, 0))
        
    def create_label(self, parent, text, font=None, pady=0):
        """创建标签的辅助方法"""
        kwargs = {
            "text": text,
            "font": font
        }
        if not HAS_BOOTSTRAP:
            kwargs["bg"] = self.bg_color
            kwargs["fg"] = self.fg_color
        
        label = Label(parent, **kwargs)
        label.pack(pady=pady)
        return label
    
    def create_frame(self, parent):
        """创建框架的辅助方法"""
        if HAS_BOOTSTRAP:
            return ttk.Frame(parent)
        else:
            return Frame(parent, bg=self.bg_color)
    
    def create_entry(self, parent, font=None, width=None):
        """创建输入框的辅助方法"""
        if HAS_BOOTSTRAP:
            return ttk.Entry(parent, font=font, width=width)
        else:
            return Entry(
                parent, 
                font=font, 
                width=width,
                bg=self.entry_bg,
                fg=self.fg_color,
                insertbackground=self.fg_color,
                relief=FLAT
            )
    
    def create_button(self, parent, text, command, style=None, state=NORMAL):
        """创建按钮的辅助方法"""
        if HAS_BOOTSTRAP:
            btn = ttk.Button(parent, text=text, command=command, style=style, state=state)
        else:
            btn = Button(
                parent,
                text=text,
                command=command,
                bg=self.button_bg,
                fg="white",
                font=("Microsoft YaHei", 10, "bold"),
                relief=RAISED,
                cursor="hand2",
                state=state
            )
        return btn
    
    def append_output(self, text, tag=None):
        """向输出文本框添加内容"""
        self.output_text.insert(END, text, tag)
        self.output_text.see(END)
        self.root.update_idletasks()
    
    def clear_output(self):
        """清空输出文本框"""
        self.output_text.delete(1.0, END)
        self.status_var.set("输出已清空")
    
    def start_ping(self):
        """开始Ping操作"""
        ip = self.ip_entry.get().strip()
        
        if not ip:
            messagebox.showwarning("警告", "请输入IP地址或域名!")
            return
        
        # 简单的IP/域名格式验证
        ip_pattern = re.compile(r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$')
        domain_pattern = re.compile(r'^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$')
        
        if not ip_pattern.match(ip) and not domain_pattern.match(ip):
            messagebox.showwarning("警告", "请输入有效的IP地址或域名!\n例如: 8.8.8.8 或 google.com")
            return
        
        # 更新UI状态
        self.ping_btn.config(state=DISABLED)
        self.stop_btn.config(state=NORMAL)
        self.clear_btn.config(state=DISABLED)
        self.ip_entry.config(state=DISABLED)
        self.stop_ping_flag = False
        
        self.append_output(f"\n{'='*60}\n", "info")
        self.append_output(f"开始Ping目标: {ip}\n", "success")
        self.append_output(f"{'='*60}\n\n", "info")
        
        self.status_var.set(f"正在Ping {ip} ...")
        
        # 在新线程中执行ping命令,避免界面卡顿
        ping_thread = threading.Thread(target=self.ping_host, args=(ip,), daemon=True)
        ping_thread.start()
    
    def ping_host(self, ip):
        """执行Ping命令"""
        try:
            # 根据操作系统选择ping命令参数
            if sys.platform.startswith('win'):
                # Windows系统
                cmd = ['ping', '-n', '4', ip]
            else:
                # Linux/Mac系统
                cmd = ['ping', '-c', '4', ip]
            
            # 执行ping命令
            self.current_process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                encoding='gbk' if sys.platform.startswith('win') else 'utf-8'
            )
            
            # 实时读取输出
            for line in self.current_process.stdout:
                if self.stop_ping_flag:
                    self.current_process.terminate()
                    break
                
                # 解析输出并添加颜色标记
                if "TTL=" in line or "ttl=" in line or "时间" in line or "time" in line:
                    self.append_output(line + "\n", "success")
                elif "请求超时" in line or "无法访问" in line or "unreachable" in line or "timed out" in line:
                    self.append_output(line + "\n", "error")
                elif "统计" in line or "statistics" in line or "丢失" in line or "loss" in line:
                    self.append_output(line + "\n", "warning")
                elif "平均" in line or "average" in line:
                    self.append_output(line + "\n", "info")
                else:
                    self.append_output(line + "\n")
            
            self.current_process.wait()
            
            if not self.stop_ping_flag:
                self.append_output("\nPing测试完成!\n", "success")
                self.status_var.set(f"Ping完成 - {ip}")
            else:
                self.append_output("\nPing已停止!\n", "warning")
                self.status_var.set(f"Ping已停止 - {ip}")
                
        except Exception as e:
            self.append_output(f"\n错误: {str(e)}\n", "error")
            self.status_var.set("发生错误")
        finally:
            # 恢复UI状态
            self.root.after(0, self.reset_ui)
    
    def reset_ui(self):
        """重置UI状态"""
        self.ping_btn.config(state=NORMAL)
        self.stop_btn.config(state=DISABLED)
        self.clear_btn.config(state=NORMAL)
        self.ip_entry.config(state=NORMAL)
        self.current_process = None
    
    def stop_ping(self):
        """停止Ping操作"""
        if self.current_process:
            self.stop_ping_flag = True
            self.current_process.terminate()
            self.status_var.set("正在停止...")
            self.append_output("\n正在停止Ping...\n", "warning")

def main():
    root = tk.Tk()
    
    # 设置窗口居中
    window_width = 700
    window_height = 600
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    x = (screen_width - window_width) // 2
    y = (screen_height - window_height) // 2
    root.geometry(f"{window_width}x{window_height}+{x}+{y}")
    
    app = PingTool(root)
    
    # 显示启动提示
    if not HAS_BOOTSTRAP:
        print("提示: 安装ttkbootstrap可以获得更好的界面效果")
        print("安装命令: pip install ttkbootstrap")
    
    root.mainloop()

if __name__ == "__main__":
    main()

打包成exe文件

方法1:使用PyInstaller(推荐)

  1. 安装PyInstaller:
  2. bash
pip install pyinstaller
  1. 创建打包脚本(保存为 build_exe.py):
  2. python
import os
import sys

# 打包命令
cmd = [
    'pyinstaller',
    '--onefile',           # 打包成单个exe文件
    '--windowed',          # 不显示控制台窗口
    '--name', 'PingTool',  # 程序名称
    '--icon', 'NONE',      # 可以指定图标文件,如 'icon.ico'
    '--clean',             # 清理临时文件
    'ping_tool.py'         # 你的主程序文件
]

# 添加ttkbootstrap和其他依赖
import pkg_resources
installed_packages = [d.project_name for d in pkg_resources.working_set]

if 'ttkbootstrap' in installed_packages:
    cmd.extend(['--hidden-import', 'ttkbootstrap'])

# 执行打包
os.system(' '.join(cmd))

print("\n打包完成!exe文件位于 dist 文件夹中")
  1. 运行打包:
  2. bash
python build_exe.py

方法2:使用auto-py-to-exe(图形化界面)

bash

# 安装auto-py-to-exe
pip install auto-py-to-exe

# 启动图形化打包工具
auto-py-to-exe

然后在图形界面中:

  • Script Location: 选择你的 ping_tool.py
  • One File: 选择 "One File"
  • Console Window: 选择 "Window Based" (隐藏控制台)
  • 点击 "Convert .py to .exe"

使用说明

安装依赖(可选,用于更好看的界面):

bash

pip install ttkbootstrap

如果没有安装ttkbootstrap,程序会自动回退到普通tkinter主题。

程序功能:

  1. 输入目标:支持IP地址(如 8.8.8.8)或域名(如 google.com)
  2. 开始Ping:点击按钮开始测试网络连接
  3. 停止Ping:可随时停止正在进行的测试
  4. 清空输出:清除所有显示的结果
  5. 彩色输出:绿色:成功的响应红色:超时或错误黄色:统计信息蓝色:提示信息

特色功能:

  • 支持Windows、Linux、macOS系统
  • 实时显示Ping结果
  • 多线程处理,界面不卡顿
  • 按回车键快速开始
  • 自动检测操作系统并使用正确的ping参数
  • 美观的现代化界面设计

打包后的文件位置:

  • exe文件会在 dist 文件夹中
  • 可以直接复制到任何地方运行,无需安装Python

这个程序界面美观,功能实用,可以直接使用!


本文标题:python3写一个exe程序,ping测试工具,界面漂亮好看
本文链接:https://www.befun.ink/detail/20247.html
声明:本站信息原创或由互联网收集,未用于商业用途,如若侵权,请联系站长删除!