昨天发布的文本编辑器Quickpad-1.2我还有很多地方不满意的,比如控制台没有实现键盘输入功能,今天本想解决这个问题,没想到做成了一个山寨版的Windows命令提示符。
MyConsole的效果如下
下面将代码贴出来,以作备忘。
MyConsole.java
package com.jison.MyConsole;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/**
* 命令提示符的外壳程序
* @version MyConsole-1.0
* @author jison
* @email jisonami@163.com
* @time 2015-1-30
*/
public class MyConsole {
/**
* MyConsole主窗体
*/
private JFrame jf = new JFrame("MyConsole");
/**
* MyConsole的终端文本区
*/
private JTextArea consoleTextArea = new JTextArea();
/**
* 将终端文本区加入到JScrollPane
*/
private JScrollPane jScrollPane = new JScrollPane(consoleTextArea);
/**
* 设置默认字体为等宽字体
*/
private final Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 13);
/**
* 控制器对象
*/
private MyConsoleControl myConsoleControl;
/**
* 程序入口
* @param args
*/
public static void main(String[] args){
new MyConsole();
}
public MyConsole(){
//初始化UI
this.setMyConsoleUI();
//创建键盘监听
this.createKeyListener();
//获取当前路径
String nowPath = (new File(".")).getAbsolutePath();
nowPath = nowPath.substring(0, nowPath.length()-2);
//设置当前路径
MyConsoleDto.getMyConsoleDto().setNowPath(nowPath);
//获取终端控制器
myConsoleControl = new MyConsoleControl();
//读取运行cmd命令的信息
String[] cmdArray = new String[3];
cmdArray[0] = "cmd";
cmdArray[1] = "/c";
cmdArray[2] = "cmd";
myConsoleControl.execCmdThread(cmdArray, 300, consoleTextArea);
}
private void setMyConsoleUI(){
//设置终端文本区的字体和颜色
consoleTextArea.setBackground(Color.BLACK);
consoleTextArea.setForeground(Color.LIGHT_GRAY);
consoleTextArea.setFont(DEFAULT_FONT);
consoleTextArea.setCaretColor(Color.LIGHT_GRAY);
//设置终端文本区自动换行
consoleTextArea.setLineWrap(true);
//垂直滚动条需要时自动出现
jScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jf.add(jScrollPane);
jf.setSize(680, 450);
FrameUtil.setFrameCenter(jf);
//设置窗口的默认关闭操作,退出应用程序
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setVisible(true);
}
/**
* 对consoleTextArea创建键盘监听
*/
private void createKeyListener(){
consoleTextArea.addKeyListener(new KeyListener(){
@Override
public void keyReleased(KeyEvent e) {
//保护consoleText已打印文本信息不受编辑
myConsoleControl.protectHasPrintText(consoleTextArea);
if(e.getKeyCode()==KeyEvent.VK_ENTER) {
//回车键释放时的操作
//获取已打印的文本
String hasPrintText = MyConsoleDto.getMyConsoleDto().getStrConsoleText();
//读取当前文本
String nowConsoleText = consoleTextArea.getText();
//执行当前输入的命令
if(nowConsoleText.length()>hasPrintText.length()){
//获取当前输入的命令
String cmdStr = nowConsoleText.substring(hasPrintText.length()).trim();
//给每条命令加入"cmd /c"的前缀
cmdStr = "cmd /c "+cmdStr;
//以空格截取输入命令的cmdArray
String[] cmdArray = cmdStr.split(" ");
//执行刚刚输入命令
myConsoleControl.execCmdThread(cmdArray, 30000, consoleTextArea);
}
}
}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {}
});
}
}
MyConsoleControl.java
package com.jison.MyConsole;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.text.Document;
/**
* 处理控制台显示的信息
* @author jison
* @email jisonami@163.com
* @time 2015-1-30
*/
public class MyConsoleControl {
/**
* 对cd等切换目录的特殊命令的处理
* @param cmdArray
*/
public void execCdChange(String[] cmdArray){
//获取当前根目录
String nowRootDir = MyConsoleDto.getMyConsoleDto().getNowRootDir();
//当前要切换的目录
File dir = null;
//对cd命令进行特殊处理
if(cmdArray[2].equals("cd")){
//如果命令数组的长度为4,表明cd命令输入了目录
if(cmdArray.length==4){
dir = new File(nowRootDir + cmdArray[3]);
}
}
//切换根驱动器命令
if(cmdArray[2].length()==2 && cmdArray[2].charAt(1)==':'){
dir = new File(cmdArray[2]);
}
//记录当前目录和上一个目录
if(dir!=null && dir.exists() && dir.isDirectory()){
//将当前目录记录为上一个目录
MyConsoleDto.getMyConsoleDto().setPrePath(MyConsoleDto.getMyConsoleDto().getNowPath());
//将dir记录为当前目录
MyConsoleDto.getMyConsoleDto().setNowPath(dir.toString());
}
}
/**
* 保护已打印文本不受编辑
*/
public void protectHasPrintText(JTextArea consoleTextArea){
//获取已打印的文本
String hasPrintText = MyConsoleDto.getMyConsoleDto().getStrConsoleText();
//读取当前终端文本
String nowConsoleText = consoleTextArea.getText();
//如果当前终端文本的长度小于已打印文本的长度
if(consoleTextArea.getText().length()<hasPrintText.length()){
//恢复已打印的文本
consoleTextArea.setText(hasPrintText);
}
//键盘输入的位置不在‘>’字符之后
if(consoleTextArea.getText().charAt(hasPrintText.length()-1)!='>'){
//恢复已打印的文本
consoleTextArea.setText(hasPrintText);
}
}
/**
* 以追加的方式打印当前目录信息到consoleTextArea
*/
public void printDirInfo(JTextArea consoleTextArea){
String nowPath = MyConsoleDto.getMyConsoleDto().getNowPath();
consoleTextArea.append(nowPath+">");
//记录当前consoleTextArea的文本
MyConsoleDto.getMyConsoleDto().setStrConsoleText(consoleTextArea.getText());
//将光标移动到最后
consoleTextArea.setCaretPosition(consoleTextArea.getText().length());
}
/**
* 在限制时间内执行cmdArray命令
* @param cmdArray 命令数组
* @param time 时间单位为微秒
*/
public void execCmdThread(String[] cmdArray, int time, JTextArea consoleTextArea){
//如果输入的命令为exit,则退出整个程序
if(cmdArray[2].equals("exit")){
System.exit(0);
}
//启动新的线程执行一条命令
Thread cmdThread = new Thread(new Runnable(){
@Override
public void run() {
outputCapture(cmdArray, consoleTextArea);
}
});
cmdThread.start();
try {
cmdThread.join(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
//对cd等切换目录的特殊命令的处理
execCdChange(cmdArray);
//插入一个换行符
if(!cmdArray[2].equals("cmd")){
consoleTextArea.append("\n");
}
//打印当前目录信息
printDirInfo(consoleTextArea);
}
/**
* 捕捉cmdArray命令的控制台输出
* @param cmdArray
*/
public void outputCapture(String[] cmdArray, JTextArea consoleTextArea){
Process process = null;
try {
File dir = new File(MyConsoleDto.getMyConsoleDto().getNowPath());
// 启动命令行指定程序的新进程
process = Runtime.getRuntime().exec(cmdArray, null, dir);
}
catch(IOException e) {
System.err.println("创建进程时出错...\n" + e);
System.exit(1);
}
// 获得新进程所写入的流
InputStream[] inStreams = new InputStream[] {process.getInputStream(),
process.getErrorStream()};
//将终端信息追加到consoleTextArea
this.toTextArea(consoleTextArea, inStreams);
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 在jTextArea上显示传入的InputStream数组的信息
* @param jTextArea 显示信息的文本区域
* @param inStreams 传入要显示的InputStream数组的信息
*/
public void toTextArea(JTextArea jTextArea, InputStream[] inStreams){
for(int i = 0; i < inStreams.length; ++i){
startConsoleReaderThread(jTextArea, inStreams[i]);
}
}
/**
* 单独启用一个线程对控制台信息的处理
* @param jTextArea
* @param inputStream
*/
private void startConsoleReaderThread(JTextArea jTextArea,
InputStream inputStream) {
final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
new Thread(new Runnable() {
public void run() {
StringBuffer sb = new StringBuffer();
try {
String s;
Document doc = jTextArea.getDocument();
while((s = br.readLine()) != null) {
boolean caretAtEnd = false;
caretAtEnd = jTextArea.getCaretPosition() == doc.getLength() ?
true : false;
sb.setLength(0);
jTextArea.append(sb.append(s).append('\n').toString());
if(caretAtEnd)
jTextArea.setCaretPosition(doc.getLength());
}
}
catch(IOException e) {
JOptionPane.showMessageDialog(null,
"从BufferedReader读取错误:" + e);
System.exit(1);
}
}
}).start();
}
}
MyConsoleDto.java
package com.jison.MyConsole;
/**
* 数据传输对象
* @author jison
* @email jisonami@163.com
* @time 2015-1-30
*/
public class MyConsoleDto {
/**
* 使用单例模式设计
*/
private static MyConsoleDto myConsoleDto;
/**
* 保存当前consoleTextArea的所有文本
*/
private String strConsoleText;
/**
* 记录当前的根目录
*/
private String nowRootDir;
/**
* 记录当前命令行打开的目录
*/
private String nowPath;
/**
* 记录前一个目录
*/
private String prePath;
/**
* 通过静态方法返回唯一实例
* @return
*/
public static MyConsoleDto getMyConsoleDto(){
if(myConsoleDto==null){
myConsoleDto = new MyConsoleDto();
}
return myConsoleDto;
}
/**
* 其余所有值的getter和setter方法
*/
public String getStrConsoleText() {
return strConsoleText;
}
public void setStrConsoleText(String strConsoleText) {
this.strConsoleText = strConsoleText;
}
public String getNowPath() {
return nowPath;
}
public void setNowPath(String nowPath) {
this.nowPath = nowPath;
}
public String getPrePath() {
return prePath;
}
public void setPrePath(String prePath) {
this.prePath = prePath;
}
public String getNowRootDir() {
this.setNowRootDir(this.nowPath.substring(0, 2));
return nowRootDir;
}
public void setNowRootDir(String nowRootDir) {
this.nowRootDir = nowRootDir;
}
}
FrameUtil.java
package com.jison.MyConsole;
import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;
/**
* 使JFrame窗口居中显示
* @author jison
* @email jisonami@163.com
* @time 2015-1-30
*/
public class FrameUtil {
public static void setFrameCenter(JFrame jf){
//使窗口居中显示
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screen = toolkit.getScreenSize();
//先乘除,后加减,再位移
int x = (screen.width-jf.getWidth()) >> 1;
int y = (screen.height-jf.getHeight() >> 1)-16;
jf.setLocation(x,y);
}
}
没了,以上就是全部的代码了。
- 大小: 49.6 KB
分享到:
相关推荐
使用`Runtime.exec()` `Runtime.exec()`是最为传统且简单的执行外部程序的方法。它可以启动一个新的进程,并返回一个代表该进程的`Process`对象。但是,这种方法在处理进程的输入/输出流时存在一定的局限性。 **...
Java.lang.Runtime.exec() 方法是 Java 语言中用于执行操作系统命令的方法,它可以将参数传递给命令,并执行命令以获取结果。但是,在使用该方法时,需要注意一些重要的知识点,以避免出现问题。 命令参数中不能...
`Runtime.exec(String command)`方法用于执行单个命令,而如果需要执行包含多个命令的shell脚本,可以使用`Runtime.exec(String[] cmdArray)`,其中cmdArray是一个包含命令及其参数的字符串数组。 下面是一个简单的...
完美解决runtime.exec()执行进程block死锁以及为waitFor设置超时 不需要耗cpu的循环判断exitValue==0 开两个进程搞定
如果遇到无法删除的问题,可以尝试使用`Runtime.exec()`调用`del`命令强制删除文件。 在实际编程中,处理这些细节能够确保Java程序在Windows环境中正确地调用命令行操作。同时,为了提高代码的可维护性和可读性,...
halcon-17.12.0.0-windows-runtime.exe
windows环境下IDEA java代码Runtime.getRuntime.exec中shell的执行环境的解决方案前言解决办法后记 前言 在使用IDEA本地开发监控守护线程的后台,我遇上了执行环境不兼容的问题,爆出各种“xxx不是内部或外部命令,...
System.Runtime.InteropServices.WindowsRuntime 是.NET Framework和.NET Core中的一个关键组件,它主要负责提供与Windows运行时(WinRT)API的互操作性。在涉及到蓝牙相关的开发时,这个库扮演着重要的角色,允许C#...
在Java编程语言中,`Runtime`类是每个Java应用程序都有的一个实例,它提供了与运行时环境交互的方法。当我们需要在Java程序中执行系统命令,比如运行一个批处理脚本(.bat文件)时,`Runtime`类或者其扩展类`...
根据提供的文件信息,本文将详细解析与“Java控制命令提示符”相关的知识点,包括如何在Java程序中执行操作系统命令、具体实现方式以及可能遇到的问题和解决办法。 ### 一、Java程序调用操作系统命令的基本原理 ...
1,申请root权限Runtime.getRuntime().exec("su"); 2,通过数据输出流DataOutputStream写入pm install命令; 3,最后获取Process进程的返回值int i = process.waitFor();,如果i=0,则表明已获取root权限。
java.lang.Runtime 类是 Java 语言中一个非常重要的类,它提供了访问当前 Java 应用程序的 Runtime 环境的能力。每个 Java 应用程序都有一个 Runtime 类实例,使应用程序能够与其运行的环境相连接。 概述: ...
如果用Maven获取,当配置稍有问题,也不能...如需在生产环境中使用ArcGIS Runtime SDK for Java,请联系ESRI公司获得授权,现在也有国产替代产品GeoScne Runtime SDK for Java,可以联系易智瑞公司获得相关资源和授权。
Esri.ArcGISRuntime.100.3.0.nupkg Esri.ArcGISRuntime.LocalServices.100.3.0.nupkg Esri.ArcGISRuntime.Hydrography.100.3.0.nupkg Esri.ArcGISRuntime.UWP.100.3.0.nupkg Esri.ArcGISRuntime.Xamarin.Forms.100.3...
1. DataContractSerializer:这是.NET Framework 3.0引入的一个高性能的序列化器,主要用于WCF(Windows Communication Foundation)服务。通过定义数据契约(DataContract),我们可以指定哪些字段或属性应该参与...
下面是一个简单的示例,展示如何使用`Runtime.exec()`来调用DOS命令`ipconfig`: ```java import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; public class ...
Java Runtime Environment(JRE)是Java程序运行所需的基础组件,它是Oracle公司提供的Java平台标准版(Java SE)的一部分。在本例中,我们讨论的是64位版本的JRE 1.8.0,适用于Windows操作系统。这个版本的JRE包含...