我正在创建一种消息传递程序,用户可以在其中发送消息。我希望看起来像任何社交消息应用程序,其中最近收到的消息显示在屏幕的底部,之前的消息显示在上面(较旧的消息显示在较高的位置)。有没有办法将消息(String)打印到终端中的特定行或底线?
Mac OS x
答案 0 :(得分:-1)
哦,昔日的日子!我记得当每个想成为巫师的乡村小伙子都知道他的ANSI控制代码时。当然,这些字节序列允许知识中的一个产生令人敬畏的视觉和文本显示上的异国情调的鲜艳色彩,较少的人认为只是哑终端。
但日子一去不复返了,我们有高分辨率显示器和3D图形,鼠标和触摸屏。时间到了,你老傻瓜!可是等等!在每个终端窗口的核心,(我们现在不谈论Windows)有一个旧的VT100终端的金色心脏。所以,是的,可以使用Java控制台输出控制光标位置和滚动区域。
这个想法是,终端不是那么倾倒。它只等待转义序列让你告诉它应该做什么特别的事情。说明以转义字符开头,它是不可打印的ASCII字符27,通常用十六进制0x1b
或八进制033
编写。之后会出现一些人类可读的东西,通常包括[
,一些数字信息和一个字母。如果需要更多数字,则用分号分隔。
例如,要将字体颜色更改为红色,请输出序列<ESC>[31m
,如下所示:
System.out.println("\033[31mThis should appear red");
您最好打开一个单独的终端窗口来摆弄代码,因为显示屏很容易出现乱码。实际上,shell提示符和目录列表的颜色是通过这些代码实现的,并且可以轻松地进行个性化。
如果你想将窗口顶部和底部的区域与滚动区分开来,可以使用<ESC>[<top>;<bottom>r
代码来自顶部和底部,在滚动发生的位置之间,实例:\033[2;22r
<强>链接:强>
当然,如果不运行代码,答案就不是答案。对?我不得不承认我对此并没有带走。虽然将Java用于终端序列感觉很奇怪。 K&amp; R C或COMMODORE BASIC会更合适。我做了非常简单的演示,但是将打印速度降低到与旧1200波特调制解调器相同的水平,因此您可以轻松地观察到发生了什么。将SPEED
设置为0以禁用。
转义序列与HTML文本格式化标记的标记类型相同,而且最好的 BLINK 仍在那里!
另存为TerminalDemo.java
,使用javac TerminalDemo.java
进行编译并使用命令运行:java TerminalDemo
import java.io.*;
public class TerminalDemo {
// Default speed in bits per second for serial line simulation
// Set 0 to disable
static final int SPEED = 1200;
// ANSI Terminal codes
static final String ESC = "\033";
static String clearScreen() { return "\033[2J"; }
static String cursorHome() { return "\033[H"; }
static String cursorTo(int row, int column) {
return String.format("\033[%d;%dH", row, column);
}
static String cursorSave() { return "\033[s"; }
static String cursorRestore() { return "\033[u"; }
static String scrollScreen() { return "\033[r"; }
static String scrollSet(int top, int bottom) {
return String.format("\033[%d;%dr", top, bottom);
}
static String scrollUp() { return "\033D"; }
static String scrollDown() { return "\033D"; }
static String setAttribute(int attr) {
return String.format("\033[%dm", attr);
}
static final int ATTR_RESET = 0;
static final int ATTR_BRIGHT = 1;
static final int ATTR_USCORE = 4;
static final int ATTR_BLINK = 5;
static final int ATTR_REVERSE = 7;
static final int ATTR_FCOL_BLACK = 30;
static final int ATTR_FCOL_RED = 31;
static final int ATTR_FCOL_GREEN = 32;
static final int ATTR_FCOL_YELLOW = 33;
static final int ATTR__BCOL_BLACK = 40;
static final int ATTR__BCOL_RED = 41;
static final int ATTR__BCOL_GREEN = 42;
public static void main(String[] args) {
// example string showing some text attributes
String s = "This \033[31mstring\033[32m should \033[33mchange \033[33m color \033[41m and start \033[5m blinking!\033[0m Isn't that neat?\n";
// Reset scrolling, clear screen and bring cursor home
System.out.print(clearScreen());
System.out.print(scrollScreen());
// Print example string s
slowPrint(s);
// some text attributes
slowPrint("This "
+ setAttribute(ATTR_USCORE) + "should be undescored\n"
+ setAttribute(ATTR_RESET)
+ setAttribute(ATTR_FCOL_RED) + "and this red\n"
+ setAttribute(ATTR_RESET)
+ "some "
+ setAttribute(ATTR_BRIGHT)
+ setAttribute(ATTR_FCOL_YELLOW)
+ setAttribute(ATTR_BLINK) + "BRIGHT YELLOW BLINKIN\n"
+ setAttribute(ATTR_RESET)
+ "could be fun.\n\n"
+ "Please press ENTER");
// Wait for ENTER
try { System.in.read(); } catch(IOException e) {e.printStackTrace();}
// Set scroll area
slowPrint(""
+ clearScreen()
+ scrollSet(2,20)
+ cursorTo(1,1)
+ "Cleared screen and set scroll rows Top: 2 and Bottom: 20\n"
+ cursorTo(21,1)
+ "Bottom area starts here"
+ cursorTo(2,1)
+ "");
// print some random text
slowPrint(randomText(60));
// reset text attributes, reset scroll area and set cursor
// below scroll area
System.out.print(setAttribute(ATTR_RESET));
System.out.print(scrollScreen());
System.out.println(cursorTo(22,1));
}
// Slow things down to resemble old serial terminals
private static void slowPrint(String s) {
slowPrint(s, SPEED);
}
private static void slowPrint(String s, int bps) {
for (int i = 0; i < s.length(); i++) {
System.out.print(s.charAt(i));
if(bps == 0) continue;
try { Thread.sleep((int)(8000.0 / bps)); }
catch(InterruptedException ex)
{ Thread.currentThread().interrupt(); }
}
}
// Retursn a character representation of sin graph
private static String randomText(int lines) {
String r = "";
for(int i=0; i<lines; i++) {
int sin = (int)Math.abs((Math.sin(1.0/20 * i)*30));
r += setAttribute((sin / 4) + 30);
for(int j=0; j<80; j++) {
if(j > 40 + sin)
break;
r += (j < (40-sin)) ? " " : "X";
}
r += setAttribute(ATTR_RESET) + "\n";
}
return r;
}
}