关于window.event.returnValue=false的用处

本文介绍了如何使用window.event.returnValue=false来取消表单提交或阻止超链接的默认行为。此外,还提供了一个示例代码,展示了如何结合confirm对话框来实现这一功能。

window.event.returnValue=false放在提交表单中的onclick事件中则不会提交表单,如果放到超链接中则不执行超链接,也就是它禁止了或取消了请求,没有任何效果。

比如:

 if (confirm("确认要删除订单吗?")) {
                $.ajax({

alert("YES");
                    //这里执行动作...

})

}
else {
                   window.event.returnValue = false;
         }
 当弹出这个窗口时 ,点击“确定”会弹出Yes ,点击取消会关闭窗口。

import PySimpleGUI as Py import time import threading import os import queue image_path1 = "D:/software/demo/pythonProject/images/image1.png" image_path2 = "D:/software/demo/pythonProject/images/image2.png" # 检查图片是否存在 if not os.path.exists(image_path1): print(f"[!] 图片1不存在: {image_path1}") image_path1 = None if not os.path.exists(image_path2): print(f"[!] 图片2不存在: {image_path2}") image_path2 = None a = 'jyrz' g = 'zbjszj' layout1 = [ [Py.Text('jdsj--')], [Py.Button('tips'), Py.Button('wykd')] ] window_position = (210, 0) # 定义主窗口的布局,这里设置了窗口在屏幕上的起始位置为(横坐标50, 纵坐标50) window1 = Py.Window('jdsq', layout1, size=(1500, 68), no_titlebar=True, location=window_position, finalize=True) window1.keep_on_top_set() Py.theme('DarkBlue3') # PySimpleGUI 设置主题颜色 def run_single_flow(): """运行一次完整的 window3 流程""" Py.theme('LightBlue') input_history = [] # 存储已确认的数字 last_input_time = None INPUT_TIMEOUT = 5.0 current_text = '' # 使用一个固定宽度的 Text 框实现横向排列 + 自动换行 layout3 = [ [Py.Image(key='img1', filename=image_path1) if image_path1 else Py.Text("加载失败")], [Py.Text("请在5秒内输入一个数字,之后5秒无操作将自动记录:")], [Py.Input(key='-INPUT-', size=(20, 1), focus=True)], [Py.Text("", size=(60, 1), key='-STATUS-')], [Py.Text("已记录的数字(横向排列,自动换行):")], # 设置 size=(None, 10) 表示不限宽度列,高度最多10行;text_color 和 background_color 提升可读性 [Py.Frame('', [[ Py.Text("", size=(600, 10), # 长度约600字符,超出则自动换行,最多10行 key='-HISTORY-', relief='sunken', background_color='white', text_color='black', font=('Courier', 10)) ]], size=(600, 50), pad=10)], # 控制整体显示区域大小以便触发换行 [Py.Button('cxxldb')], [Py.Button('txlxk')], [Py.Button('lxbfh')], [Py.Button('--jchdj--')], ] window3 = Py.Window('自动换行横向记录器', layout3, resizable=True) while True: event3, values3 = window3.read(timeout=100) if event3 == Py.WINDOW_CLOSED: break new_text = values3['-INPUT-'].strip() input_changed = new_text != current_text current_text = new_text # 验证是否为有效数字 valid_number = False try: if current_text: float(current_text) valid_number = True except ValueError: pass # 输入变化且合法 → 重置计时器 if input_changed and valid_number: last_input_time = time.time() window3['-STATUS-'].update(f"✅ 输入中 '{current_text}' ... 5秒无操作将自动提交") # 超时自动提交 if last_input_time is not None: elapsed = time.time() - last_input_time if elapsed >= INPUT_TIMEOUT: try: num = float(current_text) formatted_num = int(num) if num.is_integer() else num input_history.append(formatted_num) # 更新历史显示:空格分隔,让系统自动换行 history_str = ' '.join(map(str, input_history)) window3['-HISTORY-'].update(history_str) window3['-STATUS-'].update("🎉 已自动记录!") window3['-INPUT-'].update('') current_text = '' last_input_time = None except Exception as e: window3['-STATUS-'].update("❌ 提交失败") last_input_time = None # 状态栏提示 elif last_input_time is None and current_text and not valid_number: window3['-STATUS-'].update("❌ 请输入有效的数字") elif last_input_time and valid_number: remaining = max(0, int(INPUT_TIMEOUT - (time.time() - last_input_time) + 0.9)) if remaining > 0: window3['-STATUS-'].update(f"⏳ 还剩 {remaining} 秒自动提交...") if event3 in (Py.WIN_CLOSED, 'lxbfh'): break # 正常退出 elif event3 == 'cxxldb': window1.hide() elif event3 == 'txlxk': window3.close() layout4 = [ [Py.Image(key='img1', filename=image_path1) if image_path1 else Py.Text("加载失败")], [Py.Text("请在5秒内输入一个数字,之后5秒无操作将自动记录:")], [Py.Input(key='-INPUT-', size=(20, 1), focus=True)], [Py.Text("", size=(60, 1), key='-STATUS-')], [Py.Text("已记录的数字(横向排列,自动换行):")], # 设置 size=(None, 10) 表示不限宽度列,高度最多10行;text_color 和 background_color 提升可读性 [Py.Frame('', [[ Py.Text("", size=(600, 10), # 长度约600字符,超出则自动换行,最多10行 key='-HISTORY-', relief='sunken', background_color='white', text_color='black', font=('Courier', 10)) ]], size=(600, 50), pad=10)], # 控制整体显示区域大小以便触发换行 [Py.Button('jrrsby')], [Py.Button('jrqsby')], ] window4 = Py.Window('自动换行横向记录器', layout4, resizable=True) while True: event4, values4 = window4.read(timeout=100) if event4 == Py.WINDOW_CLOSED: break new_text = values4['-INPUT-'].strip() input_changed = new_text != current_text current_text = new_text # 验证是否为有效数字 valid_number = False try: if current_text: float(current_text) valid_number = True except ValueError: pass # 输入变化且合法 → 重置计时器 if input_changed and valid_number: last_input_time = time.time() window4['-STATUS-'].update(f"✅ 输入中 '{current_text}' ... 5秒无操作将自动提交") # 超时自动提交 if last_input_time is not None: elapsed = time.time() - last_input_time if elapsed >= INPUT_TIMEOUT: try: num = float(current_text) formatted_num = int(num) if num.is_integer() else num input_history.append(formatted_num) # 更新历史显示:空格分隔,让系统自动换行 history_str = ' '.join(map(str, input_history)) window4['-HISTORY-'].update(history_str) window4['-STATUS-'].update("🎉 已自动记录!") window4['-INPUT-'].update('') current_text = '' last_input_time = None except Exception as e: window4['-STATUS-'].update("❌ 提交失败") last_input_time = None # 状态栏提示 elif last_input_time is None and current_text and not valid_number: window4['-STATUS-'].update("❌ 请输入有效的数字") elif last_input_time and valid_number: remaining = max(0, int(INPUT_TIMEOUT - (time.time() - last_input_time) + 0.9)) if remaining > 0: window4['-STATUS-'].update(f"⏳ 还剩 {remaining} 秒自动提交...") elif event4 == 'jrrsby': Py.theme('LightBlue') # 历史记录列表 recorded_numbers = [] # 定义布局 layout5 = [ [Py.Text("请输入一个数字:")], [Py.Input(key='-INPUT-', size=(30, 1), do_not_clear=False)], # do_not_clear=False 表示默认清空 [Py.Button('blkyjc', bind_return_key=True), Py.Button('删除')], [Py.HorizontalSeparator()], [Py.Text("已保留的数字(横向排列,自动换行):")], [Py.Text("", size=(50, 10), key='-HISTORY-', relief='sunken', background_color='white', text_color='black')] ] # 创建窗口 window5 = Py.Window('数字记录器 - 保留或删除', layout5) while True: event5, values5 = window5.read() if event5 == Py.WINDOW_CLOSED: break input_value = values5['-INPUT-'].strip() if event5 == 'blkyjc': timer_queue = queue.Queue() stop_timer = threading.Event() # 控制是否继续提醒循环 # 主窗口布局 layout7 = [ [Py.Text("已录入的数值记录:")], [Py.Multiline("", size=(60, 10), key='-OUTPUT-', disabled=True, autoscroll=True)], [Py.Button('kstx'), Py.Button('yzxpc')] ] window7 = Py.Window('周期性提醒输入器', layout7) # 定时器线程:严格每5秒发一次事件(除非被 stop) def show_gift_popup(q, stop_flag): while not stop_flag.is_set(): time.sleep(5) # 每隔5秒发送一个弹窗请求 if not stop_flag.is_set(): # 如果未被停止 q.put(('SHOW_POPUP', None)) # 主事件循环 while True: event7, values7 = window7.read(timeout=100) if event7 in (Py.WINDOW_CLOSED, 'yzxpc'): stop_timer.set() break if event7 == 'kstx' and not stop_timer.is_set(): stop_timer.clear() thread = threading.Thread(target=show_gift_popup, args=(timer_queue, stop_timer), daemon=True) thread.start() window7['kstx'].update(disabled=True) # 处理队列事件 try: q_event = timer_queue.get_nowait() if q_event[0] == 'SHOW_POPUP': user_input = Py.PopupGetText( '请输入一个数字(OK提交并结束,Cancel则5秒后重试):', title='提醒输入', keep_on_top=True ) if user_input is not None: # 用户点击了 OK try: num = float(user_input.strip()) formatted_num = int(num) if num.is_integer() else num window7['-OUTPUT-'].update(f"✔️ 录入成功:{formatted_num}\n", append=True) # ✅ 成功提交 → 停止所有后续提醒 stop_timer.set() except ValueError: # 输入无效,不记录,也不停止;继续下一轮提醒 Py.PopupOK("❌ 输入无效,将5秒后重试!", title="警告", icon=None) # else: 用户点了 Cancel → 什么也不做,定时器将继续运行,5秒后再弹 except queue.Empty: pass # 无事件则跳过 action = show_gift_popup() if input_value == '': window4['-HISTORY-'].update("⚠️ 输入为空,无法保留") else: try: num = float(input_value) formatted_num = int(num) if num.is_integer() else num recorded_numbers.append(formatted_num) # 更新历史显示(横向空格分隔,自动换行) history_text = ' '.join(map(str, recorded_numbers)) window5['-HISTORY-'].update(history_text) # 清空输入框(do_not_clear=False 已自动处理,但仍显式更新以防万一) window5['-INPUT-'].update('') except ValueError: window5['-STATUS-'].update("❌ 不是有效数字!") elif event5 == '删除': # 直接清空输入框 window5['-INPUT-'].update('') elif event4 == 'jrqsby': Py.theme('LightBlue') # 历史记录列表 recorded_numbers = [] # 定义布局 layout6 = [ [Py.Text("请输入一个数字:")], [Py.Input(key='-INPUT-', size=(30, 1), do_not_clear=False)], # do_not_clear=False 表示默认清空 [Py.Button('blkyjc', bind_return_key=True), Py.Button('删除')], [Py.HorizontalSeparator()], [Py.Text("已保留的数字(横向排列,自动换行):")], [Py.Text("", size=(50, 10), key='-HISTORY-', relief='sunken', background_color='white', text_color='black')] ] # 创建窗口 window6 = Py.Window('数字记录器 - 保留或删除', layout6) while True: event6, values6 = window6.read() if event6 == Py.WINDOW_CLOSED: break input_value = values6['-INPUT-'].strip() if event6 == 'blkyjc': action = show_gift_popup() if input_value == '': window6['-HISTORY-'].update("⚠️ 输入为空,无法保留") else: try: num = float(input_value) formatted_num = int(num) if num.is_integer() else num recorded_numbers.append(formatted_num) # 更新历史显示(横向空格分隔,自动换行) history_text = ' '.join(map(str, recorded_numbers)) window6['-HISTORY-'].update(history_text) # 清空输入框(do_not_clear=False 已自动处理,但仍显式更新以防万一) window6['-INPUT-'].update('') except ValueError: window6['-STATUS-'].update("❌ 不是有效数字!") elif event6 == '删除': # 直接清空输入框 window6['-INPUT-'].update('') elif event3 == '--jchdj--': window3.un_hide() window1.hide() # 弹出礼物窗口 action = show_gift_popup() # 主事件循环 while True: event1, values1 = window1.read() if event1 == Py.WIN_CLOSED: break if event1 == 'tips': layout2 = [[Py.Text(g, size=(170, 2), auto_size_text=True)]] window2 = Py.Window('ktrx', layout2, size=(940, 210), finalize=True, keep_on_top=True) window2.read(timeout=5000, close=True) if event1 == 'wykd': run_single_flow()
最新发布
11-09
class ChartDialog(QDialog): """数据分析(折线图)弹窗""" def __init__(self, data=None, parent=None): super().__init__(parent) self.setWindowTitle("流程时间折线图") self.layout = QVBoxLayout(self) # 流程选择下拉框 self.process_combo = QComboBox() self.process_combo.addItems(process_names) self.process_combo.setCurrentIndex(0) self.layout.addWidget(QLabel("选择流程:")) self.layout.addWidget(self.process_combo) # 图表画布 self.figure = plt.figure(figsize=(10, 6)) self.canvas = FigureCanvas(self.figure) self.layout.addWidget(self.canvas) # 绑定下拉框选择变化事件 self.process_combo.currentIndexChanged.connect(self.plot_selected) # 初始化数据 self.data = data self.tooltip = None self.train_ids = [] self.x = [] self.y = [] self.line = None self.ax = None # 初始绘图 self.plot_selected() def plot_selected(self): selected_index = self.process_combo.currentIndex() selected_process = process_names[selected_index] # 清空图表 self.figure.clear() self.ax = self.figure.add_subplot(111) train_ids = sorted(self.data.keys()) x = list(range(len(train_ids))) if selected_process == "发车总时间": y = [sum(self.data[tid]) for tid in train_ids] avg_time = sum(y) / len(y) self.line, = self.ax.plot(x, y, marker='o', color='purple', linewidth=2, markersize=6, linestyle='-', zorder=2, label='发车总时间', picker=True, pickradius=5) # <<< 新增 picker 支持 self.ax.axhline(avg_time, linestyle='--', color='red', alpha=0.8, linewidth=1.5, zorder=1, label=f'平均总时间 ({avg_time:.1f} 分钟)') else: selected_index = process_names.index(selected_process) y = [self.data[tid][selected_index] for tid in train_ids] avg_time = sum(y) / len(y) self.line, = self.ax.plot(x, y, marker='o', color='blue', linewidth=2, markersize=6, linestyle='-', zorder=2, label='流程时间', picker=True, pickradius=5) # <<< 新增 picker 支持 self.ax.axhline(avg_time, linestyle='--', color='red', alpha=0.8, linewidth=1.5, zorder=1, label=f'平均时间 ({avg_time:.1f} 分钟)') # 设置图表样式 self.ax.set_title(f"列车{selected_process}组织时间采集折线图(分钟)") self.ax.xaxis.set_visible(False) # 去掉横坐标轴 yticks = self.ax.get_yticks() self.ax.yaxis.set_major_locator(plt.FixedLocator(yticks)) self.ax.yaxis.set_major_formatter(plt.FixedFormatter([f"{int(y)}" for y in yticks])) self.ax.grid(True, linestyle='--', alpha=0.5) self.ax.legend() # 保存变量 self.train_ids = train_ids self.x = x self.y = y # 解除旧的事件绑定(如果之前绑定过) if hasattr(self, 'motion_cid'): self.canvas.mpl_disconnect(self.motion_cid) if hasattr(self, 'click_cid'): self.canvas.mpl_disconnect(self.click_cid) if hasattr(self, 'pick_cid'): self.canvas.mpl_disconnect(self.pick_cid) # 重新绑定事件并保存连接ID self.motion_cid = self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move) self.click_cid = self.canvas.mpl_connect('button_press_event', self.on_click) self.pick_cid = self.canvas.mpl_connect('pick_event', self.on_pick) # <<< 新增 pick_event 绑定 self.canvas.draw() def on_pick(self, event): """使用 pick_event 实现稳定的悬停提示""" if event.artist != self.line: return ind = event.ind[0] # 获取最接近的数据点索引 x = self.x[ind] y = self.y[ind] train_id = self.train_ids[ind] selected_process = process_names[self.process_combo.currentIndex()] if selected_process == "发车总时间": total = sum(self.data[train_id]) text = f"车次: {train_id}\n总时间: {total:.0f} 分钟" else: selected_index = process_names.index(selected_process) value = self.data[train_id][selected_index] total = sum(self.data[train_id]) text = f"车次: {train_id}\n时间: {value:.0f} 分钟\n总时间: {total:.0f} 分钟" # 移除旧的 tooltip if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = None # 创建新的 tooltip,并设置 animated=True self.tooltip = self.ax.annotate( text, xy=(x, y), xytext=(10, 10), textcoords="offset points", bbox=dict(boxstyle="round,pad=0.3", facecolor="white", edgecolor="black", alpha=0.9), zorder=1000, fontsize=10, arrowprops=dict(arrowstyle="->", relpos=(0, 0)), animated=True # <<< 必须设置 ) # 将 tooltip 添加到 axes 中 self.ax.draw_artist(self.tooltip) # 使用 blit 局部刷新画布 self.canvas.blit(self.ax.bbox) self.canvas.flush_events() def on_mouse_move(self, event): """原有 mouse move 逻辑保留,用于其他用途""" if not hasattr(self, 'ax') or event.inaxes != self.ax: if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = None self.canvas.draw_idle() return if self.line is None: return xdata = self.line.get_xdata() ydata = self.line.get_ydata() if len(xdata) == 0 or len(ydata) == 0: return distances = [(x - event.xdata) ** 2 + (y - event.ydata) ** 2 for x, y in zip(xdata, ydata)] min_index = np.argmin(distances) min_distance = distances[min_index] threshold = 0.5 if min_distance < threshold: x = xdata[min_index] y = ydata[min_index] train_id = self.train_ids[min_index] selected_process = process_names[self.process_combo.currentIndex()] if selected_process == "发车总时间": total = sum(self.data[train_id]) text = f"车次: {train_id}\n总时间: {total:.0f} 分钟" else: selected_index = process_names.index(selected_process) value = self.data[train_id][selected_index] total = sum(self.data[train_id]) text = f"车次: {train_id}\n时间: {value:.0f} 分钟\n总时间: {total:.0f} 分钟" if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = self.ax.annotate( text, xy=(x, y), xytext=(10, 10), textcoords="offset points", bbox=dict(boxstyle="round,pad=0.3", facecolor="white", edgecolor="black", alpha=0.9), zorder=1000, fontsize=10, arrowprops=dict(arrowstyle="->", relpos=(0, 0)), animated=True # <<< 必须设置 ) self.ax.draw_artist(self.tooltip) self.canvas.blit(self.ax.bbox) self.canvas.flush_events() else: if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = None self.canvas.draw_idle() def on_click(self, event): if not hasattr(self, 'ax') or event.inaxes != self.ax: return try: xdata = self.line.get_xdata() ydata = self.line.get_ydata() distances = [(x - event.xdata) ** 2 + (y - event.ydata) ** 2 for x, y in zip(xdata, ydata)] min_index = np.argmin(distances) min_distance = distances[min_index] if min_distance < 0.1: train_id = self.train_ids[min_index] values = self.data[train_id] dialog = AnimatedTableDialog(train_id, values) dialog.exec() except Exception as e: print("点击事件出错:", e) class AnimatedTableDialog(QDialog): """表格弹窗""" def __init__(self, train_id, values, parent=None): super().__init__(parent) self.setWindowTitle(f"列车 {train_id} 的流程时间") self.resize(400, 300) layout = QVBoxLayout(self) title = QLabel(f"列车 {train_id} 的流程时间") title.setAlignment(Qt.AlignCenter) layout.addWidget(title) table = QTableWidget() table.setColumnCount(2) table.setHorizontalHeaderLabels(["流程", "时间(分钟)"]) table.setRowCount(len(values)) for i, (name, value) in enumerate(zip(process_names, values)): if name == "发车总时间": continue table.setItem(i, 0, QTableWidgetItem(name)) table.setItem(i, 1, QTableWidgetItem(str(value))) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) layout.addWidget(table) self.setLayout(layout)程序还是不完整啊,给我一个完整版,这个无法使用
08-30
import sys import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas from PySide6.QtWidgets import ( QApplication, QDialog, QVBoxLayout, QLabel, QComboBox, QTableWidget, QTableWidgetItem, QHeaderView, QPushButton, QHBoxLayout, QWidget ) from PySide6.QtCore import Qt # 示例流程名 process_names = [ "等送时间", "送车时间", "装车,等待取车", "取车时间", "列检作业,列车上线", "发车等待时间", "发车总时间" ] # 示例数据:车次 -> 流程时间数组 example_data = { "T101": [10, 20, 15, 25, 30, 10, 0], "T102": [12, 18, 14, 22, 32, 15, 0], "T103": [8, 22, 16, 24, 28, 12, 0], "T104": [9, 19, 17, 26, 31, 14, 0] } class ChartDialog(QDialog): """数据分析(折线图)弹窗""" def __init__(self, data=None, parent=None): super().__init__(parent) self.setWindowTitle("流程时间折线图") self.layout = QVBoxLayout(self) # 流程选择下拉框 self.process_combo = QComboBox() self.process_combo.addItems(process_names) self.process_combo.setCurrentIndex(0) self.layout.addWidget(QLabel("选择流程:")) self.layout.addWidget(self.process_combo) # 图表画布 self.figure = plt.figure(figsize=(10, 6)) self.canvas = FigureCanvas(self.figure) self.canvas.setParent(self) # <<< 必须调用 setParent self.layout.addWidget(self.canvas) # 绑定下拉框选择变化事件 self.process_combo.currentIndexChanged.connect(self.plot_selected) # 初始化数据 self.data = data if data else {} self.tooltip = None self.train_ids = [] self.x = [] self.y = [] self.line = None self.ax = None # 初始绘图 self.plot_selected() def plot_selected(self): selected_index = self.process_combo.currentIndex() selected_process = process_names[selected_index] # 清空图表 self.figure.clear() self.ax = self.figure.add_subplot(111) train_ids = sorted(self.data.keys()) x = list(range(len(train_ids))) if selected_process == "发车总时间": y = [sum(self.data[tid]) for tid in train_ids] avg_time = sum(y) / len(y) self.line, = self.ax.plot(x, y, marker='o', color='purple', linewidth=2, markersize=6, linestyle='-', zorder=2, label='发车总时间', picker=True, pickradius=5) self.ax.axhline(avg_time, linestyle='--', color='red', alpha=0.8, linewidth=1.5, zorder=1, label=f'平均总时间 ({avg_time:.1f} 分钟)') else: selected_index = process_names.index(selected_process) y = [self.data[tid][selected_index] for tid in train_ids] avg_time = sum(y) / len(y) self.line, = self.ax.plot(x, y, marker='o', color='blue', linewidth=2, markersize=6, linestyle='-', zorder=2, label='流程时间', picker=True, pickradius=5) self.ax.axhline(avg_time, linestyle='--', color='red', alpha=0.8, linewidth=1.5, zorder=1, label=f'平均时间 ({avg_time:.1f} 分钟)') # 设置图表样式 self.ax.set_title(f"列车{selected_process}组织时间采集折线图(分钟)") self.ax.xaxis.set_visible(False) # 去掉横坐标轴 yticks = self.ax.get_yticks() self.ax.yaxis.set_major_locator(plt.FixedLocator(yticks)) self.ax.yaxis.set_major_formatter(plt.FixedFormatter([f"{int(y)}" for y in yticks])) self.ax.grid(True, linestyle='--', alpha=0.5) self.ax.legend() # 保存变量 self.train_ids = train_ids self.x = x self.y = y # 解除旧的事件绑定(如果之前绑定过) if hasattr(self, 'motion_cid'): self.canvas.mpl_disconnect(self.motion_cid) if hasattr(self, 'click_cid'): self.canvas.mpl_disconnect(self.click_cid) if hasattr(self, 'pick_cid'): self.canvas.mpl_disconnect(self.pick_cid) # 重新绑定事件并保存连接ID self.motion_cid = self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move) self.click_cid = self.canvas.mpl_connect('button_press_event', self.on_click) self.pick_cid = self.canvas.mpl_connect('pick_event', self.on_pick) self.canvas.draw() def on_pick(self, event): """使用 pick_event 实现稳定的悬停提示""" if event.artist != self.line: return ind = event.ind[0] # 获取最接近的数据点索引 x = self.x[ind] y = self.y[ind] train_id = self.train_ids[ind] selected_process = process_names[self.process_combo.currentIndex()] if selected_process == "发车总时间": total = sum(self.data[train_id]) text = f"车次: {train_id}\n总时间: {total:.0f} 分钟" else: selected_index = process_names.index(selected_process) value = self.data[train_id][selected_index] total = sum(self.data[train_id]) text = f"车次: {train_id}\n时间: {value:.0f} 分钟\n总时间: {total:.0f} 分钟" # 移除旧的 tooltip if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = None # 创建新的 tooltip,并设置 animated=True self.tooltip = self.ax.annotate( text, xy=(x, y), xytext=(10, 10), textcoords="offset points", bbox=dict(boxstyle="round,pad=0.3", facecolor="white", edgecolor="black", alpha=0.9), zorder=1000, fontsize=10, arrowprops=dict(arrowstyle="->", relpos=(0, 0)), animated=True ) # 将 tooltip 添加到 axes 中 self.ax.draw_artist(self.tooltip) # 使用 blit 局部刷新画布 self.canvas.blit(self.ax.bbox) self.canvas.flush_events() def on_mouse_move(self, event): """原有 mouse move 逻辑保留,用于其他用途""" if not hasattr(self, 'ax') or event.inaxes != self.ax: if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = None self.canvas.draw_idle() return if self.line is None: return xdata = self.line.get_xdata() ydata = self.line.get_ydata() if len(xdata) == 0 or len(ydata) == 0: return distances = [(x - event.xdata) ** 2 + (y - event.ydata) ** 2 for x, y in zip(xdata, ydata)] min_index = np.argmin(distances) min_distance = distances[min_index] threshold = 0.5 if min_distance < threshold: x = xdata[min_index] y = ydata[min_index] train_id = self.train_ids[min_index] selected_process = process_names[self.process_combo.currentIndex()] if selected_process == "发车总时间": total = sum(self.data[train_id]) text = f"车次: {train_id}\n总时间: {total:.0f} 分钟" else: selected_index = process_names.index(selected_process) value = self.data[train_id][selected_index] total = sum(self.data[train_id]) text = f"车次: {train_id}\n时间: {value:.0f} 分钟\n总时间: {total:.0f} 分钟" if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = self.ax.annotate( text, xy=(x, y), xytext=(10, 10), textcoords="offset points", bbox=dict(boxstyle="round,pad=0.3", facecolor="white", edgecolor="black", alpha=0.9), zorder=1000, fontsize=10, arrowprops=dict(arrowstyle="->", relpos=(0, 0)), animated=True ) self.ax.draw_artist(self.tooltip) self.canvas.blit(self.ax.bbox) self.canvas.flush_events() else: if hasattr(self, 'tooltip') and self.tooltip: self.tooltip.remove() self.tooltip = None self.canvas.draw_idle() def on_click(self, event): if not hasattr(self, 'ax') or event.inaxes != self.ax: return try: xdata = self.line.get_xdata() ydata = self.line.get_ydata() distances = [(x - event.xdata) ** 2 + (y - event.ydata) ** 2 for x, y in zip(xdata, ydata)] min_index = np.argmin(distances) min_distance = distances[min_index] if min_distance < 0.1: train_id = self.train_ids[min_index] values = self.data[train_id] dialog = AnimatedTableDialog(train_id, values) dialog.exec() except Exception as e: print("点击事件出错:", e) class AnimatedTableDialog(QDialog): """表格弹窗""" def __init__(self, train_id, values, parent=None): super().__init__(parent) self.setWindowTitle(f"列车 {train_id} 的流程时间") self.resize(400, 300) layout = QVBoxLayout(self) title = QLabel(f"列车 {train_id} 的流程时间") title.setAlignment(Qt.AlignCenter) layout.addWidget(title) table = QTableWidget() table.setColumnCount(2) table.setHorizontalHeaderLabels(["流程", "时间(分钟)"]) table.setRowCount(len(values)) for i, (name, value) in enumerate(zip(process_names, values)): if name == "发车总时间": continue table.setItem(i, 0, QTableWidgetItem(name)) table.setItem(i, 1, QTableWidgetItem(str(value))) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) layout.addWidget(table) self.setLayout(layout) # 主程序入口 if __name__ == "__main__": app = QApplication(sys.argv) # 主窗口(用于打开 ChartDialog) class MainWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle("主窗口") self.resize(300, 200) layout = QVBoxLayout(self) self.btn = QPushButton("打开折线图") self.btn.clicked.connect(self.open_chart) layout.addWidget(self.btn) def open_chart(self): dialog = ChartDialog(example_data) dialog.exec() window = MainWindow() window.show() sys.exit(app.exec()) 帮我再修改一下 只使用pyside6,.0
08-30
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值