qtdemo浅析


    [size=x-small;]? ? <span>之所以写这篇文章,是因为之前做了一些关于修改[/size]<span lang="EN-US">QtDemo</span><span>的工作,而且之前的备忘里承诺过,虽然不一定很多人记得或者看过,但说到就要做到,哪怕说给自己听的事情。</span></span>

?

[size=x-small;]
[/size]


<p class="MsoNormal"><span lang="EN-US">[size=x-small;]?[/size]</span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]?[/size]</span>

<p class="MsoNormal">[size=x-small;]<span lang="EN-US">C:\Qt\4.5.0\demos\qtdemo [/size]<span>如果你已经配置了</span><span lang="EN-US">QT </span><span>,那么在</span><span lang="EN-US">QT
Assistant</span><span>下面就有</span><span lang="EN-US">qtdemo</span><span>的可执行文件,就可以看看效果了。</span></span>

<p class="MsoNormal">[size=x-small;]<span>? ?现在简单的说明下源码的文件分类和基本作用,由于每个[/size]<span lang="EN-US">CPP</span><span>文件都对应一个</span><span lang="EN-US">H</span><span>文件,所以我就去除后缀,只列出名字:</span></span>

<p class="MsoNormal">[size=x-small;]<span lang="EN-US">Colors//[/size]<span>主要是一些配置信息,比如是否显示动画效果,还有字体大小之类的</span></span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]Demoitemanimation[/size]</span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]Dockitem[/size]</span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]Guideline[/size]</span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]Headingitem[/size]</span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]Itemcircleanimation[/size]</span>

<p class="MsoNormal">[size=x-small;]<span lang="EN-US">Score//[/size]<span>动画效果实现的类,文字飞入飞出</span></span>

<p class="MsoNormal">[size=x-small;]<span lang="EN-US">Textbutton//[/size]<span>定义显示在左边的按钮的一些属性,如果需要修改按钮的外观或者位置,在这里修改</span></span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]?[/size]</span>

<p class="MsoNormal" style="text-align: left;" align="left">[size=x-small;]<span>这个是主窗体类,其实就是整个程序[/size]<span lang="EN-US">UI</span><span>的核心部分,所以前面说的去除不想要的两个图片,或者修改背景图(我觉得背景可以不修改,修改的话需要调整</span><span lang="EN-US">Button</span><span>大小,增加工作量),或者程序图标,都在这个类中,只要根据资源图片的名字,查找代码里面出现这些名字的位置,很容易发现和去掉的,这里就不麻烦大家,我列出在</span><span lang="EN-US">mainwindow.h</span><span>的下面有两个</span><span lang="EN-US">ImageItem*</span><span>的对象,就是图标,去掉即可。其他部分,相信只要熟悉</span><span lang="EN-US">GUI</span><span>编程的,很容易定制,就不多说了。</span></span>

<p class="MsoNormal" style="text-align: left;" align="left"><span lang="EN-US">[size=x-small;]Menumanager[/size]</span>

<p class="MsoNormal" style="text-align: left;" align="left">[size=x-small;]<span>首先看[/size]<span lang="EN-US">BUTTON_TYPE</span><span>的定义,明显看出它仅仅支持三个层次,所以只定义到</span><span lang="EN-US">Menu2</span><span>,第一件要做的事情就是扩展这个定义,一定要保持连续性,这样方便处理。改成这样:</span></span>

<p class="MsoNormal" style="text-align: left;" align="left">?
    
enum BUTTON_TYPE {ROOT, MENU1, MENU2, MENU3, MENU4, MENU5, MENU6, QUIT, FULLSCREEN, UP, DOWN, BACK};

?
?


<p class="MsoNormal" style="text-align: left;" align="left"><span lang="EN-US">[size=x-small;]?[/size]</span>

typedef struct
{
	BUTTON_TYPE type;
	QDomElement element;
}NodeRecode; 


// Create first level menu:
QDomElement rootElement = this->contentsDoc->documentElement();
this->createRootMenu(rootElement);
    
QDomNode node;
NodeRecode recode;
recode.type = MENU1;
QList<NodeRecode> nodeList;
node = rootElement.firstChild();
while(!node.isNull())//将根节点的子节点放入队列,一遍遍历
{	

	recode.element = node.toElement();
	nodeList.push_back(recode);
	node =node.nextSibling();
}
	
//遍历所有节点
while(!nodeList.isEmpty())
{
	recode= nodeList.takeFirst();//队列中取出一个节点
	if(recode.element.attribute("name")==NULL)//无名字节点剔除不做任何处理,包括子节点
	{
		continue;
	}
	this->readInfoAboutExample(recode.element);
	if( info[recode.element.attribute("name")]["isLeaf"] != "true")//非叶子
	{
		recode.type = BUTTON_TYPE((int)recode.type + 1);// BUTTON_TYPE中的MENU必须按顺序摆放
		this->createSubMenu(recode.element,recode.type);//创建目录按钮
		node = recode.element.firstChild();
		while(!node.isNull())
		{
			recode.element = node.toElement();
			nodeList.push_back(recode);
			node = node.nextSibling();
		}			
	}
	else//叶子
	{		
		this->createLeafMenu(recode.element);//创建叶子按钮
	}
}

?
?

<p class="MsoNormal" style="text-align: left;" align="left"><span>[size=x-small;]其他一些边角的按钮我就不细说了,修改方法也很简单,找到也很简单,根据名字搜索即可找到按钮生成的代码了。[/size]</span>

<p class="MsoNormal" style="text-align: left;" align="left">[size=x-small;]<span>这个类另一个重点在于,既然扩展了层次的数量,那么原来的[/size]<span lang="EN-US">BACK</span><span>按钮将不适用了(之前的处理方式是,不管你点到什么程度点</span><span lang="EN-US">BACK</span><span>一律回到</span><span lang="EN-US">ROOT</span><span>目录)所以需要修改以支持多级目录,我的方法是采用一个结构记录回退层次以及按钮的</span><span lang="EN-US">ID</span><span>,处理逻辑是,每次点击按钮,就做适当的记录,然后点</span><span lang="EN-US">Back</span><span>后,弹出最近的那个记录,然后恢复到那个点(</span><span lang="EN-US">ItemSelect</span><span>就是按钮点击事件的处理逻辑,参数是按钮的</span><span lang="EN-US">BUTTON_TYPE</span><span>和名字)</span></span>

<p class="MsoNormal" style="text-align: left;" align="left">?

<p class="MsoNormal" style="text-align: left;" align="left">?
//后进先出队列记录 返回位置
typedef struct 
{
	BUTTON_TYPE type;
	QString ID;
}BackPoint;
QList<BackPoint> backList;//记录回退地址
void setBackList( BackPoint );

?


<p class="MsoNormal" style="text-align: left;" align="left">层次按钮事件处理部分代码(itemSelected的一个Case):

<p class="MsoNormal" style="text-align: left;" align="left">?
case MENU1:
	type=MENU1;
	goto here;
case MENU2:
	type=MENU2;
	goto here;
case MENU3:
	type=MENU3;
	goto here;
case MENU4:
	type=MENU4;
	goto here;
case MENU5:
	type=MENU5;
	goto here;
case MENU6://如果需要添加层次 依上添加即可BUTTON_TYPE中 MENU N 必须按序排列否则会出错
	type=MENU6;
	goto here;
here:
	if(info[menuName]["isLeaf"] == "true")//叶子节点处理方法
	{
		   //对于Back按钮的操作,叶子节点不记录会跳路径
	          this->score->queueMovie(this->currentInfo + " -out", Score::NEW_ANIMATION_ONLY);
                  this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
                  // book-keeping:
                  this->currentMenuCode = type;
                  this->currentInfo = menuName;
                  // in / shake:
                  this->score->queueMovie("upndown -shake");
                  this->score->queueMovie("back -shake");
                  this->score->queueMovie(this->currentMenu + " -shake");
                  this->score->queueMovie(this->currentInfo, Score::NEW_ANIMATION_ONLY);
                  this->score->queueMovie(this->currentInfo + " -buttons", Score::NEW_ANIMATION_ONLY);
                  if (!Colors::noTicker){
                        this->score->queueMovie("ticker -out", Score::NEW_ANIMATION_ONLY);
                        this->window->switchTimerOnOff(false);
                }
	}
	else//非叶子节点(即目录节点)的操作
	{
		//目录节点需要记录回跳路径
	         this->score->queueMovie(this->currentMenu + " -out", Score::FROM_START, Score::LOCK_ITEMS);
                 this->score->queueMovie(this->currentMenuButtons + " -out", Score::FROM_START, Score::LOCK_ITEMS);
                  this->score->queueMovie(this->currentInfo + " -out");
                  // book-keeping:
                  this->currentMenuCode = type;
                  this->currentCategory = menuName;

		  tmp.type = type;
		  tmp.ID = menuName;
		  this->setBackList(tmp);

                  this->currentMenu = menuName + " -menu1";
                  this->currentInfo = menuName + " -info";
                  // in:
                 this->score->queueMovie("upndown -shake");
                 this->score->queueMovie("back -in");
                 this->score->queueMovie(this->currentMenu, Score::FROM_START, Score::UNLOCK_ITEMS);
                 this->score->queueMovie(this->currentInfo);
                 if (!Colors::noTicker)
                       this->ticker->useGuideTt();
	}
	break;

?
?


<p class="MsoNormal" style="text-align: left;" align="left">?

case BACK:{
            // out:
            this->score->queueMovie(this->currentInfo + " -out", Score::NEW_ANIMATION_ONLY);
            this->score->queueMovie(this->currentInfo + " -buttons -out", Score::NEW_ANIMATION_ONLY);
            // book-keeping:
            this->currentMenuCode --;
            this->currentMenuButtons = this->currentCategory + " -buttons";
            this->currentInfo = this->currentCategory + " -info";
            // in / shake:
            this->score->queueMovie("upndown -shake");
            this->score->queueMovie(this->currentMenu + " -shake");
            this->score->queueMovie(this->currentInfo, Score::NEW_ANIMATION_ONLY);
            this->score->queueMovie(this->currentInfo + " -buttons", Score::NEW_ANIMATION_ONLY);
            if (!Colors::noTicker)
			{
                this->ticker->doIntroTransitions = false;
            //    this->tickerInAnim->startDelay = 500;
                this->score->queueMovie("ticker", Score::NEW_ANIMATION_ONLY);
                this->window->switchTimerOnOff(true);
            }

            if(this->backList.size() >=1 )//如果链表中节点多于两个
			{
				this->backList.removeLast();//剔除当前节点
			}
			if(this->backList.isEmpty() )//无节点,则跳到跟节点
			{
				itemSelected(ROOT,Colors::rootMenuName);
			}			
			else//还有节点剩余,即为需要跳到的点
			{		
				BackPoint point=this->backList.takeLast();
				itemSelected(point.type,point.ID);
			}

        break; }

?
<p class="MsoNormal" style="text-align: left;" align="left">[size=x-small;]<span>上面这些基本把该做的大部分事情都弄了,剩下的问题就是如何显示每个部分的文字和图示了,由于[/size]<span lang="EN-US">qtdemo</span><span>涉及到</span><span lang="EN-US">qhelpEngine</span><span>我们其实不需要使用的,所以要去掉它,方法是,屏蔽头文件,然后慢慢找出依赖的语句,一句句删干净就好了。很暴力,但也很简单。当然删完,就要自己把要显示的数据呈现出来了。以下两个类做的事情差不多,都是读取文字和图片,然后显示,但作用的位置不一样,</span><span lang="EN-US">Exmpleconten</span><span>作用于叶子节点,</span><span lang="EN-US">Menucontent</span><span>作用于目录节点。所以合并起来说。</span></span>

<p class="MsoNormal"><span lang="EN-US">[size=x-small;]Memucontent[/size]</span>

<p class="MsoNormal">[size=x-small;]<span>我们采用的方法比较简单,就是从文件中读取跟按钮名字同名的文件,文字就从[/size]
<span lang="EN-US">./data/</span><span>(按钮名)</span><span lang="EN-US">.txt</span><span>文件读入,图片优先从</span><span lang="EN-US">XML</span><span>节点</span><span lang="EN-US">image</span><span>属性指定的路径读入,如果没有再从</span><span lang="EN-US">./image/</span><span>(按钮名)</span><span lang="EN-US">.png</span><span>读入。然后显示。所以比较简单,仅仅支持单一图片,所以如果你需要进一步扩展可能需要对程序了解更多才行。代码如下:</span></span>

<p class="MsoNormal">[size=x-small;]<span lang="EN-US">Main <span>?[/size]</span><span>不用理会</span><span lang="EN-US">…</span></span>

<p class="MsoNormal">[size=x-small;]<span>这个程序的使用十分简单,仅需根据你要编辑的内容结构,生成一个[/size]
<span lang="EN-US">./xml/example.xml </span><span>文件,然后在</span><span lang="EN-US">./data/ </span><span>下根据按钮名字写好描述性的文字,规则如前所述。执行程序即可,扩展起来也很方便,但其缺点是,节点名字不能重合,除非他们使用相同的描述文字或者图示。不让后面的节点信息会覆盖前面的,我的处理方法是,给节点加</span><span lang="EN-US">” ”</span><span>空格以区分以及尽量不让节点重名。(这部分内容需要参考</span><span lang="EN-US">MenuManager::readInfoAboutExample</span><span>方法,他根据节点名从</span><span lang="EN-US">XML</span><span>中读入属性,所以如何实现可以重名的结构我也做过尝试但失败了)</span></span>

<p class="MsoNormal">如果你没有耐心看以上部分,我也整理了个可用的代码,提供大家学习交流。
 
   
     
       

             
  • qtdemoModified.rar (74.9 KB)

  •          
             
  • 下载次数: 0

  •        

     
   
   
 

你可能感兴趣的:(java,工作,qtdemo浅析)