【WPF.NET开发】路由事件

本文内容

  1. 先决条件
  2. 什么是路由事件?
  3. 路由策略
  4. 为什么使用路由事件?
  5. 附加并实现路由事件处理程序
  6. 类处理程序
  7. WPF 中的附加事件
  8. XAML 中的限定事件名称
  9. WPF 输入事件
  10. EventSetter 和 EventTrigger

Windows Presentation Foundation (WPF) 应用程序开发人员和组件创建者可以使用路由事件,通过元素树来传播事件,并在树中的多个侦听器上调用事件处理程序。 公共语言运行时 (CLR) 事件中没有这些功能。 有一些 WPF 事件是路由事件,例如 ButtonBase.Click。 本文介绍路由事件的基本概念,并对何时以及如何响应路由事件提供了指导。

1、先决条件

本文假定读者已基本了解公共语言运行时 (CLR)、面向对象的编程以及如何将WPF 元素布局
概念化为树。 若要理解本文中的示例,还应当熟悉 Extensible Application Markup Language (XAML) 并知道如何编写 WPF 应用程序

2、什么是路由事件?

可以从功能或实现的角度来理解路由事件:

  • 从功能角度来看,路由事件是一种可以针对元素树中的多个侦听器(而不是仅针对事件源)调用处理程序的事件。 事件侦听器是附加和调用了事件处理程序的元素。 事件源是最初引发事件的元素或对象。

  • 从实现的角度来看,路由事件是向 WPF 事件系统注册的事件,由 RoutedEvent 类的实例提供支持,并由 WPF 事件系统处理。 通常,路由事件是使用 CLR 事件“包装器”实现的,可以在 XAML 和代码隐藏中启用附加处理程序,就像你使用 CLR 事件一样。

WPF 应用程序通常包含许多元素,它们要么在 XAML 中声明,要么在代码中实例化。 应用程序的元素存在于其元素树中。 根据路由事件的定义方式,当事件在源元素上被引发时,它会:

  • 通过元素树从源元素浮升到根元素(通常是页面或窗口)。
  • 通过元素树从根元素到源元素向下进行隧道操作。
  • 不会遍历元素树,只发生在源元素上。

来看看下面的一部分元素树:

<Border Height="30" Width="200" BorderBrush="Gray" BorderThickness="1"><StackPanel Background="LightBlue" Orientation="Horizontal" Button.Click="YesNoCancelButton_Click"><Button Name="YesButton">Yes</Button><Button Name="NoButton">No</Button><Button Name="CancelButton">Cancel</Button></StackPanel>
</Border>

元素树的呈现的效果如下所示:

yes-no-cancel.png?view=netdesktop-8.0

这三个按钮中的每一个都是潜在的 Click 事件源。 单击其中一个按钮时,它会引发 Click 事件,从按钮浮升到根元素。 Button 和 Border 元素没有附加事件处理程序,但 StackPanel 有。 树中较高、未显示的其他元素可能也附加了 Click 事件处理程序。 当 Click 事件到达 StackPanel 元素时,WPF 事件系统将调用附加到它的 YesNoCancelButton_Click 处理程序。 示例中 Click 事件的事件路由为:Button>StackPanel>Border> 连续的父元素。

最初引发路由事件的元素在事件处理程序参数中被标识为 RoutedEventArgs.Source。 事件侦听器是附加和调用了事件处理程序的元素,它在事件处理程序参数中标识为 sender。

2.1 路由事件的顶层方案

下面介绍一些需运用路由事件概念的方案,并将其与典型的 CLR 事件进行区分:

  • 控件的撰写和封装:WPF 中的各个控件都有一个丰富的内容模型。 例如,可以将图像放在 Button 的内部,这会有效地扩展按钮的可视化树。 但是,添加的图像不能破坏按钮的命中测试行为,它需要在用户单击图像像素时做出响应。

  • 单一处理程序附加点:可以为每个按钮的 Click 事件注册一个处理程序,但通过路由事件,可以附加单个处理程序,如前面的 XAML 示例所示。 这样,你就可以更改单一处理程序下的元素树,例如添加或删除更多按钮,而无需注册每个按钮的 Click 事件。 引发 Click 事件时,处理程序逻辑可以确定事件来自何处。 在前面演示的 XAML 元素树中指定的以下处理程序包含该逻辑:

    private void YesNoCancelButton_Click(object sender, RoutedEventArgs e)
    {FrameworkElement sourceFrameworkElement = e.Source as FrameworkElement;switch (sourceFrameworkElement.Name){case "YesButton":// YesButton logic.break;case "NoButton":// NoButton logic.break;case "CancelButton":// CancelButton logic.break;}e.Handled = true;
    }
    
  • 类处理:路由事件支持在类中定义的
    类事件处理程序 。 类处理程序会在该类的任何实例上处理同一事件的任何实例处理程序之前处理事件。

  • 在没有反射的情况下引用事件:每个路由事件都会创建一个 RoutedEvent 字段标识符,从而提供一种不需要静态反射或运行时反射的可靠的事件标识技术来标识事件。

2.2 路由事件的实现方式

路由事件是向 WPF 事件系统注册的事件,由 RoutedEvent 类的实例提供支持,并由 WPF 事件系统处理。从注册获取的 RoutedEvent 实例通常存储为已注册的类的 public static readonly 成员。 该类称为事件“拥有者”类。 通常,路由事件会实现一个名称相同的 CLR 事件“包装器”。 CLR 事件包装器包含 add 和 remove 访问器,可以通过特定于语言的事件语法在 XAML 和代码隐藏中附加处理程序。 add 和 remove 访问器重写其 CLR 实现,并调用路由事件 AddHandler 和 RemoveHandler 方法。 路由事件的支持和连接机制在概念上与以下机制相似:依赖属性是一个 CLR 属性,该属性由 DependencyProperty 类提供支持并向 WPF 属性系统注册。

以下示例注册 Tap 路由事件,存储返回的 RoutedEvent 实例,并实现 CLR 事件包装器。

// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(name: "Tap",routingStrategy: RoutingStrategy.Bubble,handlerType: typeof(RoutedEventHandler),ownerType: typeof(CustomButton));// Provide CLR accessors for adding and removing an event handler.
public event RoutedEventHandler Tap
{add { AddHandler(TapEvent, value); }remove { RemoveHandler(TapEvent, value); }
}

3、路由策略

路由事件使用以下三种路由策略之一:


  • 浮升:最初,调用事件源上的事件处理程序。 路由事件随后会路由到后续的父级元素,依次调用其事件处理程序,直到到达元素树的根。 大多数路由事件都使用浮升路由策略。 浮升路由事件通常用于报告来自复合控件或其他 UI 元素的输入或状态变化。


  • 隧道:最初将调用元素树的根处的事件处理程序。 路由事件随后会路由到后续的子级元素,依次调用其事件处理程序,直到到达事件源。 遵循隧道路由的事件也称为
    预览事件。 WPF 输入事件通常是作为
    预览和浮升对实现的。


  • 直接:仅调用事件源上的事件处理程序。 这种非路由策略类似于 Windows 窗体 UI 框架事件,它是标准 CLR 事件。 与 CLR 事件不同,直接路由事件支持类处理
    ,可由 EventSetters 和 EventTriggers 使用。

4、为什么使用路由事件?

作为应用程序开发人员,你不需要始终了解或关注要处理的事件是否作为路由事件实现。 路由事件具有特殊的行为,但是,如果在引发该行为的元素上处理事件,则该行为通常会不可见。 但是,如果要将事件处理程序附加到父元素以处理子元素引发的事件(例如在复合控件中),路由事件就是有意义的。

路由事件侦听器不需要让它们处理的路由事件成为其类的成员。 任何 UIElement 或 ContentElement 可以是任一路由事件的事件侦听器。 由于可视元素派生自 UIElement 或 ContentElement,你可以将路由事件作为一个概念性的“接口”,支持在应用程序中的不同元素之间交换事件信息。 路由事件的这个“接口”概念特别适用于
输入事件。

路由事件支持在事件路由路线上的元素之间交换事件信息,因为每个侦听器都可以访问事件数据的同一实例。 如果事件数据中的某个元素更改了某些内容,则该更改对事件路由中的后续元素可见。

除了路由方面的原因,还有以下两个原因让你可能会选择实现路由事件而不是标准 CLR 事件:

  • 一些 WPF 样式和模板功能(如 EventSetters 和 EventTriggers)要求被引用的事件是路由事件。

  • 路由事件支持
    类事件处理程序,在侦听器类的任何实例上处理同一事件的任何实例处理程序之前处理事件。 此功能在控件设计中非常有用,因为类处理程序可以强制执行事件驱动的类行为,这些行为不能被实例处理程序意外地禁止。

5、附加并实现路由事件处理程序

在 XAML 中,通过将事件名称声明为事件侦听器元素上的属性,将事件处理程序附加到元素。 属性值是处理程序方法名称。 处理程序方法必须在 XAML 页的代码隐藏分部类中实现。 事件侦听器是附加和调用了事件处理程序的元素。

对于(通过继承或其他方式)成为侦听器类的成员的事件,可以按如下所示附加处理程序:

<Button Name="Button1" Click="Button_Click">Click me</Button>

如果事件不是侦听器类的成员,则必须以 <owner type>.<event name> 的形式使用限定的事件名称。 例如,由于 StackPanel 类不实现 Click 事件,若要将处理程序附加到浮升到该元素的 Click 事件的 StackPanel,需要使用限定的事件名称语法:

<StackPanel Name="StackPanel1" Button.Click="Button_Click"><Button>Click me</Button>
</StackPanel>

代码隐藏中事件处理程序方法的签名必须与路由事件的委托类型匹配。 Click 事件的 RoutedEventHandler 委托的 sender 参数指定事件处理程序附加到的元素。 RoutedEventHandler 委托的 args 参数包含事件数据。 Button_Click 事件处理程序的兼容代码隐藏实现可能是:

private void Button_Click(object sender, RoutedEventArgs e)
{// Click event logic.
}

尽管 RoutedEventHandler 是基本的路由事件处理程序委托,但某些控件或实现方案需要不同的委托来支持更专用的事件数据。 例如,对于 DragEnter 路由事件,处理程序应实现 DragEventHandler 委托。 通过执行此操作,处理程序代码可以访问事件数据中的 DragEventArgs.Data 属性,其中包含来自拖动操作的剪贴板有效负载。

用于添加路由事件处理程序的 XAML 语法与标准 CLR 事件处理程序的语法相同。

若要使用代码将路由事件的事件处理程序附加到元素,通常有两个选择:

  • 直接调用 AddHandler 方法。 始终可以通过这种方式附加路由事件处理程序。 下面的示例使用 AddHandler 方法将 Click 事件处理程序附加到按钮:

    Button1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
    

    将按钮的 Click 事件的处理程序附加到事件路由中的不同元素,例如名为 StackPanel1 的 StackPanel:

    StackPanel1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
    
  • 如果路由事件实现 CLR 事件包装器,请使用特定于语言的事件语法添加事件处理程序,就像对标准 CLR 事件的操作一样。 大多数现有的 WPF 路由事件实现 CLR 包装器,从而实现了特定于语言的事件语法。 此示例使用特定于语言的语法将 Click 事件处理程序附加到按钮:

    Button1.Click += Button_Click;
    

如果是使用 Visual Basic 编码,则还可以使用 Handles 关键字,将处理程序添加到处理程序声明中。 

“已处理”概念

所有路由事件都有一个共同的事件数据基类,即 RoutedEventArgs 类。 RoutedEventArgs 类定义布尔 Handled 属性。 Handled 属性的目的在于,允许事件路由线路中的任何事件处理程序将路由事件标记为“已处理”。 若要将事件标记为已处理,请在事件处理程序代码中将 Handled 的值设置为 true

Handled 的值会影响路由事件在沿事件路由传播过程中的处理方式。 如果在路由事件的共享事件数据中 Handled 为 true,则通常不会为该特定事件实例调用附加到事件路由中其他元素的处理程序。 在最常见的处理程序方案中,将事件标记为已处理,会有效地阻止事件路由中的后续处理程序(无论是实例处理程序还是类处理程序)响应该特定事件实例。 但是,在极少数情况下,需要事件处理程序来响应已标记为已处理的路由事件,可以执行以下操作:

  • 使用 AddHandler(RoutedEvent, Delegate, Boolean) 重载在代码隐藏中附加处理程序,将 handledEventsToo 参数设置为 true

  • 将 EventSetter 中的 HandledEventsToo 属性设置为 true

Handled 的概念可能会影响你对应用程序和的设计和对事件处理程序的编码。 可以将 Handled 概念化为用于处理路由事件的一个简单协议。 你如何使用此协议由你决定,但 Handled 参数的预期用法是:

  • 如果路由事件标记为“已处理”,则它不必由该路由中的其他元素再次处理。

  • 如果路由事件未标记为已处理,事件路由中较早的侦听器就没有该事件的处理程序,或者没有已注册的处理程序对该事件的响应可以证明将该事件标记为已处理。 当前侦听器上的处理程序有三个可能的操作过程:

    • 根本不执行任何操作。 该事件保持未处理状态,并路由到树中的下一个侦听器。

    • 运行代码以响应事件,但不能达到可证明将事件标记为已处理的程度。 该事件保持未处理状态,并路由到树中的下一个侦听器。

    • 运行代码以响应事件,并且达到可证明将事件标记为已处理的程度。 在事件数据中将事件标记为已处理。 事件仍路由到树中的下一个侦听器,但大多数侦听器将不会调用更多处理程序。 例外情况是具有专门注册的处理程序的侦听器,它们的 handledEventsToo 设置为 true

尽管只针对引发浮升路由事件的对象来处理该事件的开发人员可能不关心其他侦听器,但最好还是将事件标记为已处理。 这样做是为了防止事件路由路线上更远的元素在具有相同路由事件的处理程序时产生意想不到的副作用。

6、类处理程序

路由事件处理程序可以是实例处理程序或类处理程序。 给定类的类处理程序会在任何实例处理程序对该类的任何实例响应相同事件之前进行调用。 由于此行为,当路由事件标记为已处理时,它们通常会在类处理程序中标记为这样。 有两种类型的类处理程序:


  • 静态类事件处理程序,通过在静态类构造函数中调用 RegisterClassHandler 方法进行注册。

  • 重写类事件处理程序,通过重写基类虚拟事件方法进行注册。 基类虚拟事件方法的存在主要是用于输入事件,名称以 On<事件名称> 和 OnPreview<事件名称> 开头。

有些 WPF 控件对某些路由事件具有固有的类处理。 类处理可能看起来从未引发过路由事件,但实际上它被标记为由类处理程序处理。 如果需要事件处理程序来响应已处理的事件,可以注册处理程序,并将 handledEventsToo 设置为 true。 

7、WPF 中的附加事件

XAML 语言还定义了一个名为附加事件的特殊类型的事件。 附加事件可用于在非元素类中定义新的
路由事件,并在树中的任何元素上引发该事件。 为此,必须将附加事件注册为路由事件,并提供支持附加事件功能的特定
支持代码。 由于附加事件注册为路由事件,因此在元素上引发时,它们会通过元素树传播。

在 XAML 语法中,附加事件由其事件名称及其所有者类型指定,格式为 <owner type>.<event name>。 因为事件名称是使用具有其所有者类型的名称限定
的,所以语法允许将该事件附加到可以实例化的任何元素。 此语法也适用于附加到沿事件路由的任意元素的常规路由事件的处理程序。 还可以通过在处理程序应附加到的对象上调用 AddHandler 方法,在代码隐藏中为附加事件附加处理程序。

WPF 输入系统广泛使用附加事件。 但是,几乎所有附加事件都通过基本元素显示为等效的非附加路由事件。 你很少会直接使用或处理附加事件。 例如,与在 XAML 或代码隐藏中使用附加事件语法相比,通过等效 UIElement.MouseDown 路由事件处理 UIElement 上的基础附加 Mouse.MouseDown 事件更为容易。

8、XAML 中的限定事件名称

<owner type>.<event name> 语法使用其所有者类型的名称限定事件名称。 此语法允许将事件附加到任何元素,而不仅仅是将事件作为其类的成员实现的元素。 在 XAML 中为
附加事件或沿事件路由的任意元素上的路由事件附加处理程序时,该语法适用。 考虑一下这样的场景:你想要将处理程序附加到父元素,以便处理子元素上引发的路由事件。 如果父元素没有作为成员的路由事件,你将需要使用限定的事件名称语法。 例如:

<StackPanel Name="StackPanel1" Button.Click="Button_Click"><Button>Click me</Button>
</StackPanel>

在此示例中,向其添加事件处理程序的父元素侦听器是 StackPanel。 但是,Click 路由事件是在 ButtonBase 类上实现和引发的,并通过继承提供给 Button 类。 尽管 Button 类“拥有”Click 事件,但是路由事件系统允许将任何路由事件的处理程序附加到任何 UIElement 或 ContentElement 实例侦听器,否则就会有 CLR 事件的处理程序。 对于这些限定的事件属性名称来说,默认的 xmlns 命名空间通常是默认的 WPF xmlns 命名空间,但是还可以为自定义路由事件指定带有前缀的命名空间。 

9、WPF 输入事件

路由事件在 WPF 平台中的常见应用之一是用于
输入事件。 按照约定,遵循隧道路由的 WPF 路由事件的名称以“Preview”为前缀。 “Preview”前缀表示预览事件在配对浮升事件开始之前完成。 输入事件通常成对出现,一个是预览事件,另一个是浮升路由事件。 例如,PreviewKeyDown 和 KeyDown。 事件对共享相同的事件数据实例,对于 PreviewKeyDown 和 KeyDown,类型为 KeyEventArgs。 有时,输入事件只有浮升版本,或者只有直接路由版本。 在 API 文档中,路由事件主题交叉引用路由事件对,并阐明每个路由事件的路由策略。

实现成对出现的 WPF 输入事件,使来自输入设备的单个用户操作(如按鼠标按钮)按顺序引发预览和浮升路由事件。 首先引发预览事件并完成其路由。 预览事件完成后,将引发浮升事件并完成其路由。 引发浮升事件的实现类中的 RaiseEvent 方法调用将重复使用来自浮升事件的预览事件中的事件数据。

标记为已处理的预览输入事件不会为预览路由的其余部分调用任何正常注册的事件处理程序,并且不会引发配对的浮升事件。 对于希望在其控件的顶层报告基于命中测试的输入事件或基于焦点的输入事件的复合控件设计人员而言,此处理行为非常有用。 控件的顶级元素有机会对控件子组件中的预览事件进行类处理,以便用特定于控件的顶层事件“替换”它们。

为了说明输入事件处理的工作方式,请思考下面的输入事件示例。 在下面的树插图中,leaf element #2 是 PreviewMouseDown 和 MouseDown 配对事件的源:

input-event-routing.png?view=netdesktop-8.0

对叶元素 #2 执行鼠标按下操作后的事件处理顺序如下:

  1. 根元素上的 PreviewMouseDown 隧道事件。
  2. 中间元素 #1 上的 PreviewMouseDown 隧道事件。
  3. 叶元素 #2(源元素)上的 PreviewMouseDown 隧道事件。
  4. 叶元素 #2(源元素)上的 MouseDown 浮升事件。
  5. 中间元素 #1 上的 MouseDown 浮升事件。
  6. 根元素上的 MouseDown 浮升事件。

路由事件处理程序委托提供对以下两个对象的引用:引发该事件的对象以及在其中调用处理程序的对象。 最初引发了事件的对象由事件数据中的 Source 属性报告。 在其中调用处理程序的对象是由 sender 参数报告的对象。 对于任何给定的路由事件实例,引发事件的对象在事件通过元素树时不会更改,但 sender 会更改。 在上图的步骤 3 和 4 中,Source 和 sender 是同一对象。

如果输入事件处理程序完成了处理事件所需的特定于应用程序的逻辑,应将输入事件标记为已处理。 通常,一旦输入事件被标记为 Handled,就不会调用事件路由路线上的后续处理程序。 但是,即使事件标记为已处理,也会调用已注册且 handledEventsToo 参数设置为 true 的输入事件处理程序。 

预览和浮升事件对的概念(共享事件数据以及依次引发预览事件和浮升事件)仅适用于某些 WPF 输入事件,并不能适用于所有路由事件。 如果你要实现自己的输入事件来解决高级方案,请考虑遵循 WPF 输入事件对方法。

如果你要实现自己的可以响应输入事件的复合控件,请考虑使用预览事件来抑制子组件上引发的输入事件,并将其替换为表示完整控件的顶层事件。

10、EventSetter 和 EventTrigger

在标记样式中,可以使用 EventSetter 添加预声明的 XAML 事件处理语法。 在处理 XAML 时,所引用的处理程序会添加到带样式的实例中。 只能针对路由事件声明 EventSetter。 在下面的示例中,引用的 ApplyButtonStyle 事件处理程序方法在代码隐藏中实现。

<StackPanel><StackPanel.Resources><Style TargetType="{x:Type Button}"><EventSetter Event="Click" Handler="ApplyButtonStyle"/></Style></StackPanel.Resources><Button>Click me</Button><Button Click="Button_Click">Click me</Button>
</StackPanel>

Style 节点可能已包含与指定类型的控件相关的其他样式信息,并且使 EventSetter 成为这些样式的一部分可以提高代码的重用率,即使在标记级别也是如此。 此外,与常用的应用程序和页面标记相比,EventSetter 还提取处理程序的方法名称。

另一个将 WPF 的路由事件和动画功能结合在一起的专用语法是 EventTrigger。 与 EventSetter 一样,只能针对路由事件声明 EventTrigger。 通常将 EventTrigger 声明为样式的一部分,但是可以在页面级元素上将 EventTrigger 声明为 Triggers 集合的一部分,或者在 ControlTemplate 中对其进行声明。 使用 EventTrigger,可以指定当路由事件到达其路由中的某个元素(这个元素针对该事件声明了 EventTrigger)时将运行的 Storyboard。 与只是处理事件并且使其启动现有情节提要相比,EventTrigger 的优势在于,EventTrigger 可对情节提要及其运行时行为提供更好的控制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/226433.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FileZilla的使用主动模式与被动模式

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《产品经理如何画泳道图&流程图》 ⛺️ 越努力 &#xff0c;越幸运 目录 一、FileZilla简介 1、FileZilla是什么&#xff1f; 2、FileZilla的应用场景 二、FileZilla的安装 1、下…

【直播预告】刘军博士:科学研究中的AI计算:何助力团队协作创新

【直播预告】随着数据、算法、算力的融合发展&#xff0c;AI已经成为科学和工程研究的不可或缺的力量&#xff0c;涉足药物设计、天气预测、新材料研发等领域。在AI领域&#xff0c;协作是关键。欢迎大家关注12月28日20:00九章云极资深数据科学家刘军博士的直播&#xff01;刘军…

HLS 2017.4 导出 RTL 报错:ERROR: [IMPL 213-28] Failed to generate IP.

软件版本&#xff1a;HLS 2017.4 在使用 HLS 导出 RTL 的过程中产生如下错误&#xff1a; 参考 Xilinx 解决方案&#xff1a;https://support.xilinx.com/s/article/76960?languageen_US 问题描述 DESCRIPTION As of January 1st 2022, the export_ip command used by Vivad…

【计算机视觉】角点检测(Harris、SIFT)

Harris 角点指的是窗口延任意方向移动&#xff0c;都有很大变化量的点。 用数学公式表示为&#xff1a; E(u,v)反映的移动后窗口的差异&#xff0c;w(x,y)为每个像素的点权值&#xff0c;I(xu,yv)是移动的像素值&#xff0c;I(x,y)是移动前的像素值。 将E(u,v)进行泰勒展开&am…

MySQL进阶之(一)逻辑架构

一、逻辑架构 1.1 逻辑架构剖析1.1.1 连接层1.1.2 服务层01、基础服务组件02、SQL Interface&#xff1a;SQL 接口03、Parser&#xff1a;解析器04、Optimizer&#xff1a;查询优化器05、Caches & Buffers&#xff1a; 查询缓存组件 1.1.3 引擎层1.1.4 存储层1.1.5 总结 1.…

elasticsearch系列九:异地容灾-CCR跨集群复制

概述 起初只在部分业务中采用es存储数据&#xff0c;在主中心搭建了个集群&#xff0c;随着es在我们系统中的地位越来越重要&#xff0c;数据也越来越多&#xff0c;针对它的安全性问题也越发重要&#xff0c;那如何对es做异地容灾呢&#xff1f; 今天咱们就一起看下官方提供的…

25、商城系统(七):商城项目基础功能pom.xml(重要),mybatis分页插件

截止这一章,我们就不把重心放在前端,后台的基础代码,因为后面都是业务层面的crud。 前端直接替换这两个文件夹即可,后台代码也直接复制: 一、重新更新一下所有的pom.xml 这个地方我踩了好多坑,最后得到一个完整的pom.xml,建议大家直接用我的pom.xml替换即可。 1.comm…

大数据与人工智能|万物皆算法(第三节)

要点一&#xff1a;数据与智能的关系 1. 一切的核心都是数据&#xff0c;数据和智能之间是密切相关的。 数据是对客观现实的描述&#xff0c;而信息是数据转化而来的。 例如&#xff0c;24是数据&#xff0c;但说“今天的气温是24摄氏度”是信息&#xff0c;而说“班可以分成24…

How to Develop Word Embeddings in Python with Gensim

https://machinelearningmastery.com/develop-word-embeddings-python-gensim/ 本教程分为 6 个部分;他们是&#xff1a; 词嵌入 Gensim 库 开发 Word2Vec 嵌入 可视化单词嵌入 加载 Google 的 Word2Vec 嵌入 加载斯坦福大学的 GloVe 嵌入 词嵌入 单词嵌入是一种提供单词的…

web自动化(4)——POM设计重构

1. 什么是POM Page Object Model 是ui自动化测试中常见的封装方式。 原理&#xff1a;将页面封装为PO对象&#xff0c;然后通过面向对象的方式实现UI自动化 2. 封装原则 PO无需包含全部UI元素PO应当验证元素PO不应该包含断言PO不应该暴露元素 3. 怎么进行POM封装 面向对象…

IntelliJ IDE 插件开发 | (四)开发一个时间管理大师插件

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;开发一…

Flink1.17实战教程(第四篇:处理函数)

系列文章目录 Flink1.17实战教程&#xff08;第一篇&#xff1a;概念、部署、架构&#xff09; Flink1.17实战教程&#xff08;第二篇&#xff1a;DataStream API&#xff09; Flink1.17实战教程&#xff08;第三篇&#xff1a;时间和窗口&#xff09; Flink1.17实战教程&…

【51单片机系列】DS18B20温度传感器扩展实验之设计一个智能温控系统

本文是关于DS18B20温度传感器的一个扩展实验。 文章目录 一、相关元件介绍二、实验分析三、proteus原理图设计四、软件设计 本扩展实验实现的功能&#xff1a;利用DS18B20设计一个智能温度控制系统&#xff0c;具有温度上下限值设定。当温度高于上限值时&#xff0c;电机开启&a…

2023年12月28日学习记录

目录 1、今日计划学习内容2、今日学习内容文献阅读—A Data-driven Base Station Sleeping Strategy Based on Traffic Prediction0、选这篇文章的原因1、文章的主要内容和贡献2、使用的数据集3、结果及分析4、郭郭有话说 整理流量预测的代码 3、今日学习总结 1、今日计划学习内…

边缘智能网关在智慧大棚上的应用突破物联网大关

边缘智能网关在智慧大棚上的应用&#xff0c;是现代农业技术的一大突破。通过与农作物生长模型的结合&#xff0c;边缘智能网关可以根据实时的环境数据和历史数据&#xff0c;预测农作物的生长趋势和产量&#xff0c;提供决策支持和优化方案。这对于农民来说&#xff0c;不仅可…

Rosalind 033 Finding a Shared Spliced Motif

题目背景&#xff1a; 上述问题的解决方法是使用动态规划来找出两个DNA字符串的最长公共子序列&#xff08;LCS&#xff09;。 https://rosalind.info/problems/lcsq/ 很经典的动态规划问题了。直接给出解题步骤&#xff1a; 1. 初始化矩阵&#xff1a;创建一个大小为 (len…

Qt的简单游戏实现提供完整代码

文章目录 1 项目简介2 项目基本配置2.1 创建项目2.2 添加资源 3 主场景3.1 设置游戏主场景配置3.2 设置背景图片3.3 创建开始按钮3.4 开始按钮跳跃特效实现3.5 创建选择关卡场景3.6 点击开始按钮进入选择关卡场景 4 选择关卡场景4.1场景基本设置4.2 背景设置4.3 创建返回按钮4.…

[react]脚手架create-react-app/vite与reac项目

[react]脚手架create-react-app/vite与reac项目 环境问题描述create-react-app 脚手架根据脚手架修改项目结构安装脚手架注入配置文件-config文件夹package.json文件变更删除 serviceWorker.js新增reportWebVitals.js文件更新index.js文件 脚手架creat-react-app 缺点 vite 脚手…

助力城市部件[标石/电杆/光交箱/人井]精细化管理,基于YOLOv6开发构建生活场景下城市部件检测识别系统

井盖、店杆、光交箱、通信箱、标石等为城市中常见部件&#xff0c;在方便居民生活的同时&#xff0c;因为后期维护的不及时往往会出现一些“井盖吃人”、“线杆、电杆、线缆伤人”事件。造成这类问题的原因是客观的多方面的&#xff0c;这也是城市化进程不断发展进步的过程中难…

垃圾收集器与内存分配策略

内存分配和回收原则 对象优先在Eden区分配 大对象直接进入老年代 长期存活的对象进入老年代 什么是内存泄漏 不再使用的对象在系统中未被回收&#xff0c;内存泄漏的积累可能会导致内存溢出 自动垃圾回收与手动垃圾回收 自动垃圾回收&#xff1a;由虚拟机来自动回收对象…