jQuery源码分析之jQuery.event.add和jQuery.event.dispatch十一问

提前阅读handles相关知识 正则表达式相关知识 jQuery.event.fix相关知识

问题1:jQuery.event.add有那些调用方式?

自定义事件click._submit keypress._submi:

	jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
				// Node name check avoids a VML-related crash in IE (#9807)
				     var elem = e.target,
					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
					jQuery.event.add( form, "submit._submit", function( event ) {
						event._submit_bubble = true;
					});
					jQuery._data( form, "submitBubbles", true );
				}
			});
自定义事件submit._submit:

jQuery.event.add( form, "submit._submit", function( event ) {
	event._submit_bubble = true;
			});
propertychange_change事件

jQuery.event.add( this, "propertychange._change", function( event ) {
						if ( event.originalEvent.propertyName === "checked" ) {
							this._just_changed = true;
						}
					});
click_change事件:

jQuery.event.add( this, "click._change", function( event ) {
						if ( this._just_changed && !event.isTrigger ) {
							this._just_changed = false;
						}
						// Allow triggered, simulated change events (#11500)
						jQuery.event.simulate( "change", this, event, true );
					});
beforeactive._change和change_changeg

jQuery.event.add( this, "beforeactivate._change", function( e ) {
				var elem = e.target;
				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
					jQuery.event.add( elem, "change._change", function( event ) {
						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
							jQuery.event.simulate( "change", this.parentNode, event, true );
						}
					});
					jQuery._data( elem, "changeBubbles", true );
				}
			});
问题2:我们添加的自定义事件步骤是什么?

第一步:获取该DOM本身用于保存数据的仓库,如果仓库获取失败(如传入的不是DOM或者JS对象那么直接返回,返回是undefined),那么无法添加事件直接返回

          elemData = jQuery._data( elem );
		// Don't attach events to noData or text/comment nodes (but allow plain objects)
		if ( !elemData ) {
			return;
		}
第二步:既然是添加事件,那么我们回调函数必须有一个独一无二的guid值

// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
			selector = handleObjIn.selector;
		}
         //为回调函数添加一个唯一的guid值
		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}
第三步:事件是添加在events域里面的,所以要组件events域

         //没有events域那么手动添加
		// Init the element's event structure and main handler, if this is the first
		if ( !(events = elemData.events) ) {
			events = elemData.events = {};
		}
第三步:上面的仓库里面还缺少一个执行所有回调事件的通用回调函数,那么我们添加。 但是添加了一个通用回调函数必须指定该通用回调函数由谁维护的!

           //如果没有handle通用回调函数则添加
		if ( !(eventHandle = elemData.handle) ) {//为DOM第二次添加回调时候不会多次添加通用回调函数,因为该DOM通用回调函数已经添加!
			eventHandle = elemData.handle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;//指定该通用回调函数所有者为当前DOM,如果下次再次为该DOM添加回调,那么不会再次添加回调函数
		}
第四步:获取我们需要添加的事件类型,多个类型之间用空格隔开

	types = ( types || "" ).match( rnotwhite ) || [ "" ];
		t = types.length;//可以添加多个类型
第五步:获取每一个事件类型的所有的参数,如类型名称,空间名称等,并构建一个独立的handleObj对象,同时把handleObj添加到特定类型事件的回调函数数组中,如果是click那么添加到click事件对应的回调数组中,如果是mouseover就添加到mouseover对应的回调数组中,每一个事件类型都有一个回调数组

                       while ( t-- ) {
			tmp = rtypenamespace.exec( types[t] ) || [];
			type = origType = tmp[1];
			namespaces = ( tmp[2] || "" ).split( "." ).sort();//排序,所以click.text1.text=click.text.text1!
			// There *must* be a type, no attaching namespace-only handlers
			if ( !type ) {
				continue;
			}
                      //看是否是特殊类型,如change_changeg,click_change等!
			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};
                        //如果含有selector表示当前DOM代理了满足selector的所有的同类的事件,那么获取delegateType!
			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;
                      //如果代理了就是获取代理的类型
			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};
			// handleObj is passed to all event handlers
			handleObj = jQuery.extend({//构建每一个事件独一无二的handleObj对象
				type: type,
				origType: origType,
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
				namespace: namespaces.join(".")
			}, handleObjIn );
                  //如果带DOM对象的events域里面没有同类的事件,那么添加这个事件的一个回调数组!
			// Init the event handler queue if we're the first
			if ( !(handlers = events[ type ]) ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;
				//添加事件的时候,如果没有setup或者setup调用后返回是false,那么用addEventListener或者attachEvent来添加!
				// Only use addEventListener/attachEvent if the special events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );
					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}
                     //如果special有add方法那么调用add方法!
			if ( special.add ) {
				special.add.call( elem, handleObj );
				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}
                   //插入handleObj对象,这是插入特定的事件处理的回调数组中handlers
			// Add to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}
                   //把global设置为true!
			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
		}
下面我们把第五步部分内容仔细分析一下:

              if ( !(handlers = events[ type ]) ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;
				//添加事件的时候,如果没有setup或者setup调用后返回是false,那么用addEventListener或者attachEvent来添加!
				// Only use addEventListener/attachEvent if the special events handler returns false
				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );
					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}
note:从这里我们看到,每一个事件类型都对应的一个回调数组!但是为该DOM指定回调函数的时候首先是当作特殊类型来处理的,如果特殊类型无法处理,那么我们通过addEventListener或者attachEvent来绑定事件, 不过绑定的回调函数就是上面的通用函数,所以如果事件触发,那么执行的将会是通用的函数!所以说, 本质还是JS原生的事件绑定的内容!
如果这种特殊类型有add方法,那么我们还是需要调用add方法,同时如果通用函数没有guid我们把guid值设置为我们上面传入的回调函数的guid值

                    if ( special.add ) {
				special.add.call( elem, handleObj );
				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;//把通用函数的guid值设置为我们自己回调的guid值,该值在前面已经定义!
				}
			}
如果含有selector,那么表示当前对象是代理的,那么我们该DOM的delegateCount自增

       if ( selector ) {
		     handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}
                //把global设置为true!
			// Keep track of which events have ever been used, for event optimization
			jQuery.event.global[ type ] = true;
下面是时候看看他们的数据保存格式了,首先我们看看handleObj有那些内容,JS部分:

jQuery.event.add($("#father")[0],"qinliang",function()
	{
	  console.log("qinliang invoked!");
	});
通过 该图,你应该知道handleObj中的data就是绑定事件时候传入的数据,而handler就是我们绑定事件时候指定的回调函数(不是通用回调函数),selector用于判断是否进行了代理;type和origType都是事件类型;guid值就是我们为该函数分配的一个全局的标记。

问题3:handleObj的数据格式我知道了,那么这个handleObj是如何和我们绑定事件的DOM联系起来的?

jQuery.event.add($("#father")[0],"qinliang",function(e)//JS部分
	{
	  console.log("qinliang invoked!");
	});
	var expando=jQuery.expando;
	var key=$("#father")[0][expando];
	var data=jQuery.cache[key];
	console.log(data);
通过 博客,你会知道这是用钥匙开门的过程。我们来看看绑定在该DOM上面的数据是什么。通过 该图,你必须知道,我们为该DOM的仓库开辟了一个events域,用来处理各种事件类型, 每一种事件类型都是一个数组,数组中存放的是上面的handleObj对象。同时,你必须知道,该DOM中绑定的handle域是一个通用的回调函数,而不是我们自定义的回调函数,同时该通用回调函数的elem属性中持有div#father这个DOM元素的引用!那么,你可能会问,什么时候把这个通用回调函数绑定上去了?

                   if ( !(eventHandle = elemData.handle) ) {
			eventHandle = elemData.handle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}
上面已经说过, 每一个元素的仓库都会添加一个handle域,用于处理所有的回调函数,而且这个回调函数只会在DOM上添加一次,而且这个回调函数本身也存在着对该DOM的引用!
问题4:那么我们添加了这个函数,具体执行过程是怎么样的呢?

if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );
					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
从这里我们可以看出,我们采用了JS通用的事件绑定方式来完成,那么当我们通过trigger(自定义事件可能不是通过用户行为来操控的)来触发事件的时候,这个DOM就能够接受到事件触发的行为,最终调用我们通用的回调函数eventHandle。

if ( !(eventHandle = elemData.handle) ) {
			eventHandle = elemData.handle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}
在我们通用的函数中,会调用 jQuery.event.dispatch方法, 上下文为该通用函数的所有者,参数就是调用时候传入的参数!
问题5:源码中那些方法调用了jQuery.event.add方法?

解答:最重要的就是实例on方法

return this.each( function() {
			jQuery.event.add( this, types, fn, data, selector );
		});
所以,经过on方法,我们就可以把所有的元素都绑定事件处理函数了!见下例

$("#father").on("click","#child",{name:"qinliang"},function(e)
	{
	  console.log("1");//回调函数中参数是什么?
	});
	var expando=jQuery.expando;
	var key=$("#father")[0][expando];
	//注意:这里是进行了事件代理,所有事件回调都在father元素上面,而不在child上!
	var data=jQuery.cache[key];
	console.log(data);
我还想强调一下 该图事件处理函数click对应于一个回调函数数组,数组中存放的是handleObj对象;handleObj的对象中selector对应于代理的子元素的选择器,data就是我们传入的数据,handle就是我们传入的回调函数而不是通用的回调函数!因为这里father是代理了child的click事件,所以delegateCount就是1!

问题6:那么我们自己的函数真正调用的时候的上下文以及参数是什么?

解答:

var data = { id: 5, name: "张三" };  
     $("body").on("click.test.me1 mouseover.test.me2","#n5",data,function(e){alert(this.id+"我在测试add方法!"+e.data.name+e.delegateTarget.tagName+e.handleObj.selector)});  

 回调函数中this指向当前元素!,也就是currentTarget。apply( matched.elem, args )是在dispatch里面的源码,但是因为这里用的是apply而不是call,所以直接把args逐个封装到回调函数中。这个args只有一个参数args[0]=event所以这里回调函数中唯一一个参数就是event,同时可以通过event.data获取数据,通过delegateTarget获取代理对象BODY。通过handleObj可以获取通过add方法添加的事件的所有信息,也就是通过add方法里面添加的handleObj所有属性!同时可以通过currentTarget获取当前所在的元素! 
总之一句话:在该回调函数中可以获取这个调用事件的所有的信息! 

问题7:我们回调jQuery.event.dispatch把,我们知道jQuery.event.add中绑定事件是通过addEventListener等常规方法的,所以当我们触发了这个事件的时候会传入event对象,同时上下文是该通用回调函数的所有者,也就是代理对象,那么该方法是如何调用函数的呢?

第一步:修正我们的event对象

event = jQuery.event.fix( event );
第二步:既然是调用事件,那么肯定是某一类事件了,那么我们要获取仓库里面的该类事件的所有handleObj对象了

                      args = slice.call( arguments ),
				//获取该DOM的events域下面保存的所有的事件的集合!
			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
				//看事件是否是特殊事件
			special = jQuery.event.special[ event.type ] || {};
		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		   //获取event对象!
		   args[0] = event;
		//代理对象就是上下文对象,如果不是代理this就是调用对象的DOM对象!
		event.delegateTarget = this;
		// Call the preDispatch hook for the mapped type, and let it bail if desired
		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
			return;
		}
之所以jQuery.event.dispatch中的上下文是代理对象,这是因为我们在添加事件的时候决定的,也就是这个通用函数决定的

if ( !(eventHandle = elemData.handle) ) {
			eventHandle = elemData.handle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) ://上下文是代理对象!
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}
第三步:既然代理对象的事件调用了,那么回调函数中时候需要知道当前事件流到那里了呢,看看事件流把

    handlerQueue = jQuery.event.handlers.call( this, event, handlers );//获取当前事件流在那里,包括当前所在的DOM等,以及当前DOM应该回调的handleObj集合!
第四步:把 jQuery.event.handlers所有的返回事件流信息用于函数回调, 不过这里不再回调通用函数,而是自己定义的回调函数!

    while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
			event.currentTarget = matched.elem;//当前事件流到那里了
			j = 0;
			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
				//遍历当前DOM的满足的handleObj,以便回调!
				// Triggered event must either 1) have no namespace, or
				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
		
			//如果event对象没有namespace_re属性,或者handleObj的namespace满足namespace_re正则表达式!
				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
					event.handleObj = handleObj;
					event.data = handleObj.data;
                    //经过上两步,该event对象具有了handleObj和data属性,handleObj具有该事件的所有的信息,本来data也有
					//但是这里把data也单独封装到event上
					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );
                     //真正开始执行我们自己的函数了(handleObj.handler),而不再是通用函数了!上下文是当前事件流的所在的DOM元素!
					 //参数是event,但是该event具有data保存了数据,具有handleObj保存了该事件所有的信息!
					if ( ret !== undefined ) {
						if ( (event.result = ret) === false ) {
							event.preventDefault();
							event.stopPropagation();
						}
					}
				}
			}
我们仔细分析一下这里的代码:

这里是什么鬼?

if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) )
如果通过jQuery.event.trigger来调用,那么event对象会具有namespace_re属性,因为通过 jQuery.event.trigger来调用的时候可以指定命名空间,click.text.text1和click.text1.text是相同的,因为内部是经过sort了。 所以,如果不是通过trigger来调用的话是没有namespace_re属性的!
问题8:我们自己指定的回调函数中的上下文以及参数是什么?

ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ).apply( matched.elem, args );
通过这里你就知道了,我们自己的函数中上下文就是当前事件流所在的DOM元素,而参数只有event对象,但是该event对象具有currentTarget,handleObj以及data属性,也就是说他具有了该事件所有的信息。举例:

<div id="parent">  
    <div id="child1" style="width:50px;height:50px;border:1px solid red;">child1</div>  
    <div id="child2" style="width:50px;height:50px;border:1px solid red;margin-top:10px;">child2</div>  
</div>  
JS部分

$("body").on("click","#child2",function(e){console.log(this);});//this指代child2元素!
$("body").on("click","#parent",function(e){console.log(this)});//this指代parent元素  
这时候你就会明白:虽然child2和parent的点击事件都是被body代理的,但是点击child2的时候,jQuery去查找body的click对应的handleObj数组一看,哇 抓狂,这个child2满足我click中handleObj数组中的一个handleObj的选择器啊(通过jQuery.event.handlers发现的),于是他就触发了,给他一个上下文为自己,也就是child2元素,当然this也可以通过event.currentTarget来代替。 其它所有关于该事件的参数除了data可以通过e.data访问以外,都需要通过event.handleObj.x访问!
当事件流到了father的时候,jQuery一看,我靠,又满足body的关于click的handleObj数组的一个handleObj的选择器,于是他又触发了,这次的this是father元素,其它内容的访问和上面的方式一样! ( 之所以会查看body的click的handleObj数组还是由于事件冒泡了
问题9:子元素的事件被触发了以后,父元素也必须触发?

解答:不是。我们看看源码中的这一部分就知道如何处理了

if ( ret !== undefined ) {
			if ( (event.result = ret) === false ) {//只要返回函数返回false就能防止冒泡了!
				event.preventDefault();
				event.stopPropagation();
			}
}
他告诉我们,如果不想父元素触发,就必须阻止冒泡,只要return false就可以了
 $("body").on("click","#child2",function(e){console.log(this);return false;});//this指代child2元素!
   $("body").on("click","#parent",function(e){console.log(this)});//this指代parent元素  
这时候父元素的click事件不会被调用!
问题10:一般我们都有currentTarget,target,但是这里有了delegateTarget?

解答:delegateTarget是jQuery指定的,表示代理对象

<div id="parent">  
    <div id="child1" style="width:50px;height:50px;border:1px solid red;">child1</div>  
    <div id="child2" style="width:50px;height:50px;border:1px solid red;margin-top:10px;">child2</div>  
</div>  
点击child2元素:

$("body").on("click","#child2",function(e){
     console.log(e.target);//child2
     console.log(e.currentTarget);//child2
     console.log(e.delegateTarget);//body元素
  });
target就是触发事件的元素;currentTarget表示事件处理函数当前所在的元素,是一个动态的过程;delegateTarget是代理对象,是不变的!
我们看看currentTarget和target不同的情况

 $("body").on("click","#parent",function(e){
     console.log(e.target);//child2
     console.log(e.currentTarget);//parent
     console.log(e.delegateTarget);//body元素
  });
这时候currentTarget就是父元素了,而target还是子元素,delegateTarget还是body!t arget表示事件的真实触发处,currentTarget一般是事件被处理的地方
问题11:上面这种冒泡是否可以取消父元素的绑定的事件,而不仅仅是取消父元素的代理事件?

解答:可以

 $("body").on("click","#child2",function(e){
     console.log("child2");
  });
  $("body").click(function()
  {
    console.log("body");
  });
这时候点击child2两者都会被调用
  $("body").on("click","#child2",function(e){
     console.log("child2");
	 return false;
  });
  $("body").click(function()
  {
    console.log("body");
  });
这种情况下就可以防止事件冒泡到父元素上面,因为return false了!

下面给出一种jQuery自定义事件触发的方式:

HTML部分

<div id="parent">  
    <div id="child" style="width:50px;height:50px;border:1px solid red;margin-top:10px;">child2</div>  
</div>  
JS部分

jQuery.event.add($("#child")[0],"qinliang",function(e)//绑定qinliang事件
   {
     console.log("child");
   });
   var expando=jQuery.expando;
   var key=$("#child")[0][expando];
   var walhouse=jQuery.cache;
   var data=walhouse[key];
   console.log(data);//仓库里面的数据
   var event1=new jQuery.Event("qinliang")
   jQuery.event.dispatch.call($("#child")[0],event1);
这时候你会发现,我绑定的qinliang事件被触发了!

 如果要深入jQuery.event学习请参考  

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java中的"java.awt.eventdispatchthread"是一个线程,它负责处理用户界面组件上的事件,如按钮点击、文本框更新等。这个线程是单独的,主要是为了避免在处理事件时阻塞主线程,从而让用户界面变得更加流畅。 ### 回答2: Java.awt.eventdispatchthread是一个Java AWT(Abstract Window Toolkit)中的线程类,用于处理和分发事件。它是AWT事件模型的核心部分,负责接收和分发用户输入的事件。 Java.awt.eventdispatchthread负责管理用户交互产生的各种事件,包括鼠标点击、键盘敲击、窗口操作等。当用户触发这些事件时,事件首先被底层操作系统捕获,然后传递给Java.awt.eventdispatchthread进行处理。 Java.awt.eventdispatchthread是单线程的,它采用事件队列(Event Queue)的方式处理事件。当一个事件发生时,它会将该事件加入到事件队列中。然后按照事件的先后顺序,逐个处理队列中的事件。这种方式保证了事件的顺序一致性,避免了多个事件同时处理的题。 除了事件的分发以外,Java.awt.eventdispatchthread还负责调用事件监听器(Event Listener)。事件监听器是在应用程序中定义的,用于响应特定事件的回调函数。当事件被分发到监听器时,Java.awt.eventdispatchthread会调用监听器中定义的方法进行逻辑处理。 Java.awt.eventdispatchthread的工作原理如下: 1. 事件被捕获并传递给Java.awt.eventdispatchthread。 2. Java.awt.eventdispatchthread将事件加入到事件队列中。 3. 依次处理事件队列中的事件。 4. 根据事件类型找到相应的事件监听器。 5. 调用监听器中定义的方法进行事件处理。 总之,Java.awt.eventdispatchthread是Java AWT中的关键线程类,负责接收、管理和分发用户输入的各种事件。它使用事件队列的方式保证事件的有序处理,并调用相应的事件监听器进行逻辑处理。 ### 回答3: Java AWT EventDispatchThread(事件调度线程)是Java AWT(图形用户界面)库中的一个线程,它的主要作用是接收、处理和分发所有的AWT事件。它是一个单线程,用于处理UI事件和操作。 Java AWT EventDispatchThread是一种特殊的线程,它负责处理用户界面事件的顺序和同步。当用户与界面进行交互,比如点击按钮、输入文本等操作时,这些操作都会被封装为AWT事件,并由EventDispatchThread按照先后顺序进行处理。 EventDispatchThread的作用主要有以下几个方面: 1. 事件的分发:当用户触发了某个事件,EventDispatchThread负责将该事件分发给对应的组件进行处理。这样可以保证事件被按照正确的顺序执行,防止事件处理出现混乱的情况。 2. 事件的处理:EventDispatchThread负责将事件发送到目标组件,并调用相应的事件处理方法。例如,当用户点击按钮时,EventDispatchThread会调用按钮的actionPerformed方法来处理点击事件。 3. 界面的刷新:EventDispatchThread负责处理界面的刷新操作。当某个组件的状态发生变化时,EventDispatchThread会负责重新绘制该组件,以保持界面的一致性。 综上所述,Java AWT EventDispatchThread是一个专门负责处理UI事件和操作的线程。它负责接收、处理和分发所有的AWT事件,保证事件的顺序和同步性,确保界面的正确响应和刷新。因此,了解和理解EventDispatchThread的工作原理对于开发Java AWT应用程序是非常重要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值