2015年3月26日星期四

OpenGL在Ubuntu初始配置问题汇集

简单的OpenGL配置在此不多说,glut.h什么的不在此文范围

本文主要针对自己测试/学习各种奇葩代码时所遇到的形形色色问题而总结


1. fatal error: GL/glew.h: No such file or directory


  • sudo apt-get install libglew-dev 即可解决
如图





2. fatal error: GLFW/glfw3.h: No such file or directory
这是个大麻烦,参考了How to build & install GLFW 3 and use it in a Linux projectubuntu 14.04下编译GLFW3筛选了,找到了如下完美解决方案

  • 下载GLFW源代码
  • 安装cmake cmake-gui  使用sudo apt-get install cmake cmake-gui
  • 安装编译环境,sudo apt-get build-dep glfw or sudo apt-get build-dep glfw3 sudo apt-get install cmake xorg-dev libglu1-mesa-dev
  • 进入GLFW.zp解压后的目录,....cd glfw-3.X.X 
  • 尽情地make和 sudo make install,看着代码刷刷刷飞过,特别舒服编译完成后,会显示安装完成的目录所在,我的是
  • 不要忘了测试,新建test.cpp,贴进如下代码:
#include 
#include 
#include 
static void error_callback(int error, const char* description)
{
    fputs(description, stderr);
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}
int main(void)
{
    GLFWwindow* window;
    glfwSetErrorCallback(error_callback);
    if (!glfwInit())
        exit(EXIT_FAILURE);
    window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        exit(EXIT_FAILURE);
    }
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, key_callback);
    while (!glfwWindowShouldClose(window))
    {
        float ratio;
        int width, height;
        glfwGetFramebufferSize(window, &width, &height);
        ratio = width / (float) height;
        glViewport(0, 0, width, height);
        glClear(GL_COLOR_BUFFER_BIT);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-ratio, ratio, -1.f, 1.f, 1.f, -1.f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glRotatef((float) glfwGetTime() * 50.f, 0.f, 0.f, 1.f);
        glBegin(GL_TRIANGLES);
        glColor3f(1.f, 0.f, 0.f);
        glVertex3f(-0.6f, -0.4f, 0.f);
        glColor3f(0.f, 1.f, 0.f);
        glVertex3f(0.6f, -0.4f, 0.f);
        glColor3f(0.f, 0.f, 1.f);
        glVertex3f(0.f, 0.6f, 0.f);
        glEnd();
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwDestroyWindow(window);
    glfwTerminate();
    exit(EXIT_SUCCESS);
}


  • g++ -std=c++11 -c test.cpp生成.o文件
  • g++ test.o -o test.exec -lGL -lGLU -lglfw3 -lX11 -lXxf86vm -lXrandr -lpthread -lXi
  • Enjoy it
3.又出现了新的问题fatal error: glm.hpp: No such file or directory

缺少glm.hpp文件,需要安装glm,即OpenGL Mathematics,下载之,解压之,得到glm文件夹,其中还有同名子文件夹glm,其余还有doc文件夹,里边有glm的文档说明pdf。
  
  值得注意的是,glm只是一个C++的库,不需要去build它。

  cd进入glm根目录,对子文件夹glm进行操作 sudo cp -r glm/ /usr/local/include/ ,-r是复制所有子文件子文件夹。

按照官方说明安装好了,可是我的问题又出来了——还是报错。。。。绞尽脑汁,反复谷歌,还是没有找出问题。脑子一拍,看了下头文件**.h 头文件,娘西皮的,竟然是#include<glm.hpp>,而我的路径是/include/glm/glm.hpp。修改头文件为#include<glm/glm.hpp>问题就解决了!

4.fatal error: : No such file or directory

谁能告诉我opencv2和opencv是不是一代二代的关系,心力憔悴,先睡去了。

-------------睡不着我又回来了-------------

应该头文件opencv2是opencv里边的,不管怎么样,先安装opencv吧
下载最新的opencv.sh文件,cd进入此目录。执行chmod +x opencv.sh ,然后./opencv.sh


2015年3月25日星期三

给定字符串全排列问题(递归/非递归)

刚才刷微博,看到有人吐槽T大某系GPA第一咖啡馆面试,字符串去重全排列冰淇淋化了都没有搞定。暗笑递归大法好的时候,才看到此题要求非递归,那就谷歌谷歌整理一下吧。

如题,用C++写一个函数, 如 Foo(const char *str), 打印出 str 的全排列, 
如 abc 的全排列: abc, acb, bca, dac, cab, cba

一.全排列的递归实现

为方便起见,用123来示例下。123的全排列有123、132、213、231、312、321这六种。首先考虑213和321这二个数是如何得出的。显然这二个都是123中的1与后面两数交换得到的。然后可以将123的第二个数和每三个数交换得到132。同理可以根据213和321来得231和312。因此可以知道——全排列就是从第一个数字起每个数分别与它后面的数字交换。找到这个规律后,递归的代码就很容易写出来了:

//全排列的递归实现
#include 
#include 
void Swap(char *a, char *b)
{
 char t = *a;
 *a = *b;
 *b = t;
}
//k表示当前选取到第几个数,m表示共有多少数.
void AllRange(char *pszStr, int k, int m)
{
 if (k == m)
 {
  static int s_i = 1;
  printf("  第%3d个排列\t%s\n", s_i++, pszStr);
 }
 else
 {
  for (int i = k; i <= m; i++) //第i个数分别与它后面的数字交换就能得到新的排列
  {
   Swap(pszStr + k, pszStr + i);
   AllRange(pszStr, k + 1, m);
   Swap(pszStr + k, pszStr + i);
  }
 }
}
void Foo(char *pszStr)
{
 AllRange(pszStr, 0, strlen(pszStr) - 1);
}
int main()
{
 printf("         全排列的递归实现\n");
 printf("  --by Peikun( http://izpk.blogspot.fr )--\n\n");
 char szTextStr[] = "123";
 printf("%s的全排列如下:\n", szTextStr);
 Foo(szTextStr);
 return 0;
}
运行结果如下:


注意这样的方法没有考虑到重复数字,如122将会输出:

这种输出绝对不符合要求,因此现在要想办法来去掉重复的数列。

二.去掉重复的全排列的递归实现

由于全排列就是从第一个数字起每个数分别与它后面的数字交换。我们先尝试加个这样的判断——如果一个数与后面的数字相同那么这二个数就不交换了。如122,第一个数与后面交换得212、221。然后122中第二数就不用与第三个数交换了,但对212,它第二个数与第三个数是不相同的,交换之后得到221。与由122中第一个数与第三个数交换所得的221重复了。所以这个方法不行。
换种思维,对122,第一个数1与第二个数2交换得到212,然后考虑第一个数1与第三个数2交换,此时由于第三个数等于第二个数,所以第一个数不再与第三个数交换。再考虑212,它的第二个数与第三个数交换可以得到解决221。此时全排列生成完毕。
这样我们也得到了在全排列中去掉重复的规则——去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。用编程的话描述就是第i个数与第j个数交换时,要求[i,j)中没有与第j个数相等的数。下面给出完整代码:

//去重全排列的递归实现
#include 
#include 
#include 
void Swap(char *a, char *b)
{
 char t = *a;
 *a = *b;
 *b = t;
}
//在pszStr数组中,[nBegin,nEnd)中是否有数字与下标为nEnd的数字相等
bool IsSwap(char *pszStr, int nBegin, int nEnd)
{
 for (int i = nBegin; i < nEnd; i++)
  if (pszStr[i] == pszStr[nEnd])
   return false;
 return true;
}
//k表示当前选取到第几个数,m表示共有多少数.
void AllRange(char *pszStr, int k, int m)
{
 if (k == m)
 {
  static int s_i = 1;
  printf("  第%3d个排列\t%s\n", s_i++, pszStr);
 }
 else
 {
  for (int i = k; i <= m; i++) //第i个数分别与它后面的数字交换就能得到新的排列
  {
   if (IsSwap(pszStr, k, i))
   {
    Swap(pszStr + k, pszStr + i);
    AllRange(pszStr, k + 1, m);
    Swap(pszStr + k, pszStr + i);
   }
  }
 }
}
void Foo(char *pszStr)
{
 AllRange(pszStr, 0, strlen(pszStr) - 1);
}
int main()
{
 printf("         去重全排列的递归实现\n");
 printf("  --by Peikun( http://izpk.blogspot.fr  )--\n\n");
 char szTextStr[] = "122";
 printf("%s的全排列如下:\n", szTextStr);
 Foo(szTextStr);
 return 0;
}

运行结果如下:


OK,到现在我们已经能熟练写出递归的方法了,并且考虑了字符串中的重复数据可能引发的重复数列问题。那么如何使用非递归的方法来得到全排列了?

三.全排列的非递归实现

要考虑全排列的非递归实现,先来考虑如何计算字符串的下一个排列。如"1234"的下一个排列就是"1243"。只要对字符串反复求出下一个排列,全排列的也就迎刃而解了。
如何计算字符串的下一个排列了?来考虑"926520"这个字符串,我们从后向前找第一双相邻的递增数字,"20"、"52"都是非递增的,"26 "即满足要求,称前一个数字2为替换数,替换数的下标称为替换点,再从后面找一个比替换数大的最小数(这个数必然存在),0、2都不行,5可以,将5和2交换得到"956220",然后再将替换点后的字符串"6220"颠倒即得到"950226"。
对于像"4321"这种已经是最“大”的排列,采用STL中的处理方法,将字符串整个颠倒得到最“小”的排列"1234"并返回false。
这样,只要一个循环再加上计算字符串下一个排列的函数就可以轻松的实现非递归的全排列算法。按上面思路并参考STL中的实现源码,不难写成一份质量较高的代码。值得注意的是在循环前要对字符串排序下,可以自己写快速排序的代码(请参阅《白话经典算法之六 快速排序 快速搞定》),也可以直接使用VC库中的快速排序函数(请参阅《使用VC库函数中的快速排序函数》)。下面列出完整代码:

//全排列的非递归实现
#include 
#include 
#include 
#include 
void Swap(char *a, char *b)
{
 char t = *a;
 *a = *b;
 *b = t;
}
//反转区间
void Reverse(char *a, char *b)
{
 while (a < b)
  Swap(a++, b--);
}
//下一个排列
bool Next_permutation(char a[])
{
 char *pEnd = a + strlen(a);
 if (a == pEnd)
  return false;
 char *p, *q, *pFind;
 pEnd--;
 p = pEnd;
 while (p != a)
 {
  q = p;
  --p;
  if (*p < *q) //找降序的相邻2数,前一个数即替换数
  {
   //从后向前找比替换点大的第一个数
   pFind = pEnd;
   while (*pFind <= *p)
    --pFind;
   //替换
   Swap(pFind, p);
   //替换点后的数全部反转
   Reverse(q, pEnd);
   return true;
  }
 }
 Reverse(p, pEnd);//如果没有下一个排列,全部反转后返回true
 return false;
}
int QsortCmp(const void *pa, const void *pb)
{
 return *(char*)pa - *(char*)pb;
}
int main()
{
 printf("         全排列的非递归实现\n");
 printf("  --by Peikun( http://izpk.blogspot.fr )--\n\n");
 char szTextStr[] = "abc";
 printf("%s的全排列如下:\n", szTextStr);
 //加上排序
 qsort(szTextStr, strlen(szTextStr), sizeof(szTextStr[0]), QsortCmp);
 int i = 1;
 do{
  printf("第%3d个排列\t%s\n", i++, szTextStr);
 }while (Next_permutation(szTextStr));
 return 0;
}
测试一下,结果如下所示:



将字符串改成"cba"会输出:

至此我们已经运用了递归与非递归的方法解决了全排列问题,总结一下就是:
1.全排列就是从第一个数字起每个数分别与它后面的数字交换。
2.去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换。
3.全排列的非递归就是由后向前找替换数和替换点,然后由后向前找第一个比替换数大的数与替换数交换,最后颠倒替换点后的所有数据。

以上主要转载STL系列之十 全排列(百度迅雷笔试题)的内容,代码微调在本地重新实现,图也是我重新截的,调试过程遇到几个问题,如下:

1.'for' loop initial declarations are only allowed in C99 mode
不能在for循环中声明变量。我使用的是codeblocks,默认环境为C94,在Setings -> Complier and debugger settings -> other options中 添加语句“-std=c99”即可解决(注意去掉引号)

2.expected '=', ',', ';', 'asm' or '__attribute__' before IsSwap
可以确定的是,IsSwap前边并不缺乏那些蛋疼的符号,谷歌一下发现有很多雷同问题,但是原因也是千奇百怪:

  • 有可能是漏写;}或者将)写成},或者是中英文混写,如将英文的)写成中文的)。
  • 机器码本身的问题,需要对数据类型进行typedef,如,使用int类型或者 char类型,分别进行定义,typedef in DTYPE,typedef char PCHAR,这一点没试验过,是看别人的
  • 没有加上需要的头文件
  • C和C++混编,如在C中使用class inline等,需要加上extern告诉编译器。因为C和C++的编译时找不同的内部代码,如果不告诉他,他会找一种,比如说全部找C的内部解释,那么C++部分的就会出错;
  • 明显的错误,比如c代码,结果写了个函数 bool testIt;而bool默认没有定义,所以报错;改成int的就行了;
还以为是什么千奇百怪的头文件...以“bool 声明”关键字搜索发现,缺少了stdbool.h的头文件,加上即可解决

总结:
去年下半年一直在学函数式编程OCaml,现在思考养成了递归优先的习惯,也是懒。
算法是一条漫长的练级路,吾将左蹦右跳来求索

OpenGL学习笔记整理(一)

代码如下
#ifdef _APPLE_
#include   //OS X version of GLUT
#else
#define FREEGLUT_STATIC
#include    //Windows/Linux FreeGlut equivalent
#endif

int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("3D Effects Demo");
glutReshapeFunc(ChangeSize);
glutKeyboardFunc(KeyPressFunc);
glutDisplayFunc(RenderScene);

SetupRC();

glutMainLoop();
glDeleteTextures(4,textures);
return0;
}
代码中所示的几个函数,算是最入门级别的,还是整理下吧。

gluInit(&argc,argv) 初始函数,对GLUT进行初始化,必须在使用其他GLUT前调用

glutInitDisplayMode 设置显示模式,GLUT_DOUBLE为双缓冲,GLUT_RGBA私用RGBA颜色模式,GLUT_DEPTH使用深度缓存,GLUT_SINGLE使用单缓存。单缓冲区的窗口因为这所有的绘图命令都在显示的窗口中执行,双缓冲的窗口中执行绘图命令世纪上是在画面以外创建一个场景,然后很快交换到窗口的视图中来,常用于产生动画效果。

glutInitWindowSize 设置窗口大小

glutCreateWindow(“title”) 创建窗口,参数为标题名


glutDisplayFunc(RenderScene) 将先前定义的函数RenderScene设为回调函数,意味着只要需要绘制窗口,GLUT就会调用这里指定的函数,例如,在第一次显示窗口或改变窗口大小或移去窗口上覆盖的其他窗口时就会发生调用 

glutReshapeFunc(ChangeSize);
用户可以自己写一个函数,然后接收两个参数之后,做一定的工作。通常是为了避免在窗口大小变化的过程中显示的内容扭曲失真。
示例:
void ChangeSize(int w , int h)
{
glViewport(0,0,w,h);
}
glutKeyboardFunc(void (*func)(unsigned char key, int x, int y));
用户可以自定义一个键盘响应函数,它有三个参数,第一个用来接收键盘按键的ASCII值,后两个是鼠标在屏幕上的位置。
glutDisplayFunc(RenderScene) 
void RenderScene(void)
{
glClear(Gl_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
glColor3f(1.0f,1.0f,1.0f);
glLoadIdentity();
gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0);
glScalef(1.0f,2.0f,1.0f);
glutWireCube(1.0);
glutSwapBuffers();
}

glClear 在每次重画前,把上次画的东西清除掉

SetupRC()是我们进行OpenGL初始化的地方,初始话必须在渲染之前进行。OpenGL的许多状态只需要设置一次,而不必没渲染一帧(全部图形的一个场景)就重新设置一次。

glutMainLoop() 此函数让GLUT框架开始运行,在为屏幕显示和其他函数定义了回调之后,请放开GLUT的缰绳吧,这个函数会处理所有特定于操作系统

程序在实际中的初始运行顺序,main入口->SetupRc->changeSize->RenderScene

OpenGL 绘图的机制是: 先用 OpenGL 的绘图上下文 Rendering Context (简称为 RC,SetupRC负责 )把图画好,再把所绘结果通过 SwapBuffer() 函数传给 Window 的 绘图上下文 Device Context (简记为 DC).要注意的是,程序 运行过程中,可以有多个 DC,但只能有一个 RC。因此当一个 DC 画完图后,要立即释放 RC,以便其它的 DC 也使用。


2015年3月17日星期二

Blogger中贴代码解决方案

苦苦谷歌了半晚上,试验了三种方案,最后前两者效果一般被弃,下边只说第三种

效果下所示:

#include
int main()
{
    printf"Peikun is a handsome boy";
    return 0;
}

实现方法:

1.进入blogger后台-->模板-->修改HTML

2.编辑HTML模板,定位至</head>,将如下代码贴指</head>之前,然后保存





使用方法:

需要粘贴代码时,需要引用以下格式:
// 快把代码都扔到这里来
注意,brush后面是所选的语言,目前支持python, java, cpp, xml, vb, css, ruby, sql, perl等

瞧,最新的一篇博文java中this的用法中的代码效果就是杠杠的


java中this的用法

在一般方法中
   最普遍的情况就是,在你的方法中的某个形参名与当前对象的某个成员有相同的名字,这时为了不至于混淆,你便需要明确使用this关键字来指明你要使用某 个成员,使用方法是“this.成员名”,而不带this的那个便是形参。另外,还可以用“this.方法名”来引用当前对象的某个方法,但这时this 就不是必须的了,你可以直接用方法名来访问那个方法,编译器会知道你要调用的是那一个。下面的代码演示了上面的用法:

public class DemoThis{
  private String name;
  private int age;
  DemoThis(String name,int age){
    setName(name); //你可以加上this来调用方法,像这样:this.setName(name);但这并不是必须的
    setAge(age);
    this.print();
  }   
  public void setName(String name){
    this.name=name;//此处必须指明你要引用成员变量
  }
  public void setAge(int age){
    this.age=age;
  }
  public void print(){
    System.out.println("Name="+name+" Age="+age);//在此行中并不需要用this,因为没有会导致混淆的东西
  }
  public static void main(String[] args){
    DemoThis dt=new DemoThis("Kevin","22");
  }
}
   
这段代码很简单,不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它,两者效果一样。


转载以下来自博客园的一篇总结(转)java中this的用法

论专业技能和见识阅历

刚才在朋友圈看到宇轲分享的知乎帖子对放弃高考准备去上海图书馆自修的19岁男孩有怎样的建议?,字字句句甚是犀利。

阅历和视野让人受益匪浅,但是,对于青年来说,阅历是成本最低的成长方法。

每天大量的阅读量,博览群书,各种新闻深度,各种历史政治,觉得受益匪浅,自觉也比身边的“俗人”见识和阅历不知高到哪里去了。

可是,这几件事,没有一件有难度,没有一件是别人做不到的,只要别人想做,他们也能做到。显然,大多数的他们有更重要的事情。


很多人年纪不大,看不起自己宿舍的学霸,想着走千山万水,以为自己是英雄末路,恨不得三尺剑得天下,大学毕业了,学霸找到工作,又觉得学霸不懂人情世故,自己八面玲珑。

一年以后同学会,学霸各个八面琳珑,如鱼得水,自己还在找工作。

所谓八面琳珑,人情世故,见识阅历,视野开阔,你走上社会,最多三年,只要你想,肯定能成,除非你蠢。

但专业技能,知识匹配,一技之长,核心能力,熟练掌握者,百里挑一。


到底哪个才是更难的?

很显然,是专业知识、专业技能的学习。

写下这篇文字之前的我,是如此的幼稚,幼稚到以为见识和阅历是比专业技能更重要更有用的。诚然,我的意识不算错,只是错在了时间点。在没有坚实的基础,过人的技能,笑傲群雄的一技之长之前,见识和阅历也不过给饭桌上增加了点谈资,别人不会因此高看你什么。

要想让过人的见识和阅历变成你的护城河,必须先砌起自己稳固、高壮的城墙。你再怎么有战略思维,一辈子搬砖肯定用不上;再怎么有历史的眼光,天天蹲在地下室蜗居也用不上。你要做的是,一步一步扎实地积累,一寸一寸坚定地向上再向上。只有护城河,没有城墙的城堡就好比只有牙齿没有利爪的老虎,纸老虎!护城河和城墙相辅相成,才能各得其所,实现各自的最大价值。

感谢这篇知乎帖子,可谓是惊醒梦中人。法国时间2015年3月17日,21:28,以后无比厉害的我会铭记这一刻的。

2015年3月11日星期三

解决Chrome因Flash插件卡顿、页面假死问题

在线看高清点的视频,会很卡,抑或是Flash多点的页面,动不动就假死,很是烦人,搜索一番,找到了原因:


Chrome集成的Adobe Flash Player 不支持GPU硬解码,对于分辨率高的视频软解CPU很容易飙升

解决办法也很简单:

-禁用Chrome集成的Adobe Flash Player 
-用Adobe官方的替代之

  下载Adobe Flash Player ,安装

2.进入chrome://plugins页面,禁用Chrome自带的Flash(位置在chrome目录中的),启动新安装的(在windows目录中)

  如图所示


问题解决了,chrome可以愉快地飞起啦

-----update 2015-11-26----


Chrome的settings -> Show Advanced Settings... -> Privacy -> Prefetch resources to load pages more quickly


这样可以解决部分磁盘占用100%的情况。



Eclipse 新建Activity

2015.5.17更新:

Activity的建立方法有两种,我给他们起名字分别叫手动和自动,差异在是否自动在layout中建立xml文件及自动在AndroidManifest中注册。

之前写的帖子是谷歌得来的,现在看来非常狭隘。

先说,手动。

  1. 选中包,右键,新建class,命名之,superClass选项中填上需要继承的Activity,得到一基本空白的文件,然后手动完成onCreate等部分。
  2. 在res/layout中新建相应xml文件,选中此文件夹,右键->new->Android XML File,注意此xml文件名务必于1中setContentView(R.layout.Iamhandsomeboy)的Iamhandsomeboy保持一致
  3. 进入AndroidManifest文件,看清楚标签,在Application下,完成activity的注册,如<activity android:name="Iamhandsomeboy"></anctivity>,当然,这是最基础的部分。
再说,自动。
  1. 选中当前包,Eclipse左上角->New->Android->Android Activity
  2. 完成Activity Name,Layout Name等
  3. Hierarchical Parent中选中当前新建类的父类
  4. 溜溜的,当前包下的java文件(有初始代码),layout下的xml布局文件,AndroidManifest中的注册都搞定了。按需修改即可。
总结。
  1. 新建的Activity必须在AndroidManifest注册,必须
  2. 如果无关layout,可以不在layout中新建xml,即没有setContentView部分-----这个名词叫啥来着?



****************************************
有同学求救如何如题问题,那就写一个发给它喽

Ecplise中新建Activity

1.点击工具类中的New,注意不是直接右键


2.选中Android -> Android Activity, Next


3.Blank Activity, Next


4.配置Activity,新窗口中完善如下:

 * Activity Name: DisplayMessageActivity, 
 * Layout Name: activity_display_message
 * Title: My Message, 
 * Hierachical Parent: com.example.hellow.MainActivity
 Finish

此时,在src://下会新建一个名为DisplayMessageActivity.java的类,

打开DisplayMessageActivity.java文件,此类已经实现了onCreate()方法,稍后需要更新此实现方法。另外还有一个onOptionsItemSelected()方法,用来处理action bar的点击行为,保留这两个方法。

新建的Activity的标题需加入String.xml中:
<resources>
    ...
    <string name="title_activity_display_message">My Message</string>
</resources>
在AndroidMainfest.xml的application标签中为DisplayMyMessage添加标签:
<application ... >
    ...
    <activity
        android:name="com.mycompany.myfirstapp.DisplayMessageActivity"
        android:label="@string/title_activity_display_message"
        android:parentActivityName="com.mycompany.myfirstapp.MyActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.mycompany.myfirstapp.MyActivity" />
    </activity>
</application>
其中,android:parentActivityName属性声明了在应用程序中该Activity逻辑层面的父类Activity的名称。 使用Support Library,如上所示的<meta-data>元素可以为安卓旧版本提供相同功能。

总结:新建activity很简单,重要的是记着在xml注册