当前位置: 首页 > news >正文

Charts Factory 鼠标悬停显示数值信息实现详解

Charts Factory 鼠标悬停显示数值信息实现详解

charts_factory.py中,鼠标悬停显示数值信息的功能通过 PySide6 的信号槽机制和工具提示系统实现。以下是详细的实现原理和流程:

1. 核心实现机制

1.1 信号连接机制

在创建每种图表类型时,都会将图表系列的hovered信号连接到对应的处理函数:

# 折线图信号连接(line_chart.py:102)series.hovered.connect(self.on_line_hovered)# 柱状图信号连接(bar_chart.py:208) - 使用lambda传递额外参数bar_set.hovered.connect(lambdastatus,index,bs=bar_set:self.on_bar_hovered(status,index,bs))

1.2 事件处理函数

每种图表类型都有对应的悬停处理函数,这些函数负责:

  • 接收悬停事件参数
  • 解析数据信息
  • 生成格式化的工具提示
  • 控制工具提示的显示/隐藏

2. 具体实现流程

2.1 通用流程

  1. 信号触发:鼠标悬停在图表数据点上时,触发hovered信号
  2. 事件处理:对应的处理函数接收信号参数(不同图表类型参数不同)
  3. 数据解析:从参数中提取需要显示的数据(如坐标、数值、标签等)
  4. HTML生成:创建包含样式和数据的HTML工具提示内容
  5. 显示提示:使用QToolTip.showText()显示工具提示

2.2 不同图表类型的实现差异

折线图/曲线图/面积图
defon_line_hovered(self,point,state):ifstateandisinstance(point,QPointF):tooltip_html=f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">数据点</div> <div>X: <span style="color: #3498db;">{point.x():.1f}</span></div> <div>Y: <span style="color: #2ecc71;">{point.y():.1f}</span></div> </div> """QToolTip.showText(QCursor.pos(),tooltip_html,w=None,msecShowTime=3000)else:QToolTip.hideText()
  • 参数point(数据点坐标,QPointF类型)、state(悬停状态,布尔值)
  • 特点:直接显示X/Y坐标值,使用不同颜色区分X/Y值
柱状图
defon_bar_hovered(self,*args):iflen(args)==3:# Pattern: (status, index, barset) - from lambda connectionstatus,index,barset=argsifstatusandbarsetisnotNoneandindex>=0:tooltip_html=f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">{barset.label()}</div> <div>数值: <span style="color: #f39c12;">{barset.at(index)}</span></div> </div> """QToolTip.showText(QCursor.pos(),tooltip_html,w=None,msecShowTime=3000)else:QToolTip.hideText()
  • 参数status(悬停状态)、index(数据索引)、barset(柱状图数据集)
  • 特点:使用lambda函数传递额外的barset参数,显示数据集标签和具体数值
饼图
defon_pie_hovered(self,slice,state):ifstateandsliceisnotNone:tooltip_html=f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">{slice.label()}</div> <div>数值: <span style="color: #9b59b6;">{slice.value():.1f}</span></div> <div>百分比: <span style="color: #1abc9c;">{slice.percentage()*100:.1f}%</span></div> </div> """QToolTip.showText(QCursor.pos(),tooltip_html,w=None,msecShowTime=3000)slice.setExploded(True)# 饼图切片突出显示else:QToolTip.hideText()ifsliceisnotNone:slice.setExploded(False)
  • 参数slice(饼图切片对象)、state(悬停状态)
  • 特点:显示切片标签、数值和百分比,并实现切片突出显示效果

3. 技术特点

3.1 HTML样式的工具提示

  • 使用HTML和内联CSS创建美观的工具提示
  • 支持字体、颜色、布局等样式自定义
  • 不同类型的数据使用不同颜色区分,提高可读性

3.2 自适应不同图表类型

  • 针对不同图表类型的hovered信号参数差异,设计了不同的处理逻辑
  • 柱状图使用lambda函数解决参数传递问题
  • 饼图实现了额外的视觉反馈(切片突出)

3.3 性能优化

  • 仅在悬停状态有效时才生成和显示工具提示
  • 设置工具提示显示时间为3000毫秒,避免长时间占用屏幕
  • 鼠标离开时立即隐藏工具提示

4. 实现优势

  1. 代码复用:相似图表类型的悬停处理函数可以复用(如曲线图和面积图复用折线图的处理函数)
  2. 扩展性强:新增图表类型时,只需添加对应的悬停处理函数即可
  3. 用户体验好:美观的工具提示提供了清晰的数据信息,提升了交互体验
  4. 灵活性高:支持自定义工具提示的样式和内容

通过这种实现方式,Charts Factory 提供了一致且美观的鼠标悬停数据显示功能,增强了图表的交互性和可读性。

```python #!/usr/bin/env python3 """ Charts Factory Module Provides a factory for creating beautiful charts with consistent styling """ import sys import random from PySide6.QtWidgets import QWidget, QVBoxLayout, QToolTip from PySide6.QtCore import Qt, QPointF from PySide6.QtGui import QColor, QPen, QBrush, QFont, QLinearGradient, QPainter, QCursor from PySide6 import QtCharts class ChartsFactory: """ Factory class for creating consistent, beautifully styled charts """ # Default theme colors - Tech style THEME_COLORS = { "background": "#0A0E27", # Dark blue-black background "primary": "#00C8FF", # Bright cyan - main color "secondary": "#6B5B95", # Deep purple "accent1": "#2E8B57", # Dark green "accent2": "#50C878", # Medium green "accent3": "#1E3A8A", # Deep blue "grid": "#1E3A8A", # Dark blue grid lines "text": "#E0E0E0" # Light gray text for readability } # Default color palette for multiple series (e.g., bar charts) - Tech style COLOR_PALETTE = [ "#00C8FF", # Bright cyan - main color "#1E90FF", # Deep blue "#4169E1", # Royal blue "#6A5ACD", # Slate blue "#4B0082", # Indigo "#32CD32", # Lime green (accent) "#20B2AA", # Light sea green "#4682B4", # Steel blue "#708090", # Slate gray "#87CEFA" # Light sky blue ] def __init__(self): """Initialize the charts factory""" pass def create_chart_view(self, chart_type, data, title, **kwargs): """ Create a chart view based on the given type Args: chart_type (str): Type of chart ("line", "spline", "area", "bar", "pie", "scatter", "boxplot") data: Chart data title (str): Chart title **kwargs: Additional parameters Returns: QtCharts.QChartView: Configured chart view """ chart_type_map = { "line": self.create_line_chart, "spline": self.create_spline_chart, "area": self.create_area_chart, "bar": self.create_bar_chart, "horizontal_bar": self.create_horizontal_bar_chart, "pie": self.create_pie_chart, "scatter": self.create_scatter_chart, "boxplot": self.create_boxplot_chart } if chart_type not in chart_type_map: raise ValueError(f"Unsupported chart type: {chart_type}") return chart_type_map[chart_type](data, title, **kwargs) def create_line_chart(self, data, title, **kwargs): """Create a line chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create series series = QtCharts.QLineSeries() series.setName(kwargs.get("series_name", "Data")) # Set series style pen_color = QColor(kwargs.get("color", self.THEME_COLORS["primary"])) pen_width = kwargs.get("line_width", 2) series.setPen(QPen(pen_color, pen_width)) # Add data for x, y in data: series.append(x, y) # Add series to chart chart.addSeries(series) # Connect hovered signal series.hovered.connect(self.on_line_hovered) # Create and configure axes self._setup_axes(chart, series, **kwargs) # Create chart view return self._create_chart_view(chart) def create_spline_chart(self, data, title, **kwargs): """Create a spline chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create series series = QtCharts.QSplineSeries() series.setName(kwargs.get("series_name", "Data")) # Set series style pen_color = QColor(kwargs.get("color", self.THEME_COLORS["secondary"])) pen_width = kwargs.get("line_width", 2) series.setPen(QPen(pen_color, pen_width)) # Add data for x, y in data: series.append(x, y) # Add series to chart chart.addSeries(series) # Connect hovered signal series.hovered.connect(self.on_spline_hovered) # Create and configure axes self._setup_axes(chart, series, **kwargs) # Create chart view return self._create_chart_view(chart) def create_area_chart(self, data, title, **kwargs): """Create an area chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create line series for area boundaries line_series = QtCharts.QLineSeries() line_series.setName(kwargs.get("series_name", "Data")) # Add data for x, y in data: line_series.append(x, y) # Create area series with the line series and a base line area_series = QtCharts.QAreaSeries(line_series) # Set area style pen_color = QColor(kwargs.get("color", self.THEME_COLORS["primary"])) area_series.setPen(QPen(pen_color, 2)) # Create gradient fill gradient = QLinearGradient() gradient.setStart(0, 0) gradient.setFinalStop(0, 1) gradient.setColorAt(0, QColor(pen_color.red(), pen_color.green(), pen_color.blue(), 100)) gradient.setColorAt(1, QColor(pen_color.red(), pen_color.green(), pen_color.blue(), 0)) area_series.setBrush(gradient) # Add series to chart chart.addSeries(area_series) # Connect hovered signal area_series.hovered.connect(self.on_area_hovered) # Create and configure axes self._setup_axes(chart, area_series, **kwargs) # Create chart view return self._create_chart_view(chart) def create_bar_chart(self, data, title, **kwargs): """Create a vertical bar chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create bar series series = QtCharts.QBarSeries() # Create bar sets for i, (set_name, values) in enumerate(data.items()): bar_set = QtCharts.QBarSet(set_name) bar_set.append(values) # Set bar set style with different colors if "color" in kwargs: # User specified a single color for all bars pen_color = QColor(kwargs["color"]) else: # Use color from palette based on index pen_color = QColor(self.COLOR_PALETTE[i % len(self.COLOR_PALETTE)]) bar_set.setPen(QPen(pen_color)) bar_set.setBrush(QColor(pen_color)) # Connect hovered signal for this bar set using lambda to pass bar_set reference bar_set.hovered.connect(lambda status, index, bs=bar_set: self.on_bar_hovered(status, index, bs)) series.append(bar_set) # Add series to chart chart.addSeries(series) # Remove incorrect signal connection pass # Create and configure axes self._setup_axes(chart, series, **kwargs) # Create chart view return self._create_chart_view(chart) def create_horizontal_bar_chart(self, data, title, **kwargs): """Create a horizontal bar chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create bar series series = QtCharts.QHorizontalBarSeries() # Create bar sets for i, (set_name, values) in enumerate(data.items()): bar_set = QtCharts.QBarSet(set_name) bar_set.append(values) # Set bar set style with different colors if "color" in kwargs: # User specified a single color for all bars pen_color = QColor(kwargs["color"]) else: # Use color from palette based on index pen_color = QColor(self.COLOR_PALETTE[i % len(self.COLOR_PALETTE)]) bar_set.setPen(QPen(pen_color)) bar_set.setBrush(QColor(pen_color)) # Connect hovered signal for this bar set using lambda to pass bar_set reference bar_set.hovered.connect(lambda status, index, bs=bar_set: self.on_bar_hovered(status, index, bs)) series.append(bar_set) # Add series to chart chart.addSeries(series) # Create and configure axes (swapped for horizontal bar chart) kwargs["horizontal"] = True self._setup_axes(chart, series, **kwargs) # Create chart view return self._create_chart_view(chart) def create_pie_chart(self, data, title, **kwargs): """Create a pie chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create pie series series = QtCharts.QPieSeries() # Add data slices using the tech-style color palette for i, (label, value) in enumerate(data.items()): slice = series.append(label, value) slice_color = QColor(self.COLOR_PALETTE[i % len(self.COLOR_PALETTE)]) slice.setBrush(slice_color) slice.setPen(QPen(QColor(self.THEME_COLORS["background"]), 2)) slice.setLabelBrush(QColor(self.THEME_COLORS["text"])) # Make first slice exploded if requested if kwargs.get("explode_first", True) and i == 0: slice.setExploded(True) slice.setLabelVisible(True) # Connect hovered signal for the pie series series.hovered.connect(self.on_pie_hovered) # Add series to chart chart.addSeries(series) # Create chart view return self._create_chart_view(chart) def create_scatter_chart(self, data, title, **kwargs): """Create a scatter chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create scatter series series = QtCharts.QScatterSeries() series.setName(kwargs.get("series_name", "Data")) # Set scatter style pen_color = QColor(kwargs.get("color", self.THEME_COLORS["primary"])) series.setColor(pen_color) series.setMarkerSize(kwargs.get("marker_size", 8)) # Add data for x, y in data: series.append(x, y) # Add series to chart chart.addSeries(series) # Connect hovered signal series.hovered.connect(self.on_scatter_hovered) # Create and configure axes self._setup_axes(chart, series, **kwargs) # Create chart view return self._create_chart_view(chart) def create_boxplot_chart(self, data, title, **kwargs): """Create a box plot chart""" # Create chart chart = QtCharts.QChart() self._setup_chart(chart, title) # Create box plot series series = QtCharts.QBoxPlotSeries() series.setName(kwargs.get("series_name", "Data")) # Set box plot style pen_color = QColor(kwargs.get("color", self.THEME_COLORS["primary"])) series.setPen(QPen(pen_color, 1)) series.setBrush(QColor(pen_color.red(), pen_color.green(), pen_color.blue(), 100)) # Connect hovered signal for the box plot series series.hovered.connect(self.on_boxplot_hovered) # Add data for label, box_data in data.items(): # box_data should be [min, lower_quartile, median, upper_quartile, max] # Correct order: min, lower_quartile, median, upper_quartile, max box = QtCharts.QBoxSet(box_data[0], box_data[1], box_data[2], box_data[3], box_data[4], label) series.append(box) # Add series to chart chart.addSeries(series) # Create and configure axes self._setup_axes(chart, series, **kwargs) # Create chart view return self._create_chart_view(chart) def _setup_chart(self, chart, title): """Setup common chart properties""" # Set chart background chart.setBackgroundBrush(QColor(self.THEME_COLORS["background"])) # Set chart title chart.setTitle(title) chart.setTitleBrush(QColor(self.THEME_COLORS["text"])) # Set animation options chart.setAnimationOptions(QtCharts.QChart.SeriesAnimations) return chart def _setup_axes(self, chart, series, **kwargs): """Setup common axis properties""" horizontal_bar = kwargs.get("horizontal", False) # Create X and Y axes based on chart type if isinstance(series, (QtCharts.QBarSeries, QtCharts.QHorizontalBarSeries)): # Bar charts typically use category axes for one dimension if horizontal_bar: axis_x = QtCharts.QValueAxis() axis_y = QtCharts.QCategoryAxis() else: axis_x = QtCharts.QCategoryAxis() axis_y = QtCharts.QValueAxis() else: # Most charts use value axes axis_x = QtCharts.QValueAxis() axis_y = QtCharts.QValueAxis() # Configure X axis axis_x.setTitleText(kwargs.get("x_axis_title", "X Axis")) axis_x.setLabelFormat(kwargs.get("x_label_format", "%.0f")) axis_x.setTickCount(kwargs.get("x_tick_count", 11)) if "x_min" in kwargs and "x_max" in kwargs: axis_x.setRange(kwargs["x_min"], kwargs["x_max"]) # Configure Y axis axis_y.setTitleText(kwargs.get("y_axis_title", "Y Axis")) axis_y.setLabelFormat(kwargs.get("y_label_format", "%.0f")) axis_y.setTickCount(kwargs.get("y_tick_count", 11)) if "y_min" in kwargs and "y_max" in kwargs: axis_y.setRange(kwargs["y_min"], kwargs["y_max"]) # Apply styles to both axes for axis in [axis_x, axis_y]: # Set axis colors axis.setLabelsColor(QColor(self.THEME_COLORS["text"])) axis.setTitleBrush(QColor(self.THEME_COLORS["text"])) # Set grid line style grid_pen = QPen(QColor(self.THEME_COLORS["grid"]), 0.5) axis.setGridLinePen(grid_pen) # Set axis line style axis_pen = QPen(QColor(self.THEME_COLORS["text"]), 1.0) axis.setLinePen(axis_pen) # Add axes to chart if horizontal_bar: chart.addAxis(axis_x, Qt.AlignBottom) chart.addAxis(axis_y, Qt.AlignLeft) else: chart.addAxis(axis_x, Qt.AlignBottom) chart.addAxis(axis_y, Qt.AlignLeft) # Attach series to axes series.attachAxis(axis_x) series.attachAxis(axis_y) return axis_x, axis_y def _create_chart_view(self, chart): """Create a chart view with common settings""" chart_view = QtCharts.QChartView(chart) chart_view.setRenderHint(QPainter.Antialiasing) return chart_view def on_line_hovered(self, point, state): """折线图数据点悬停处理""" if state and isinstance(point, QPointF): tooltip_html = f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">数据点</div> <div>X: <span style="color: #3498db;">{point.x():.1f}</span></div> <div>Y: <span style="color: #2ecc71;">{point.y():.1f}</span></div> </div> """ QToolTip.showText( QCursor.pos(), tooltip_html, w=None, msecShowTime=3000 ) else: QToolTip.hideText() def on_spline_hovered(self, point, state): """曲线图表数据点悬停处理""" self.on_line_hovered(point, state) def on_area_hovered(self, point, state): """面积图表数据点悬停处理""" self.on_line_hovered(point, state) def on_bar_hovered(self, *args): """柱状图悬停处理""" # Handle different parameter patterns if len(args) == 3: # Pattern: (status, index, barset) - from lambda connection status, index, barset = args if status and barset is not None and index >= 0: tooltip_html = f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">{barset.label()}</div> <div>数值: <span style="color: #f39c12;">{barset.at(index)}</span></div> </div> """ QToolTip.showText( QCursor.pos(), tooltip_html, w=None, msecShowTime=3000 ) else: QToolTip.hideText() else: # Fallback if we don't recognize the pattern QToolTip.hideText() def on_pie_hovered(self, slice, state): """饼图悬停处理""" if state and slice is not None: tooltip_html = f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">{slice.label()}</div> <div>数值: <span style="color: #9b59b6;">{slice.value():.1f}</span></div> <div>百分比: <span style="color: #1abc9c;">{slice.percentage()*100:.1f}%</span></div> </div> """ QToolTip.showText( QCursor.pos(), tooltip_html, w=None, msecShowTime=3000 ) slice.setExploded(True) else: QToolTip.hideText() if slice is not None: slice.setExploded(False) def on_scatter_hovered(self, point, state): """散点图悬停处理""" if state and isinstance(point, QPointF): tooltip_html = f""" <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;"> <div style="font-weight: bold; margin-bottom: 4px;">数据点</div> <div>X: <span style="color: #3498db;">{point.x():.1f}</span></div> <div>Y: <span style="color: #e74c3c;">{point.y():.1f}</span></div> </div> """ QToolTip.showText( QCursor.pos(), tooltip_html, w=None, msecShowTime=3000 ) else: QToolTip.hideText() def on_boxplot_hovered(self, state, index, barset): """箱线图悬停处理""" if state and barset is not None and index >= 0: QToolTip.showText( QCursor.pos(), f"组: {barset.label()}", w=None, msecShowTime=3000 ) else: QToolTip.hideText() def create_chart_tab(self, chart_view, tab_name): """Create a tab with the chart view""" tab = QWidget() layout = QVBoxLayout(tab) layout.addWidget(chart_view) return tab # Example usage def main(): """Example demonstrating the charts factory""" from PySide6.QtWidgets import QApplication, QMainWindow, QTabWidget, QVBoxLayout, QWidget app = QApplication(sys.argv) # 设置QToolTip样式 app.setStyleSheet(""" QToolTip { background-color: #2c3e50; color: #ecf0f1; border: 1px solid #34495e; border-radius: 4px; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-size: 12px; padding: 8px; opacity: 0.9; } """) # Create main window window = QMainWindow() window.setWindowTitle("Charts Factory Demo") window.setGeometry(100, 100, 1000, 700) # Create central widget and layout central_widget = QWidget() main_layout = QVBoxLayout(central_widget) window.setCentralWidget(central_widget) # Create tab widget tab_widget = QTabWidget() main_layout.addWidget(tab_widget) # Create charts factory factory = ChartsFactory() # Create sample data line_data = [(x, random.randint(0, 100)) for x in range(20)] bar_data = {"Product A": [15, 20, 35, 25, 40], "Product B": [20, 25, 30, 35, 45]} pie_data = {"Company A": 35, "Company B": 25, "Company C": 20, "Company D": 15, "Others": 5} scatter_data = [(random.uniform(0, 100), random.uniform(0, 100)) for _ in range(50)] boxplot_data = { "Set 1": [10, 20, 30, 40, 50], "Set 2": [15, 25, 35, 45, 55], "Set 3": [5, 15, 25, 35, 45] } try: # Create charts one by one with proper error handling print("Creating charts...") # 创建简化的数据以减少资源消耗 simplified_line_data = line_data[:10] # 减少数据点数量 simplified_scatter_data = scatter_data[:20] # 减少散点数量 # 所有支持的图表类型 - 按照资源消耗从低到高排序 all_chart_types = [ ("line", simplified_line_data, "Line Chart"), ("bar", bar_data, "Bar Chart"), ("pie", pie_data, "Pie Chart"), ("scatter", simplified_scatter_data, "Scatter Chart") ] # 扩展图表类型列表,展示所有可用类型(根据系统资源自动调整) extended_chart_types = [ ("spline", simplified_line_data, "Spline Chart"), ("area", simplified_line_data, "Area Chart"), ("horizontal_bar", bar_data, "Horizontal Bar Chart"), ("boxplot", boxplot_data, "Box Plot Chart") ] # 创建图表类型示例 charts_created = 0 max_charts = 4 # 限制同时显示的图表数量以避免资源耗尽 print("=== 基本图表类型示例 ===") for chart_type, data, title in all_chart_types: if charts_created >= max_charts: break print(f"Creating {chart_type} chart...") try: chart_view = factory.create_chart_view(chart_type, data, title) tab = factory.create_chart_tab(chart_view, title) tab_widget.addTab(tab, title) charts_created += 1 print(f"✓ {title} created successfully") except Exception as e: print(f"✗ Error creating {title}: {e}") import traceback traceback.print_exc() # 如果还有资源,创建更多图表类型 print(f"\n=== 扩展图表类型示例 (已创建 {charts_created}/{max_charts} 个) ===") for chart_type, data, title in extended_chart_types: if charts_created >= max_charts: print(f"已达到最大图表数量 ({max_charts}),跳过 {title}") continue print(f"Creating {chart_type} chart...") try: chart_view = factory.create_chart_view(chart_type, data, title) tab = factory.create_chart_tab(chart_view, title) tab_widget.addTab(tab, title) charts_created += 1 print(f"✓ {title} created successfully") except Exception as e: print(f"✗ Error creating {title}: {e}") import traceback traceback.print_exc() print(f"\n共创建了 {charts_created} 个图表类型示例") # 在文档中列出所有可用的图表类型 print("\n=== 所有支持的图表类型 ===") all_supported_types = [ "line (折线图)", "spline (曲线图表)", "area (面积图表)", "bar (条形图)", "horizontal_bar (水平条形图)", "pie (饼图)", "scatter (散点图)", "boxplot (箱线图)" ] for i, chart_type in enumerate(all_supported_types, 1): print(f"{i}. {chart_type}") # Show window window.show() print("Application started successfully!") return app.exec() except Exception as e: print(f"Error: {e}") import traceback traceback.print_exc() return 1 if __name__ == "__main__": main()
http://www.jsqmd.com/news/263099/

相关文章:

  • 计算机小程序毕设实战-基于springboot+微信小程序的乐器宣传销售平台【完整源码+LW+部署说明+演示视频,全bao一条龙等】
  • 手机共享位置的技术原理解析
  • 2026年行业内有实力的升降机公司排名,登车桥/装卸平台/自行走升降平台/防爆升降机/防爆升降机,升降机供应厂家怎么选择 - 品牌推荐师
  • Windows文件传输命令大汇总
  • 甘肃万通汽修技工学校排名及优势解读 - 工业品牌热点
  • 【课程设计/毕业设计】基于微信小程序的乐器宣传平台基于springboot+微信小程序的乐器宣传平台【附源码、数据库、万字文档】
  • 进制转化入门 - 指南
  • 数据库备份的 10 分钟里,接了个 SQL 优化单:甲方给了执行计划,改 3 行代码,结款比备份还快
  • 基于深度学习的大地电磁反演方法研究
  • EtherCAT 主站3 - 指南
  • 承重型变形缝源头厂家哪家好?苏州昱安值得选择吗 - 工业品牌热点
  • ASPUPLOAD组件实现文件上传完整代码示例与应用详解
  • 基于sabl-cascade-rcnn_r101_fpn_1x_coco的葡萄成熟度检测项目_1
  • 【2026最新】Maven配置阿里云镜像
  • 2025年行业内品牌形象升级广告大型公司口碑排行,广告4A公司帕特广告引领行业标杆 - 品牌推荐师
  • Servlet生命周期全解析 - 教程
  • 2026年深圳技术好的ISO认证代理怎么选择,CE认证/3A信用等级认证/ISO45001,ISO认证代办哪家强 - 品牌推荐师
  • 承重型变形缝厂家哪家好,河南口碑较好的厂家有哪些 - 工业品牌热点
  • 软件工程Agent在工程依赖版本升级探索
  • 经典78M05 LDO经典应用电路
  • 博客园vscode使用
  • 机箱界的西装暴徒,能打的硬核小钢炮:机械大师C34 Pro装机实测
  • 活动回顾|Oracle 到 PostgreSQL 迁移技术网络研讨会 - 详解
  • 1.网络设备及网络通信问题
  • 穿搭技巧:让衣品瞬间提升一个档次,时髦又高级
  • 探讨苏州建筑变形缝资深厂商,昱安变形缝靠谱吗?质量与服务如何? - 工业品牌热点
  • 题解:P14976 [USACO25DEC] Photoshoot B
  • 深度测评!继续教育必用9个AI论文网站TOP9全解析
  • 2026年市场上靠谱的打包扣生产厂家排行榜,打包扣源头厂家甄选实力品牌 - 品牌推荐师
  • [Teanary] 因为 google 流量统计打不开了,新增了流量统计功能,这是开发文档,可以轻松扩展为数据洞查