web analytics

Processing:文本

1. 本课我们要学一个新的类,称为字符串(string)。对我们来说,这并不是一个全新的概念,之前我们也曾接触过它们:

println("printing some text to the message window!");      // 列印一个字符串
PImage img = loadImage("filename.jpg");   // 为文件名使用一个字符串

这样看起来,我们似乎可以简单的将字符串理解为“在双引号内的内容”。

2. 字符串的核心其实是储存字母数组,如果没有string类,那么我们要写一行字的代码可能会变成:

char[] sometext = { 'H', 'e', 'l', 'l' , 'o' , ' ', 'W' , 'o' , 'r', 'l' ,  'd'};

这么搞绝对会被搞死,如果使用string对象,世界立马变得简单美好起来:

String sometext = " 如何做一个字符串? 在引号间输入字符!";

3. 我们必须记住,一个string是一个伴随方法(method)的对象。类似于PImage对象可以在存储一个图像数据的同时,还可以使用方法copy(), loadPixels()等等。对于string来说,一个方法是 charAt(),它可以返回一个字符串里给定序号的字母。同数组一样,字符串的第一个字母同为第0号。

4. 通过Daniel随后出的一题我意外的发现,在一个字符串内,空格也算一个“字母”,也占序号,无论这个空格出现在字符串内的任何地方。

5. 另一有用的方法是length()。这常会与数组length的属性混淆。不过你记得按一下方式呼叫它就对了:

String message = "这个字符串有十五个字符那么长。";   
println(message.length());

通过笨办法——数数的方式,我们看到,句号也会被当作一个“字母”。因此我们可以推论,在一个字符串内任何占位符都会被当作一个“字母”被进行计数。

6. 顺序列印一个字符串的每一个字母:

String message = "一堆文字."; 
    for(int i = 0; i < message.length(); i++) {
         char c =  message.charAt(i); 
         println(c);

7. toUpperCase()可以使字符串内字母全大写:

String message = "a bunch of text here.";
String uppercase = message.toLowerCase();   
println(uppercase);

8. toLowerCase()可以使字符串内字母全小写,用法同上。

9. 细心的你可能会发现,在第7条的例子当中,为什么我们要用println(uppercase); ,而不用println(message);?因为string对象是一种特殊的不可变对象。所谓“不可变”是指它的数据永远都不可变。这就意味着任何时候我们要改变一个字符串,我们必须创建一个新的字符串。因此在转换大写的时候,方法toUpperCase()返回的是一个全大写的字符串对象的副本。

10. 最后,我们看看equals()。说到“等于”,也许你首先会想到这么写:

String one = "hello";  
String two = "hello";  
println(one == two);

从技术角度讲,当对对象使用"==",它比较的是每个对象的内存位置。尽管每个字符串包含相同的数据——"hello"——如果它们是不同的对象实例,则"=="可能会返回一个错误的对比。这样的时候,就是equals()发挥作用的时候,它用来对比两个字符串是否包含相同的数据,而无论它们存储的位置在哪里。

String one = "hello";  
String two = "hello";
println(one.equals(two));

尽管以上两种方法都会返回正确的结果,但是用equals()更保险。基于string对象不同的创建方式,"=="不会始终保持正确。

11. 字符串还可用“+”号连接。

String helloworld = "Hello" + "World";

变量照使:

int x = 10;   
String message = "x的值是:" + x;

“图像”一课载入编号图像数组是这一用法一个很好的例子。

12. 要在萤幕上显示一些文本,我们需要做以下简单几步:
12.1. Tools > Creat Font 选择一个子体。这将创建并将字体文件放入你的data文件夹。p5的字体格式很特殊——"vlw",它使用图像来显示每个字母。因为如此,你同时还要指定你想要显示文字的大小。
12.2. 申明一个PFont类型的对象:

PFont f;

12.3. 用loadFont()载入字体。载入一次就够了,所以我门将它放在setup()里,和载入图像一个道理。

f = loadFont("ArialMT-16.vlw");

12.4. 用textFont()指定字体。两个引数,第一个字体变量,第二个字体大小(可选)。如果不指定字体大小,则字体会以最初载入的大小显示。指定一个与创建字体大小不同的字体大小会影像它的显示(和放大缩小图像一样)。

textFont(f,36);

12.5. 用fill()指定颜色。
12.6. 呼叫text()函数显示文本。三个引数:文本,x位置,y位置。

text( "呜呜呜... 字符串...  " ,10,100);

12.7. 上完整的例子:

// Step 2: 申明PFont变量
PFont f;  

void setup() {
  size(200,200);

  // Step 3: Load Font
  f = loadFont( "ArialMT-16.vlw" ); 
} 

void draw() {
  background(255);
  textFont(f,16); // Step 4: 指定要用的字体
  fill(0);        // Step 5: 指定字体颜色

  // Step 6: 显示文本
  text ( "oNEwAY is a Chinese Post-Rock Band" ,10,100); 
}

通过上例,我发现这玩意不会自动换行,,多出来的部分就会显示在窗口之外而不可见。

13. 字体还可被createFont()函数创建:

myFont = createFont( "Georgia", 24, true);   // 三个引数分别是:字体名字,字体大小,是否开启平滑的一个布尔表达式

createFont()允许你创建安装于本机却在p5默认选项中不支持的字体。另外,createFont()允许字体缩放到任意大小而不影响显示质量。更多介绍请参看p5在线手册.

14. PFont.list()可以查看所有可用的字体:

println(PFont.list());     // 列印全部可用于createFont() 的字体。

15. 下面这个练习在弹跳的球旁边伴随显示球的x,y位置(当然一个更好的显示方式是将文本位置固定):

PFont f;

float x = 100; 
float y = 0; 
float speed = 0; 
float gravity = 0.05;

void setup() {
  size(400,200);
  f = createFont("Arial", 16, true);
  smooth();
}

void draw() {
  background(255);
  stroke(175);
  rectMode(CENTER);
  ellipse(x,y,10,10);
  
  y = y + speed;
  
  // Add gravity to speed.
  speed = speed + gravity;
  
  // If square reaches the bottom
  // Reverse speed
  if (y > height) {
    // Multiplying by -0.95 instead of -1 slows the square down each time it bounces (by decreasing speed).  
    // This is known as a "dampening" effect and is a more realistic simulation of the real world (without it, a ball would bounce forever).
    speed = speed * -0.95;  
  }
  
  textFont(f,10);
  fill(0);
  // 将浮点值转为整数并显示 
  text((int)x+", "+(int)y,x+8,y-8);
}

16. textAlign() —— 指定文本对齐模式:

PFont f;

void setup() {
  size(400,200);
  f = createFont("Arial", 16, true);
}

void draw() {
  background(255);
  stroke(175);
  line(width/2,0,width/2,height);
  textFont(f);
  fill(0);
  
  // textAlign()设置文本对齐模式. 它有一个引数: CENTER, LEFT, 或者 RIGHT.
  textAlign(CENTER); // 居中
  text("这是居中的文字." ,width/2,60);
  textAlign (LEFT) ; // 居左
  text("这是左对齐的文字." ,width/2,100);
  textAlign(RIGHT); // 居右
  text("这是右对齐的文字." ,width/2,140);
}

17. textWidth() —— 计算并返回任何字母或文本字符串的宽度。比如说我们要在萤幕下方做一个从右至左的新闻滚动条。当文字全部滚入左边后,从右边重新开始滚动。如果我们知道文本开头的x位置和文本的宽度,我们便可知道它什么时候会完全滚入左边。textWidth()给我们的正是这个宽度。
首先,我们在setup()内申明新闻,字体,x变量,并初始化它们。

//   一条新闻   
String headline = "New study shows computer programming lowers cholesterol.";   
PFont f;   // 全局字体变量   
float x;   // 新闻的水平位置   
void setup()  {   
  f = createFont( "Arial",16,true); // 载入字体   
  x = width; // 将x放到右边 
} 

draw()里边:

// 在x位置显示新闻   
textFont(f,16);   
textAlign(LEFT);   
text(headline,x,180);

让x减小,以使文本向左走:

x = x – 3;

稍微复杂一点的一步,测试文本是否已经全部滚入左侧,如果已经离开萤幕,重置其到最右边:

// 如果x小于文本宽度的负值,则这段文本便完全处于萤幕外
float w = textWidth(headline);   
if (x < -w)  {  
  x = width;      
}

下例即以上代码的合体,唯一不同的是,它分别滚动两段不同的文本:

// 新闻数组
String[] headlines = {
  "Processing downloads break downloading record." ,
  "New study shows computer programming lowers cholesterol." ,
};

PFont f; // 全局字体变量
float x; // 水平位置
int index = 0;

void setup() {
  size(400,200);
  f = createFont( "Arial" ,16,true);
  
  // 初始化x到最右
  x = width;
}

void draw() {
  background(255);
  fill(0);
  
  // 在x位置显示新闻
  textFont(f,16);
  textAlign (LEFT);
  
  // 基于"index"变量的值显示数组的一个特定字符串
  text(headlines[index],x,180); 
  
  // 递减x
  x = x - 3;
  
  // 如果x小于文本宽度的负值,则这段文本便完全处于萤幕外
  // textWidth()被用来计算当前字符串的宽度.
  float w = textWidth(headlines[index]); 
  if (x < -w) {
    x = width;
    // 递增index,这样当当前字符串离开萤幕便显示一个新的字符串。
    index = (index + 1) % headlines.length; 
  }
}

18. 除了textAlign()和textWidth()外,还有textLeading(), textMode()和textSize()可用,自己看p5在线参考for more。

19. 习题17-6,做一个接头接尾持续滚动的文本条。看似简单,我却不会,,已经给了Daniel邮件,等他答案。

20. 结合像素数组,我们可以用字母做一个视频马赛克,代码长度不短:

import processing.video.*;

// 缩放值
int videoScale = 14;
// 我们系统中行和列的数量
int cols, rows;
// capture对象
Capture video;

// 马赛克模式中的源文本. 越长的字符串也许会出现越有趣的结果.
String chars = "fuckyoubaby" ; 

PFont f;

void setup() {
  size(640,480);
  // 建立行和列
  cols = width/videoScale;
  rows = height/videoScale;
  video = new Capture(this,cols,rows,15);
  
  // 载入字体
  // 使用一个固定宽度的字体. 对大多数字体来说, 不同的字母有不同的宽度. 
  // 在固定宽度字体钟, 所有字母等宽. 
  // 这对本例很有用,因为我们要在空间平均排布这些字母 
  f = loadFont("Courier-Bold-20.vlw");
}

void draw() {
  background(0);
  
  // 从摄像头读取图像
  if (video.available()) {
    video.read();
  }
  video.loadPixels();
  
  // 使用一个计数器变量来数字符串中的字母
  int charcount = 0;
  // 开始循环行
  for (int j = 0; j < rows; j ++ ) {
    // 开始循环列
    for (int i = 0; i < cols; i ++ ) {
      
      // 我们在哪?
      int x = i*videoScale;
      int y = j*videoScale;
      
      // 在像素数组内寻找合适的颜色
      color c = video.pixels[i + j*video.width];
      // 显示字符串中的各个字母来替代矩形
      textFont(f);
      fill(c);
      
      // 文本内的一个字母在像素位置显示并被染色. 
      // 一个计数器变量—— "charcount"被用来每次触发一个字符串内的字母.
      text(chars.charAt(charcount),x,y);
      
      // 继续下一个字母
      charcount = (charcount + 1) % chars.length();
    }
  }
}

21. 让字母根据亮度调整大小,你只需加入以下几行(如果你不想要彩色而只要黑白,那么将关于颜色的几行注释掉即可),不过记得使用createFont()函数创建字体,因为这样创建的字体不会因为缩放而失真:

亮度调整字体大小
亮度调整字体大小

float b = brightness(video.pixels[i + j*video.width]);
float fontSize = 36 * (b / 255);
textSize(fontSize);

虽然能运行成功,但我却持续的得到错误提示:“Thu Dec 3 23:53:34 xxx.local java[431] : CGAffineTransformInvert: singular matrix.”。关于这点,我正在等Daniel回答。

22. 文本同样可以实现位移与旋转:

PFont f;
String message = "这段文本正在旋转";
float theta;

void setup() {
  size(200,200);
  f = createFont("Arial", 20, true);
}

void draw() {
  
  background(255);
  fill(0);
  textFont(f);                 // 设置字体
  translate(width/2,height/2); // 由中点旋转
  rotate(theta);               // 以theta旋转
  textAlign(CENTER) ;
  
  // 在平移和旋转后这段文本居中对齐并显示在(0,0). 
  // 如果你忘了平移和旋转,返回去复习一下吧.
  text(message,0,0); 
  
  // 增加旋转(加 为顺时针)
  theta += 0.05; 
}

23. 是的,如上例可见,p5支持并可正确显示中文,但是它并不允许你在程序中直接输入中文,没事,在文本编辑器里写好再把它们粘贴进去就好了~

24. 如果你要新起一行,可以这么写:

String message = "这是第一行\n这是第二行";

“\”意思是"新的一行"。在Java中,不可见字母可以与一个“转义序列(escape sequence)”一起北河并到一个字符串内——一个斜杠"\"伴随一个字母。以下是一些基本用法:
\n—新的一行
\r—回车
\t—tab
\’—单引号
\”—双引号
\\—斜杠

25. 在一些制图软件中,要求一串文本中每个字符都得独立渲染。在p5中,这样的解决方式是循环一个字符串,每次显示一个字符。

// 第一个字母在位于10个像素的水平位置
int x = 10;   
for (int i = 0; i < message.length(); i++ )  {
  //  使用charAt()函数使每次显示一个字符 
  text(message.charAt(i), x, height/2);
  // 每个字符间间隔10个像素   
  x += 10; 
}

26. 呼叫每个字符的text()函数给了我们之后的例子更多的发挥空间(染色,设置大小,在一个字符串内单独放置字符)。10个像素的间隔不一定准确,因为不一定每个字符的宽度都是10。准确的间隔在下例中由textWidth()实现。注意它是如何在随机字符大小的情况下仍然保持合适的间隔的:

PFont f;   
String message = "oNEwAY是一支来自昆明的后摇滚乐队";   

void setup()  {   
  size(500,200);   
  f = createFont( " Arial " ,12,true);      
}    

void draw()  {  
  background(255);
  fill(0);
  textFont(f,12);  
  int x = 10;   
  for (int i = 0; i < message.length(); i++ )  {   
    textSize(random(12,36));   
    text(message.charAt(i), x, height/2);   
    x += textWidth(message.charAt(i)); 
  }
}

我注意到如果让上边这段代码一直跑的话,最后会停止(因为出错了..),解决办法是,要么你加个noLoop();,要么你把它从draw()里边给整出来:

PFont f;   
String message = "oNEwAY是一支来自昆明的后摇滚乐队";   

size(500,200);   
f = createFont( " Arial " ,12,true);
background(255);
fill(0);
textFont(f,12);  
int x = 10;   
for (int i = 0; i < message.length(); i++ )  {   
  textSize(random(12,36));   
  text(message.charAt(i), x, height/2);   
  x += textWidth(message.charAt(i));    
}

然后我发现在这样的情形下,使用"\n"换行的方式是没用的。

27. 用自适应间隔重做第一个字母马赛克的例子:

import processing.video.*;

// 缩放比例
int videoScale = 16;
// 行数和列数
int cols, rows;
// capture对象
Capture video;

// 一个字符串和字体
String chars = "oNEwAYisapostrockbandfromkunmingyunnanchina";
PFont f;

void setup() {
  size(640, 480);
  //建立行和列
  cols = width/videoScale;
  rows = height/videoScale;
  video = new Capture(this,cols,rows,15);

  // 载入字体
  f = createFont("Arial",18,true);
}

void draw(){ 
  // 从摄像头读取图像
  if (video.available()) {
    video.read(); 
  }
  video.loadPixels();
  //image(video,0,0,width,height);

  background(0);

  // 使用一个计数器
  int charcount = 0;

  // 开始循环行
  for ( int j = 0; j < rows;j++) {
    // 现在开始循环列, 而不是逐一循环像素
    // 我们基于字符宽度使用一个浮点变量x来进行移动
    float x = 0;
    while (x < width) {
      // 我们垂直位置在哪?
      int y = j*videoScale;
      // 我们水平位置在哪? 转化到整数, 缩小, 并确保我们始终位于萤幕内 
      int pix = constrain((int) (x / videoScale),0,cols-1);

      // 在像素数组内选取正确的颜色
      color c = video.pixels[pix+j*video.width]; 

      // 显示字符串中的独立字符
      // 替代矩形
      textFont(f);
      fill(c);
      char ch = chars.charAt(charcount);
      text(ch,x,y);
      // 继续下一个字符, 到最末的时候重新从0开始循环
      charcount = (charcount + 1) % chars.length();
      // 依据字符宽度移动x
      x += textWidth(ch);
    }
  }
}

28. 这种方法同样可以用于各个字符独立运动的案例。下边这个例子使用面向对象得方式制作,让字符串中的每一个字符成为一个对象,使它们既能在适当的位置显示又能在萤幕内独立运动:

PFont f;
String message = "oNEwAY是一支来自云南昆明的后摇滚乐队";

// 字母数组
Letter[] letters;

void setup() {
  size(460,200);
  
  // 载入字体
  f = createFont("Arial", 20, true);
  textFont(f);
  
  // 创建与字符串同样大小的数组
  letters = new Letter[message.length()];
  
  // 在正确的x位置初始化字母
  int x = 66;
  for (int i = 0; i < message.length(); i ++ ) {
    // 字符对象依它们在字符串中的位置及显示初始化
    letters[i] = new Letter(x,100,message.charAt(i)); 
    x += textWidth(message.charAt(i));
  }
}

void draw() {
  background(255);
  for (int i = 0; i < letters.length; i ++ ) {
    
    // 显示全部字符
    letters[i].display();
    
    // 如果鼠标按下,字符开始抖动
    // 如果放开,它们回归原位
    if (mousePressed) {
      letters[i].shake();
    } else {
      letters[i].home();
    }
  }
}

// 一个描述单独字符的类
class Letter {
  char letter;
  
  // 对象知道它最初的位置
  float homex,homey;
  
  // 以及它现在的位置
  float x,y;
  
  Letter(float x_, float y_, char letter_) {
    homex = x = x_;
    homey = y = y_;
    letter = letter_;
  }
  
  // 显示字符
  void display() {
    fill(0);
    textAlign(LEFT);
    text(letter,x,y);
  }
  
  // 随机移动字符
  void shake() {
    x += random(-2,2);
    y += random(-2,2);
  }
  
  // 在任何一点, 通过呼叫home()函数便可将位置从当前重置到最初。
  void home() { 
    x = homex;
    y = homey;
  }
}

29. 这种方法还允许我们将文字附于一个曲线上。在这么做之前,我们先看看如何将一系列矩形附于一个曲线上:

PFont f;

// 圆形的半径
float r = 100;

// 矩形的长、宽
float w = 40;
float h = 40;

void setup() {
  size(320,320);
  smooth();
}

void draw() {
  background(255);
  
  // 从中心开始并画圆
  translate(width/2, height/2);
  noFill();
  stroke(0);
  // 这个圆就是我们的曲线
  ellipse(0, 0, r*2, r*2); 
  // 10个矩形围绕曲线
  int totalBoxes = 10;
  // 我们必须保持记录围绕曲线的位置
  float arclength = 0;
  // 为每个矩形
  for (int i = 0; i < totalBoxes; i ++ ) {
    // 每个盒子都居中,因此我们将它们移动半个身位
    arclength += w/2; 
    
    // 角的弧度等于弧长除以半径
    float theta = arclength / r;
    
    pushMatrix();
    // 极坐标到笛卡尔坐标的转换
    translate(r*cos(theta) , r*sin(theta));
    // 旋转矩形
    rotate(theta);
    
    // 显示矩形
    fill(0, 100);
    rectMode(CENTER);
    rect(0, 0, w, h);
    popMatrix();
    
    // 再次移动半个身位
    arclength += w/2;
  }
}

30. 尽管你觉得这个例子的数学可能有点难,但它的运行结果已经向我们揭示了下一步。我们需要做的只是用字符来填入各个矩形。并且因为每个字符并非同等宽度,所以相对"w"这个常量,我们需要使用一个变量,这个宽度由textWidth()函数得到:

// 被显示的文本
String message = "围绕曲线的汉字们";
PFont f;

// 圆半径
float r = 100;

void setup() {
  size(320,320);
  f = createFont("Georgia",40,true);
  textFont(f);
   // 文本必须居中!
  textAlign(CENTER);
  smooth();
}

void draw() {
  background(255);
  
  // 从中心开始并绘制圆形
  translate(width/2, height/2);
  noFill();
  stroke(0);
  ellipse(0, 0, r*2, r*2);
  
  // 保存位置
  float arclength = 0;
  
  // 为每个字
  for (int i = 0; i < message.length(); i ++ ) {
    
    // 字符及其宽度
    char currentChar = message.charAt(i);
    // 我们查询每个字符的宽度来替代固定的宽度.
    float w = textWidth(currentChar); 
    // 每个字都是居中对齐的,所以我们移动半个身位
    arclength += w/2;
    
    // 角的弧度等于弧长除以半径
    // 通过增加PI由圆形左边开始
    float theta = PI + arclength / r;
    
    pushMatrix();
    
    // 极坐标到笛卡尔坐标的转换允许我们找到沿着曲线的点.
    translate(r*cos(theta), r*sin(theta)); 
    // 旋转文字 (抵消旋转90度)
    rotate(theta + PI/2); 
    
    // 显示文字
    fill(0);
    text(currentChar,0,0);
    
    popMatrix();
    
    // 再次移动半个身位
    arclength += w/2;
  }
}

31. 下边是书里的练习,让随机位置的文本归位,然后继续上边那个例子,鼠标点击,抖动,放开,归位。还要用到一些新函数,哦也,我不会做,直接看答案,慢慢学习吧。。。:

PFont f;
String message = "呼啦啦啊呼啦啦,随机文字们各归其位!";
// 文字对象数组
Letter[] letters;

void setup() {
  size(400, 200);
  // 载入字体
  f = createFont("Georgia",20,true);
  textFont(f);
  
  // 以字符串大小创建数组
  letters = new Letter[message.length()];
  // 在正确的x位置初始化数组
  int x = 30;
  for (int i = 0; i < message.length(); i++) {
    letters[i] = new Letter(x,height/2,message.charAt(i)); 
    x += textWidth(message.charAt(i));
  }
}

void draw() { 
  background(255);
  for (int i = 0; i < letters.length; i++) {
    // Display all letters
    letters[i].display();
    
    // If the mouse is pressed the letters shake
    // If not, they return to their original location
    if (mousePressed) {
      letters[i].shake();
    } else {
      letters[i].home();
    }
  }
}

// A class to describe a single Letter
class Letter {
  char letter;
  // The object knows its original "home" location
  float homex,homey;
  // As well as its current location
  float x,y;
  // And an angle of rotation
  float theta;

  Letter (float x_, float y_, char letter_) {
    homex = x = x_;
    homey = y = y_;
    x = random(width);
    y = random(height);
    theta = random(TWO_PI);
    letter = letter_; 
  }

  // Display the letter
  void display() {
    fill(0);
    textAlign(LEFT);
    // 用户位移和旋转来绘制文字
    pushMatrix();
    translate(x,y);
    rotate(theta);
    text(letter,0,0);
    popMatrix();
  }

  // 随机移动文字
  void shake() {
    x += random(-2,2);
    y += random(-2,2);
    theta += random(-0.5,0.5);
  }

  // 用lerp让文字归位!
  void home() {
    x = lerp(x,homex,0.05);
    y = lerp(y,homey,0.05);
    theta = lerp(theta,0,0.05);
  }
}

lerp()——依一个特殊的增量计算两个数字间的一个数字。参数amt是两个值间的篡改(interpolate)总数,比如,0.0等于第一个值,0.1非常靠近第一个值,0.5在它们之间,等等。lerp函数便于创建直线运动以及绘制点状线。更多
是的,貌似比较难理解,但我想了个笨办法,列印lerp出来的值,然后慢慢去琢磨它的用法。还是挺管用的~

分享给你的网络

ww
ww

14 Comments

  1. 这个博客不错,我也在学习processing,希望多交流。请问你是吧Daniel的书翻译过了吗?

  2. 我想知道怎么显示中文,还有我在网上看到一个小作品,它的字符串似乎不是用String message =..,而似乎是连到外面的文本文档了,StrArray = loadStrings(“affirmations.txt”);
    请麻烦解释解释

    • @Blackburn,
      1. 显示中文没问题,只是在p5环境中不支持中文输入到是真的,因此你只能将中文粘贴进代码中。

      2. 关于读取外部txt文档,请看下一课。

  3. 感谢你的提醒,我已经用creatFont显示出了中文,但是我还是不太明白这个函数,所谓创造字体到底创造在哪里了,还是只是个名称而已,因为我再随意改动这个自造字体的名称,它依然可以显示出打好的中文,是不是也不需要data里的字体文件呢,另外似乎只能显示宋体的样子,这是否可以改呢;第二个问题就是读取外部文档,在代码中我依然用creatFont可是这时候连进来的中文显示的都是一个个小方块,这是怎么回事,当然,如果是loadFont就跟本不显示中文了

    • @Blackburn,
      creatFont()用与字体创建工具同样的方式创建一个位图版本的字体。它依名字载入一个字体,并基于大小创建一系列的图像。在可能的情况下,函数text()将使用本地字体而不是创建的本地位图字体。例如,当使用默认渲染设置(JAVA2D)时,将使用本地字体,以提升绘图质量和性能。使用P2D,P3D和OPENGL渲染设置时,将使用位图版本。

      PFont.list()可以查看所有可用的字体。理论上来说,能被列印出来的字体都是可用的。但由于Java的局限性,有时并非所有字体都可用,或者某些系统可用而其他系统却不可用。

      loadStrings()创建的是一个字符串数组(每行为一个字符串形式的元素),用它读取txt文档后,用join()整合这个数组为一个长字符串后再输出看结果。

      例如:
      String[] lines = loadStrings(“text.txt”);
      String onelongstring = join (lines, “”);
      text(onelongstring,x,y);

  4. 我还是不会整合,因为我分不清你的例子哪个是函数哪个是名称,orz另外我不只要连接外部文本,还要根据外部文本的行数将字体随机显示在屏幕上,如果你有q的话希望可以把源文件传给你再看

    • @blackburn,
      学到现在,你应该知道函数在P5内是以棕色高亮显示的,如果连这点都还不知道,那还是建议你从基础学起,不要急于求成。

  5. 您好,“习题17-6,做一个接头接尾持续滚动的文本条。” 您现在有进展么?我想了好久想不出来,能请教一下吗?

Leave a Reply

Your email address will not be published. Required fields are marked *