如何在Processing中使用for循环将句子居中显示在画布上
Processing:实现句子按单词拆分并居中显示
问题描述
我还在学习阶段,想要实现输入新句子时,将句子按单词拆分并居中显示在Processing画布上。尝试用for循环,但没法确定循环里怎么设置X、Y坐标来完成单词拆分和居中;手动拆分单词的话,更新新句子时会出错。以下是我当前的代码:
import javax.swing.JOptionPane; String Answer; // 存储输入答案 String Secret = "Sponge"; // 正确答案 int textposX, textposY; // 文本的X、Y坐标 final int ansBoxHeight = 50; // 答案输入框高度 final int ansBoxWidth = 200; // 答案输入框宽度 int boxPosX, boxPosY; // 答案输入框的X、Y坐标 String riddle = "WHAT IS: FULL OF HOLES BUT STILL HOLDS WATER, WHAT AM I?"; void setup() { size(500, 500); textposX = width/2; textposY = height/2; textAlign(CENTER, CENTER); // 先设置文本对齐方式,方便居中 } void draw() { background(255); // 每次绘制清空背景,避免重叠 answerBox(); riddle(); answerComparison(); } void riddle() { fill(0); textSize(24); // 调整字号避免超出画布 // 原错误循环:重复绘制整个句子,没有拆分单词 for (int textposX = 0; textposX<=450; textposX = textposX+120) { for (int textposY = 0; textposY>=450; textposY = textposY+100) { text(riddle, textposX, textposY); } } // 手动拆分的代码,更新句子时需要修改多处,扩展性差 //text("WHAT IS:", textposX-100, textposY-200); //text("FULL OF HOLES", textposX-150, textposY-90); //text("BUT", textposX-50, textposY-50); //text("STILL HOLDS", textposX-130, textposY-10); //text("WATER?", textposX-70, textposY+30); //text("WHAT AM I;", textposX-110, textposY+120); } void answerBox() { noFill(); rect(150, 440, ansBoxWidth, ansBoxHeight); // 简化坐标计算,boxPosX/Y初始为0,可直接写数值 // 修正鼠标点击范围判断:原逻辑错误,把宽高加反了 if (mouseX > 150 && mouseX < 150 + ansBoxWidth && mouseY > 440 && mouseY < 440 + ansBoxHeight && mousePressed) { noLoop(); Answer = JOptionPane.showInputDialog("请输入答案:"); loop(); // 重新开启绘制循环 } } void answerComparison() { if (Answer != null && Secret.equalsIgnoreCase(Answer)) { // 避免空指针,忽略大小写匹配 background(0); fill(255); text("答对了!", width/2, height/2); } }
解决方案
要实现动态拆分单词并居中,核心是利用字符串拆分和文本宽度计算来自动定位坐标,以下是修改后的关键代码和逻辑:
修改后的完整代码
import javax.swing.JOptionPane; String Answer; String Secret = "Sponge"; final int ansBoxHeight = 50; final int ansBoxWidth = 200; String riddle = "WHAT IS: FULL OF HOLES BUT STILL HOLDS WATER, WHAT AM I?"; float lineHeight = 30; // 行间距,根据字号调整 void setup() { size(500, 500); textAlign(CENTER, CENTER); } void draw() { background(255); answerBox(); drawCenteredSplitText(riddle, width/2, height/2 - 100, 24); // 调用拆分居中绘制函数 answerComparison(); // 显示输入的答案 if (Answer != null) { fill(0); textSize(20); text(Answer, width/2, 465); } } // 核心函数:拆分句子为单词,居中显示 void drawCenteredSplitText(String text, float centerX, float startY, float fontSize) { fill(0); textSize(fontSize); textAlign(LEFT, CENTER); // 临时设置左对齐,方便逐个绘制单词 String[] words = split(text, " "); // 按空格拆分单词 float totalWidth = 0; // 计算所有单词(含空格)的总宽度 for (String word : words) { totalWidth += textWidth(word + " "); // 每个单词后加空格,计算总宽度 } float currentX = centerX - totalWidth/2; // 起始X坐标,实现水平居中 float currentY = startY; // 逐个绘制单词 for (String word : words) { text(word, currentX, currentY); currentX += textWidth(word + " "); // 更新X坐标到下一个单词位置 // 可选:如果一行放不下,自动换行(这里简单判断,可根据需求优化) if (currentX + textWidth(word) > width - 20) { currentX = centerX - totalWidth/2; currentY += lineHeight; } } textAlign(CENTER, CENTER); // 恢复全局对齐方式 } void answerBox() { noFill(); rect(150, 440, ansBoxWidth, ansBoxHeight); if (mouseX > 150 && mouseX < 150 + ansBoxWidth && mouseY > 440 && mouseY < 440 + ansBoxHeight && mousePressed) { noLoop(); String newRiddle = JOptionPane.showInputDialog("输入新句子:"); if (newRiddle != null && !newRiddle.isEmpty()) { riddle = newRiddle; // 更新句子 } Answer = JOptionPane.showInputDialog("请输入答案:"); loop(); } } void answerComparison() { if (Answer != null && Secret.equalsIgnoreCase(Answer)) { background(0); fill(255); textSize(30); text("答对了!", width/2, height/2); } }
关键逻辑说明
- 拆分单词:用
split(text, " ")将句子拆分为单词数组,支持任意句子动态更新 - 水平居中计算:先遍历所有单词计算总宽度,再通过
centerX - totalWidth/2得到起始X坐标,确保整体水平居中 - 逐词绘制:循环遍历单词数组,逐个绘制并更新X坐标,自动处理单词间距
- 可选换行:判断当前X坐标是否超出画布,自动换行并保持垂直居中
- 修复原代码问题:修正了输入框鼠标点击范围错误、空指针异常、文本重叠等问题
内容的提问来源于stack exchange,提问作者Jrishi_del14
相关产品推荐
相关产品推荐

