python自定义IP输入栏,Tkinter PyQT分别实现
1.TKinter实现 Windows 10 风格 IP 地址输入控件 - Tkinter 版本 这个模块提供了高度还原 Windows 10 风格的 IP 地址输入控件具备以下特性 主要功能: 1. 自动焦点管理 - 输入 3 位数字后自动跳转到下一段 2. 智能输入验证 - 只允许 0-255 范围内的数字 3. 视觉反馈 - 聚焦、错误状态等 4. 键盘导航 - 支持方向键、点号、空格跳转 5. Windows 10 风格 - 现代简洁的外观设计 基本用法: from UI.ip_address_input_tkinter import Windows10IPInput # 创建控件 ip_input Windows10IPInput(root) ip_input.pack() # 设置 IP 地址 ip_input.set_ip(192.168.1.1) # 获取 IP 地址 ip ip_input.get_ip() # 验证 IP if ip_input.is_valid(): print(IP 地址有效) 作者Xiao Ming 版本1.0 (Tkinter) import tkinter as tk from tkinter import ttk class IPSegmentEntry(tk.Entry): IP 段输入框 - 单个数字段的输入控件 def __init__(self, parent, index, **kwargs): self.index index self.segment_completed_callback None self.segment_back_callback None self.on_text_change_callback None # 默认参数 default_kwargs { width: 3, font: (Segoe UI, 10), justify: center, bd: 0, # 无边框 bg: white, fg: #333333, highlightthickness: 0, selectbackground: #0078D7, selectforeground: white } # 如果有 height 参数添加到默认参数中 if height in kwargs: default_kwargs[height] kwargs[height] super().__init__(parent, **default_kwargs) # 绑定事件 self.bind(Key, self._on_key_press) self.bind(FocusIn, self._on_focus_in) self.bind(Button-1, self._on_click) self.bind(BackSpace, self._on_backspace) # 变量追踪 - 使用兼容方式 self.var tk.StringVar() self.config(textvariableself.var) # 兼容 Python 3.7 和旧版本 try: self.trace_id self.var.trace_add(write, self._on_var_change) except AttributeError: # Python 3.6 及以下版本使用 trace 方法 self.trace_id self.var.trace(w, self._on_var_change) def _on_key_press(self, event): 处理键盘事件 key event.keycode # 处理点号、逗号、空格 - 跳转到下一段 if event.char in [., ,, ]: if self.segment_completed_callback: self.segment_completed_callback() return break # 数字键允许 if event.char.isdigit(): current self.get() if len(current) 3: return break # 验证数值范围 new_value current event.char if int(new_value) 255: return break # 如果输入了 3 位有效数字自动跳转 if len(new_value) 3 and int(new_value) 255: self.after(100, self.segment_completed_callback) else: # 非数字字符不允许除了控制键 if event.char and not event.char.isdigit(): # 允许控制键如 Ctrl、Alt 等 if event.keycode not in [16, 17, 18, 27]: # Shift, Control, Alt, Escape return break def _on_backspace(self, event): 处理退格键 if not self.get(): if self.segment_back_callback: self.segment_back_callback() def _on_focus_in(self, event): 焦点进入事件 self.selection_range(0, tk.END) def _on_click(self, event): 点击事件 self.after(10, lambda: self.selection_range(0, tk.END)) def _on_var_change(self, *args): 变量变化回调 text self.var.get() # 防止空值处理 if not text: if self.on_text_change_callback: self.on_text_change_callback() return # 只允许数字 if not text.isdigit(): # 保存当前光标位置 cursor_pos self.index(tk.INSERT) # 过滤非数字字符 clean_text .join(c for c in text if c.isdigit()) # 临时移除追踪避免无限递归 try: self.var.trace_remove(write, self.trace_id) except (AttributeError, tk.TclError): pass self.var.set(clean_text) # 重新添加追踪 try: self.trace_id self.var.trace_add(write, self._on_var_change) except AttributeError: self.trace_id self.var.trace(w, self._on_var_change) # 恢复光标位置 self.icursor(min(cursor_pos, len(clean_text))) return # 验证数值范围 try: value int(text) if value 255: # 保存当前光标位置 cursor_pos self.index(tk.INSERT) # 截断最后一位 clean_text text[:-1] if len(text) 1 else # 临时移除追踪 try: self.var.trace_remove(write, self.trace_id) except (AttributeError, tk.TclError): pass self.var.set(clean_text) # 重新添加追踪 try: self.trace_id self.var.trace_add(write, self._on_var_change) except AttributeError: self.trace_id self.var.trace(w, self._on_var_change) # 恢复光标位置 self.icursor(min(cursor_pos, len(clean_text))) except ValueError: pass # 触发自定义回调 if self.on_text_change_callback: self.on_text_change_callback() def set_segment_completed(self, callback): 设置完成回调 self.segment_completed_callback callback def set_segment_back(self, callback): 设置回退回调 self.segment_back_callback callback def set_on_text_change(self, callback): 设置文本变化回调 self.on_text_change_callback callback class Windows10IPInput(ttk.Frame): Windows 10 风格 IP 地址输入控件Tkinter 版本 一个完整的 IP 地址输入解决方案提供现代化的用户界面和流畅的交互体验。 由四个 IPSegmentEntry 组件组成通过点号分隔形成标准的 IPv4 输入格式。 主要特性: - 直观的输入体验输入三位数字后自动跳转到下一段 - 多种跳转方式支持点号、空格、右箭头键跳转到下一段 - 完善的导航支持左右箭头键在各段之间移动 - 实时验证输入时即时验证数值有效性0-255 - 视觉反馈清晰的聚焦状态和错误指示 - 响应式设计支持启用/禁用状态切换 - 灵活配置可设置占位符文本、默认值等 方法: get_ip() - str: 获取当前完整的 IP 地址 set_ip(ip: str): 设置 IP 地址 is_valid() - bool: 检查当前 IP 是否有效 clear(): 清空所有输入段 set_enabled(enabled: bool): 设置控件启用/禁用状态 set_placeholder_text(text: str): 设置占位符文本 使用示例: root tk.Tk() ip_input Windows10IPInput(root) ip_input.pack(padx20, pady20) # 设置初始值 ip_input.set_ip(192.168.1.1) # 获取输入结果 ip ip_input.get_ip() def __init__(self, parent, **kwargs): # 默认参数 default_kwargs { padding: (0, 0, 0, 0) } default_kwargs.update(kwargs) super().__init__(parent, **default_kwargs) # 配置样式 self.style ttk.Style() # 存储四个段的变量 self.segment_vars [tk.StringVar() for _ in range(4)] self.segments [] self.dot_labels [] # 回调函数 self.ip_change_callback None self.ip_complete_callback None # 设置背景色 self.configure(styleIP.Container.TFrame) self._setup_ui() self._setup_style() def _setup_ui(self): 初始化 UI # 使用 Frame 包裹来确保边框完整显示 self.border_frame tk.Frame(self, bg#cccccc, highlightthickness0) self.border_frame.pack(filltk.BOTH, expandTrue, padx2, pady2) # 内部白色背景区域 self.inner_frame tk.Frame(self.border_frame, bgwhite, highlightthickness0) self.inner_frame.pack(filltk.X, sidetk.TOP) # 在内部 Frame 中创建容器 self.container ttk.Frame(self.inner_frame, styleIP.Container.TFrame) self.container.pack(filltk.BOTH, expandTrue, padx1, pady1) # 创建 4 个 IP 段输入框 for i in range(4): # 创建输入框 segment IPSegmentEntry(self.container, i) segment.grid(row0, columni*2, padx(0 if i 0 else 1, 0 if i 3 else 1), pady3, ipady3, stickyns) self.segments.append(segment) # 同步 segment_vars 到 segment 内部的 var self.segment_vars[i] segment.var # 设置回调 segment.set_segment_completed(lambda idxi: self._focus_next_segment(idx)) segment.set_segment_back(lambda idxi: self._focus_previous_segment(idx)) segment.set_on_text_change(lambda: self._on_text_changed()) # 添加点号分隔符最后一段不需要 if i 3: dot_label ttk.Label(self.container, text., font(Segoe UI, 14, bold), foreground#666666, backgroundwhite) dot_label.grid(row0, columni*21, padx0, pady3) self.dot_labels.append(dot_label) # 配置列权重 for i in range(7): if i % 2 0: self.container.grid_columnconfigure(i, weight1) else: self.container.grid_columnconfigure(i, weight0) # 设置初始焦点到第一个输入框 self.after(100, lambda: self._set_initial_focus()) def _setup_style(self): 设置整体样式 # 配置自定义样式 self.style.configure(IP.Container.TFrame, backgroundwhite) self.style.configure(IP.Dot.TLabel, backgroundwhite, foreground#666666) # 为点号设置样式 for dot in self.dot_labels: dot.configure(styleIP.Dot.TLabel) def _focus_next_segment(self, current_index): 聚焦到下一个输入框 if current_index 3: next_segment self.segments[current_index 1] next_segment.focus_set() next_segment.selection_range(0, tk.END) def _focus_previous_segment(self, current_index): 聚焦到上一个输入框 if current_index 0: prev_segment self.segments[current_index - 1] prev_segment.focus_set() prev_segment.selection_range(0, tk.END) def _on_text_changed(self): 文本变化处理 # 获取当前 IP ip self.get_ip() # 触发回调 if self.ip_change_callback: self.ip_change_callback(ip) # 检查是否完成 self._check_completion() def _check_completion(self): 检查 IP 是否输入完成 all_filled all( seg.get().isdigit() and 0 int(seg.get()) 255 for seg in self.segments ) if all_filled and self.ip_complete_callback: self.ip_complete_callback() def get_ip(self) - str: 获取完整的 IP 地址 return ..join(var.get() for var in self.segment_vars) def set_ip(self, ip: str): 设置 IP 地址 parts ip.split(.) if len(parts) ! 4: raise ValueError(无效的 IP 地址格式) for i, part in enumerate(parts): # 验证每一段 value int(part) if value 0 or value 255: raise ValueError(fIP 地址第{i1}段超出范围 (0-255)) self.segment_vars[i].set(part) # 聚焦到第一个有空的段或最后一个段 for i, var in enumerate(self.segment_vars): if not var.get(): self.segments[i].focus_set() return self.segments[-1].focus_set() def clear(self): 清空所有输入 for var in self.segment_vars: var.set() self.segments[0].focus_set() def is_valid(self) - bool: 检查 IP 地址是否有效 try: ip self.get_ip() if not ip or ip.count(.) ! 3: return False parts ip.split(.) if len(parts) ! 4: return False for part in parts: if not part: return False value int(part) if value 0 or value 255: return False return True except (ValueError, AttributeError): return False def set_enabled(self, enabled: bool): 设置启用/禁用状态 state normal if enabled else disabled for segment in self.segments: segment.config(statestate) # 更新点号颜色 color #666666 if enabled else #cccccc for dot in self.dot_labels: dot.config(foregroundcolor) def set_placeholder_text(self, text: str 0): 设置占位符文本 # Tkinter Entry 不直接支持 placeholder可以通过其他方式实现 pass def bind_ip_change(self, callback): 绑定 IP 变化事件 self.ip_change_callback callback def bind_ip_complete(self, callback): 绑定 IP 完成事件 self.ip_complete_callback callback def _on_frame_resize(self, event): Frame 大小变化时调整容器 # 不需要额外处理container 会自动适应 inner_frame 的大小 pass def _set_initial_focus(self): 设置初始焦点到第一个输入框 if self.segments: self.segments[0].focus_set() # # 简单测试版本 # if __name__ __main__: root tk.Tk() root.title(Windows 10 IP 输入控件 - Tkinter 版本) root.geometry(400x200) root.configure(bg#f0f0f0) # 主框架 main_frame ttk.Frame(root, padding20) main_frame.pack(filltk.BOTH, expandTrue) # 标题 title_label ttk.Label(main_frame, textIP 地址输入测试, font(Segoe UI, 14, bold)) title_label.pack(anchortk.W, pady(0, 15)) # IP 输入控件 ip_input Windows10IPInput(main_frame) ip_input.pack(filltk.X, pady5) # 设置默认值 # ip_input.set_ip(192.168.1.1) # 显示当前 IP result_label ttk.Label(main_frame, text, font(Segoe UI, 10)) result_label.pack(anchortk.W, pady5) def update_result(ip): if ip_input.is_valid(): result_label.config(textf✓ 有效 IP: {ip}, foregroundgreen) else: result_label.config(textf当前 IP: {ip}, foreground#666666) ip_input.bind_ip_change(update_result) # 按钮 btn_frame ttk.Frame(main_frame) btn_frame.pack(filltk.X, pady10) def on_get_ip(): ip ip_input.get_ip() print(f获取 IP: {ip}) update_result(ip) def on_clear(): ip_input.clear() result_label.config(text已清空, foreground#666666) get_btn ttk.Button(btn_frame, text获取 IP, commandon_get_ip) get_btn.pack(sidetk.LEFT, padx(0, 10)) clear_btn ttk.Button(btn_frame, text清空, commandon_clear) clear_btn.pack(sidetk.LEFT) # 启动主循环 print(程序已启动请测试 IP 输入功能...) print(测试要点) print(1. 输入数字0-255) print(2. 按点号、空格或右箭头跳转到下一段) print(3. 按退格键删除内容) print(4. 使用左右箭头键导航) root.mainloop()2.PyQt 实现 Windows 10 风格 IP 地址输入控件 这个模块提供了高度还原 Windows 10 风格的 IP 地址输入控件具备以下特性 主要功能: 1. 自动焦点管理 - 输入 3 位数字后自动跳转到下一段 2. 智能输入验证 - 只允许 0-255 范围内的数字 3. 视觉反馈 - 聚焦、错误状态等 4. 键盘导航 - 支持方向键、点号、空格跳转 5. Windows 10 风格 - 现代简洁的外观设计 基本用法: from UI.ip_address_input import Windows10IPInput # 创建控件 ip_input Windows10IPInput() # 设置 IP 地址 ip_input.set_ip(192.168.1.1) # 获取 IP 地址 ip ip_input.get_ip() # 验证 IP if ip_input.is_valid(): print(IP 地址有效) # 连接信号 ip_input.ip_changed.connect(lambda ip: print(fIP 变化{ip})) ip_input.ip_completed.connect(lambda: print(IP 输入完成)) 作者: Xiao Ming 版本: 1.0 from PyQt5.QtCore import pyqtSignal, Qt, QRegExp from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QLabel, QApplication from PyQt5.QtGui import QPainter, QColor, QPen, QValidator, QFocusEvent class IPSegmentValidator(QValidator): IP 段验证器 专门用于验证 IP 地址单个数字段0-255的有效性。 提供三种验证状态 - Invalid: 无效输入包含非数字字符或数值超出范围 - Intermediate: 中间状态正在输入中 - Acceptable: 可接受输入完整且有效的数值 使用示例: validator IPSegmentValidator() state, text, pos validator.validate(255, 0) # 返回 QValidator.Acceptable因为 255 在有效范围内 IP 段验证器 - 验证 0-255 范围内的数字 def __init__(self, parentNone): super().__init__(parent) self.max_value 255 def validate(self, input_str, pos): if not input_str: return QValidator.Intermediate, input_str, pos # 只允许数字 if not input_str.isdigit(): return QValidator.Invalid, input_str, pos # 检查数值范围 value int(input_str) if value self.max_value: return QValidator.Invalid, input_str, pos # 如果输入了 3 位数字且有效则接受 if len(input_str) 3 and value self.max_value: return QValidator.Acceptable, input_str, pos # 少于 3 位数字中间状态 return QValidator.Intermediate, input_str, pos class IPSegmentLineEdit(QLineEdit): IP 段输入框 - 单个数字段的输入控件 实现了 Windows 10 风格的单个 IP 数字段输入框支持 特性: - 固定宽度显示居中对齐 - 数字输入限制仅允许 0-255 的数字 - 自动跳转功能输入完成后自动移动到下一字段 - 键盘导航支持方向键、退格键、点号、空格 - 视觉反馈聚焦状态、错误状态指示 信号: segment_completed: 当输入完成需要跳转到下一段时发射 segment_back: 当需要跳转到上一段如退格键时发射 使用场景: 通常不直接使用而是作为 Windows10IPInput 控件的内部组件。 示例: # 在组合框中使用 segment IPSegmentLineEdit(0) # 第一个段 segment.segment_completed.connect(lambda: focus_next_segment(0)) # 自定义信号当输入完成需要跳转到下一段 segment_completed pyqtSignal() # 自定义信号当需要跳转到上一段退格时 segment_back pyqtSignal() def __init__(self, index, parentNone): super().__init__(parent) self.index index self.setup_ui() self.setup_style() def setup_ui(self): # 设置验证器 self.validator IPSegmentValidator(self) self.setValidator(self.validator) # 设置最大长度 self.setMaxLength(3) # 设置对齐方式 self.setAlignment(Qt.AlignCenter) # 设置固定宽度 # self.setFixedSize(60, 40) def setup_style(self): 设置 Windows 10 风格 self.setStyleSheet( QLineEdit { border: 2px solid #cccccc; border-radius: 4px; background-color: white; padding: 5px; font-size: 16px; font-family: Segoe UI, Arial, sans-serif; } QLineEdit:focus { border: 2px solid #0078D7; background-color: white; } QLineEdit:disabled { background-color: #f5f5f5; color: #999999; } ) def keyPressEvent(self, event): 处理键盘事件 key event.key() # 处理点号或空格 - 跳转到下一段 if key in [Qt.Key_Period, Qt.Key_Comma, Qt.Key_Space]: self.segment_completed.emit() event.ignore() return # 处理退格键 if key Qt.Key_Backspace: if not self.text(): self.segment_back.emit() return # 处理方向键 if key Qt.Key_Right: self.segment_completed.emit() return if key Qt.Key_Left: self.segment_back.emit() return super().keyPressEvent(event) # 如果输入了 3 位有效数字自动跳转 if self.hasAcceptableInput() and len(self.text()) 3: self.segment_completed.emit() def focusInEvent(self, event): 焦点进入事件 super().focusInEvent(event) # 全选文本 self.selectAll() def paintEvent(self, event): 绘制事件 - 添加错误状态指示 super().paintEvent(event) # 如果有错误绘制红色边框 if self.validator and self.text(): state self.validator.validate(self.text(), 0)[0] if state QValidator.Invalid: painter QPainter(self) pen QPen(QColor(#FF0000), 2) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing) painter.drawRoundedRect(self.rect().adjusted(1, 1, -1, -1), 3, 3) class Windows10IPInput(QWidget): Windows 10 风格 IP 地址输入控件 一个完整的 IP 地址输入解决方案提供现代化的用户界面和流畅的交互体验。 由四个 IPSegmentLineEdit 组件组成通过点号分隔形成标准的 IPv4 输入格式。 主要特性: - 直观的输入体验输入三位数字后自动跳转到下一段 - 多种跳转方式支持点号、空格、右箭头键跳转到下一段 - 完善的导航支持左右箭头键在各段之间移动 - 实时验证输入时即时验证数值有效性0-255 - 视觉反馈清晰的聚焦状态和错误指示 - 响应式设计支持启用/禁用状态切换 - 灵活配置可设置占位符文本、默认值等 信号: ip_changed(str): IP 地址发生变化时发射参数为当前 IP 字符串 ip_completed(): 所有四个段都输入完成时发射 方法摘要: get_ip() - str: 获取当前完整的 IP 地址 set_ip(ip: str): 设置 IP 地址 is_valid() - bool: 检查当前 IP 是否有效 clear(): 清空所有输入段 set_enabled(enabled: bool): 设置控件启用/禁用状态 set_placeholder_text(text: str): 设置占位符文本 使用示例: # 创建并添加到布局 ip_input Windows10IPInput() layout.addWidget(ip_input) # 设置初始值 ip_input.set_ip(192.168.1.1) # 获取输入结果 ip ip_input.get_ip() # 连接信号处理 ip_input.ip_changed.connect(self.handle_ip_change) ip_input.ip_completed.connect(self.handle_ip_complete) # IP 地址改变信号 ip_changed pyqtSignal(str) # IP 输入完成信号 ip_completed pyqtSignal() def __init__(self, parentNone): super().__init__(parent) self.setup_ui() self.setup_style() self.connect_signals() def setup_ui(self): 初始化 UI - 使用单个统一容器 main_layout QHBoxLayout(self) main_layout.setSpacing(0) main_layout.setContentsMargins(0, 0, 0, 0) # 创建一个统一的容器来包裹所有段 self.container QWidget() container_layout QHBoxLayout(self.container) container_layout.setSpacing(0) container_layout.setContentsMargins(5, 0, 5, 0) # 左右留一点内边距 # 创建 4 个 IP 段输入框 self.segments [] for i in range(4): segment IPSegmentLineEdit(i, self) self.segments.append(segment) container_layout.addWidget(segment) # 添加点号分隔符最后一段不需要 if i 3: dot_label QLabel(.) dot_label.setAlignment(Qt.AlignCenter) dot_label.setObjectName(fdot_{i}) # 点号样式 - 无边框透明背景 dot_label.setStyleSheet( QLabel { font-size: 24px; color: #666666; font-family: Segoe UI, Arial, sans-serif; background-color: transparent; border: none; padding: 0px; margin: 0px; } ) dot_label.setFixedWidth(5) # 设置固定宽度 container_layout.addWidget(dot_label) main_layout.addWidget(self.container) def setup_style(self): 设置整体样式 - 统一边框和背景 # 主控件不设置样式让容器继承系统默认 # 设置容器样式 - 整体边框内部白色背景 self.container.setStyleSheet( QWidget { border: 2px solid #cccccc; border-radius: 4px; background-color: white; padding: 0px; } QWidget:focus { border: 2px solid #0078D7; } ) # 设置各个输入段的样式 - 内部无边框 for segment in self.segments: segment.setStyleSheet( QLineEdit { border: none; background-color: transparent; padding: 5px 2px; font-size: 16px; font-family: Segoe UI, Arial, sans-serif; } QLineEdit:focus { border: none; background-color: transparent; } QLineEdit:disabled { background-color: transparent; color: #999999; } ) def connect_signals(self): 连接信号 for i, segment in enumerate(self.segments): segment.segment_completed.connect( lambda idxi: self.focus_next_segment(idx) ) segment.segment_back.connect( lambda idxi: self.focus_previous_segment(idx) ) segment.textChanged.connect(self.on_text_changed) def focus_next_segment(self, current_index): 聚焦到下一个输入框 if current_index 3: next_segment self.segments[current_index 1] next_segment.setFocus() next_segment.selectAll() def focus_previous_segment(self, current_index): 聚焦到上一个输入框 if current_index 0: prev_segment self.segments[current_index - 1] prev_segment.setFocus() prev_segment.selectAll() def on_text_changed(self, text): 文本变化处理 sender self.sender() # 验证当前段是否有效 if sender.text(): validator sender.validator state validator.validate(sender.text(), 0)[0] if state QValidator.Invalid: # 可以在这里添加错误提示 pass # 检查所有段是否都已填写 self.check_completion() # 发送 IP 变化信号 ip self.get_ip() self.ip_changed.emit(ip) def check_completion(self): 检查 IP 是否输入完成 all_filled all( seg.hasAcceptableInput() and seg.text() for seg in self.segments ) if all_filled: self.ip_completed.emit() def get_ip(self) - str: 获取完整的 IP 地址 return ..join(seg.text() for seg in self.segments) def set_ip(self, ip: str): 设置 IP 地址 parts ip.split(.) if len(parts) ! 4: raise ValueError(无效的 IP 地址格式) for i, (segment, part) in enumerate(zip(self.segments, parts)): # 验证每一段 value int(part) if value 0 or value 255: raise ValueError(fIP 地址第{i1}段超出范围 (0-255)) segment.setText(part) # 聚焦到第一个有空的段或最后一个段 for i, segment in enumerate(self.segments): if not segment.text(): segment.setFocus() return self.segments[-1].setFocus() def clear(self): 清空所有输入 for segment in self.segments: segment.clear() self.segments[0].setFocus() def is_valid(self) - bool: 检查 IP 地址是否有效 ip self.get_ip() if not ip or ip.count(.) ! 3: return False try: parts ip.split(.) if len(parts) ! 4: return False for part in parts: value int(part) if value 0 or value 255: return False return True except (ValueError, AttributeError): return False def set_enabled(self, enabled: bool): 设置启用/禁用状态 for segment in self.segments: segment.setEnabled(enabled) def set_placeholder_text(self, text: str 0): 设置占位符文本 for segment in self.segments: segment.setPlaceholderText(text) # # 高级使用示例和集成指南 # class AdvancedUsageExample: 高级使用示例类展示各种应用场景 staticmethod def example_in_form(): 在表单中使用的示例 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel widget QWidget() layout QVBoxLayout(widget) layout.setContentsMargins(10, 10, 10, 10) # 创建 IP 输入控件 ip_input Windows10IPInput() layout.addWidget(ip_input) # 添加保存按钮 save_btn QPushButton(保存配置) layout.addWidget(save_btn) # 连接保存功能 def on_save(): if ip_input.is_valid(): ip ip_input.get_ip() print(f✓ 保存 IP 配置: {ip}) else: print(✗ 无法保存无效的 IP 地址) save_btn.clicked.connect(on_save) return widget staticmethod def example_with_validation(): 带实时验证反馈的示例 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel widget QWidget() layout QVBoxLayout(widget) layout.setContentsMargins(10, 10, 10, 10) ip_input Windows10IPInput() layout.addWidget(ip_input) # 添加验证结果标签 status_label QLabel(等待输入...) status_label.setStyleSheet(padding: 8px; font-size: 13px;) layout.addWidget(status_label) # 实时更新验证状态 def update_status(ip): if ip_input.is_valid(): status_label.setText(f✓ {ip} - 有效 IP 地址) status_label.setStyleSheet(color: green; padding: 8px;) else: status_label.setText(f✗ {ip} - 无效 IP 地址) status_label.setStyleSheet(color: red; padding: 8px;) ip_input.ip_changed.connect(update_status) return widget staticmethod def example_multiple_inputs(): 多个 IP 输入框的表单示例 from PyQt5.QtWidgets import QWidget, QFormLayout widget QWidget() layout QFormLayout(widget) layout.setSpacing(10) # 创建多个 IP 输入框 start_ip Windows10IPInput() end_ip Windows10IPInput() gateway_ip Windows10IPInput() subnet_mask Windows10IPInput() # 添加到布局 layout.addRow(起始 IP:, start_ip) layout.addRow(结束 IP:, end_ip) layout.addRow(网关地址:, gateway_ip) layout.addRow(子网掩码:, subnet_mask) # 设置默认值 start_ip.set_ip(192.168.1.1) end_ip.set_ip(192.168.1.254) gateway_ip.set_ip(192.168.1.1) subnet_mask.set_ip(255.255.255.0) return widget staticmethod def example_readonly_mode(): 只读/编辑模式切换示例 from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton widget QWidget() layout QVBoxLayout(widget) layout.setContentsMargins(10, 10, 10, 10) ip_input Windows10IPInput() ip_input.set_ip(10.0.0.1) layout.addWidget(ip_input) # 切换编辑/只读模式 toggle_btn QPushButton(切换到只读模式) layout.addWidget(toggle_btn) is_readonly False def toggle(): nonlocal is_readonly is_readonly not is_readonly ip_input.set_enabled(not is_readonly) toggle_btn.setText(切换到编辑模式 if is_readonly else 切换到只读模式) toggle_btn.clicked.connect(toggle) return widget def integrate_with_existing_ui(): 集成到现有 UI 项目的示例 展示如何将此控件集成到现有的 PyQt5 应用程序中。 假设你已经有一个基于 PyQt5 的项目结构可以这样集成 # 此处仅为演示集成思路实际使用时需要根据具体项目调整 class ExampleIntegration: def __init__(self): self.ip_input_widget Windows10IPInput() # 连接业务逻辑 self.ip_input_widget.ip_changed.connect(self.on_ip_changed) self.ip_input_widget.ip_completed.connect(self.on_ip_complete) def on_ip_changed(self, ip): IP 地址变化时的处理 print(fIP 地址已更改{ip}) # 在这里添加你的业务逻辑比如更新网络配置 def on_ip_complete(self): IP 输入完成时的处理 ip self.ip_input_widget.get_ip() print(fIP 输入完成{ip}) # 可以在这里自动触发保存或其他操作 return ExampleIntegration # # 主要演示程序 # if __name__ __main__: import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel, QFormLayout app QApplication(sys.argv) # 创建主窗口 window QMainWindow() window.setWindowTitle(Windows 10 IP 输入控件 - 完整示例) window.setGeometry(100, 100, 600, 500) central_widget QWidget() window.setCentralWidget(central_widget) main_layout QVBoxLayout(central_widget) main_layout.setContentsMargins(20, 20, 20, 20) main_layout.setSpacing(15) # 标题 title_label QLabel(IP 地址配置管理) title_label.setStyleSheet(font-size: 18px; font-weight: bold; padding: 10px;) main_layout.addWidget(title_label) # 示例 1: 基础 IP 输入 section1_label QLabel(1. 基础 IP 输入:) section1_label.setStyleSheet(font-size: 14px; font-weight: bold;) main_layout.addWidget(section1_label) basic_ip Windows10IPInput() main_layout.addWidget(basic_ip) # 示例 2: 带实时验证 section2_label QLabel(2. 带实时验证:) section2_label.setStyleSheet(font-size: 14px; font-weight: bold;) main_layout.addWidget(section2_label) validated_ip Windows10IPInput() main_layout.addWidget(validated_ip) validation_label QLabel(等待输入...) validation_label.setStyleSheet(padding: 8px; font-size: 13px;) main_layout.addWidget(validation_label) def update_validation(ip): if validated_ip.is_valid(): validation_label.setText(f✓ 有效 IP: {ip}) validation_label.setStyleSheet(color: green; padding: 8px;) else: validation_label.setText(f✗ 无效 IP: {ip}) validation_label.setStyleSheet(color: red; padding: 8px;) validated_ip.ip_changed.connect(update_validation) # 示例 3: 完整网络配置表单 section3_label QLabel(3. 完整网络配置:) section3_label.setStyleSheet(font-size: 14px; font-weight: bold;) main_layout.addWidget(section3_label) form_widget QWidget() form_layout QFormLayout(form_widget) form_layout.setSpacing(10) ip_address Windows10IPInput() subnet_mask Windows10IPInput() gateway Windows10IPInput() ip_address.set_ip(192.168.1.100) subnet_mask.set_ip(255.255.255.0) gateway.set_ip(192.168.1.1) form_layout.addRow(IP 地址:, ip_address) form_layout.addRow(子网掩码:, subnet_mask) form_layout.addRow(默认网关:, gateway) main_layout.addWidget(form_widget) # 操作按钮 button_layout QHBoxLayout() save_btn QPushButton(保存配置) save_btn.setStyleSheet( QPushButton { background-color: #0078D7; color: white; border: none; padding: 10px 20px; border-radius: 4px; font-size: 14px; min-width: 100px; } QPushButton:hover { background-color: #005A9E; } QPushButton:pressed { background-color: #004578; } ) button_layout.addWidget(save_btn) reset_btn QPushButton(重置) reset_btn.setStyleSheet( QPushButton { background-color: #cccccc; color: #333333; border: none; padding: 10px 20px; border-radius: 4px; font-size: 14px; min-width: 100px; } QPushButton:hover { background-color: #bbbbbb; } ) button_layout.addWidget(reset_btn) main_layout.addLayout(button_layout) # 连接按钮功能 def on_save(): configs [] valid_count 0 for ip_widget in [basic_ip, validated_ip, ip_address, subnet_mask, gateway]: if ip_widget.is_valid(): configs.append(ip_widget.get_ip()) valid_count 1 else: print(f⚠️ 无效的 IP: {ip_widget.get_ip()}) print(f✅ 保存 {valid_count}/5 个有效配置{configs}) def on_reset(): for ip_widget in [basic_ip, validated_ip, ip_address, subnet_mask, gateway]: ip_widget.clear() print( 所有输入已重置) save_btn.clicked.connect(on_save) reset_btn.clicked.connect(on_reset) # 添加弹性空间 main_layout.addStretch() window.show() sys.exit(app.exec_())

相关新闻

【避坑指南】ConcurrentHashMap 并发操作的致命陷阱

【避坑指南】ConcurrentHashMap 并发操作的致命陷阱

注:本文是笔者在学习【极客时间】业务开发常见错误过程中,整理记载的个人学习和思考笔记 在高并发编程中,ConcurrentHashMap 因线程安全特性被广泛使用,但很多开发者误以为「用了 ConcurrentHashMap 就万事大吉」,却忽…

2026/7/3 8:36:43 阅读更多 →
【RTX4070】12g显存 ComfyUI AI 视频 (T2V/I2V) 避坑与实战指南

【RTX4070】12g显存 ComfyUI AI 视频 (T2V/I2V) 避坑与实战指南

进阶之路:资深玩家的 ComfyUI AI 视频 (T2V/I2V) 避坑与实战指南 对于习惯了代码逻辑的开发者来说,初入 ComfyUI 的感觉就像是接手了一个没有说明文档的开源微服务架构。节点满天飞、连线如乱麻、动不动就爆显存(OOM)或者产出“电…

2026/5/17 12:55:38 阅读更多 →
ssm+java2026年毕设社区少年儿童读物共享系统【源码+论文】

ssm+java2026年毕设社区少年儿童读物共享系统【源码+论文】

本系统(程序源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、选题背景关于图书管理与分享问题的研究,现有研究主要以传统图书馆管理系统和数字化阅读平台为主,专门针对社交化…

2026/7/3 19:36:42 阅读更多 →

最新新闻

VisProg与GPT-3的完美结合:揭秘自然语言生成Python视觉程序的黑科技

VisProg与GPT-3的完美结合:揭秘自然语言生成Python视觉程序的黑科技

VisProg与GPT-3的完美结合:揭秘自然语言生成Python视觉程序的黑科技 【免费下载链接】visprog Official code for VisProg (CVPR 2023 Best Paper!) 项目地址: https://gitcode.com/gh_mirrors/vi/visprog 想要让AI理解你的自然语言指令并自动生成Python视觉…

2026/7/4 6:52:54 阅读更多 →
深入理解Laravel Vonage Notification Channel的核心组件:从ServiceProvider到Message类

深入理解Laravel Vonage Notification Channel的核心组件:从ServiceProvider到Message类

深入理解Laravel Vonage Notification Channel的核心组件:从ServiceProvider到Message类 【免费下载链接】vonage-notification-channel Vonage Notification Channel for Laravel. 项目地址: https://gitcode.com/gh_mirrors/vo/vonage-notification-channel …

2026/7/4 6:52:54 阅读更多 →
SQL聚合函数实战:SQL Ultimate Course数据分析基础指南

SQL聚合函数实战:SQL Ultimate Course数据分析基础指南

SQL聚合函数实战:SQL Ultimate Course数据分析基础指南 【免费下载链接】sql-ultimate-course The most comprehensive SQL guide from a real-world expert! Learn everything from basics to advanced queries, optimizations, and real-world SQL 项目地址: h…

2026/7/4 6:46:51 阅读更多 →
switch.vim性能优化:大型代码库中的高效文本切换策略终极指南

switch.vim性能优化:大型代码库中的高效文本切换策略终极指南

switch.vim性能优化:大型代码库中的高效文本切换策略终极指南 【免费下载链接】switch.vim A simple Vim plugin to switch segments of text with predefined replacements 项目地址: https://gitcode.com/gh_mirrors/sw/switch.vim 你是否在大型代码库中频…

2026/7/4 6:46:51 阅读更多 →
如何智能切换DLSS版本:游戏性能优化的终极指南

如何智能切换DLSS版本:游戏性能优化的终极指南

如何智能切换DLSS版本:游戏性能优化的终极指南 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 还在为游戏卡顿而烦恼吗?想要提升游戏帧率却不知从何下手?DLSS Swapper正是你需要的游…

2026/7/4 6:44:51 阅读更多 →
CANN/asc-devkit LoadData矩阵搬运

CANN/asc-devkit LoadData矩阵搬运

# LoadData(2D矩阵搬运) 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景…

2026/7/4 6:44:51 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻