Хорошо, я думаю, что могу теперь ответить на свой собственный вопрос. Вот реализация в качестве примера для вычисления квадрата числа на сервере. Сообщите мне, существуют ли какие-либо улучшения или неправильные представления.
файл сервера Python:
import threading
import webbrowser
import BaseHTTPServer
import SimpleHTTPServer
FILE = 'frontend.html'
PORT = 8080
class TestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
"""The test example handler."""
def do_POST(self):
"""Handle a post request by returning the square of the number."""
length = int(self.headers.getheader('content-length'))
data_string = self.rfile.read(length)
try:
result = int(data_string) ** 2
except:
result = 'error'
self.wfile.write(result)
def open_browser():
"""Start a browser after waiting for half a second."""
def _open_browser():
webbrowser.open('http://localhost:%s/%s' % (PORT, FILE))
thread = threading.Timer(0.5, _open_browser)
thread.start()
def start_server():
"""Start the server."""
server_address = ("", PORT)
server = BaseHTTPServer.HTTPServer(server_address, TestHandler)
server.serve_forever()
if __name__ == "__main__":
open_browser()
start_server()
... и файл HTML (я называю его 'frontend.html', к сожалению, имя должно появиться в коде JavaScript также):
AJAX test
, Конечно, было бы намного более удобно использовать jQuery для запроса XML, но в интересах простоты я оставлю его как этот.
Наконец альтернативная реализация с помощью WSGI (к сожалению, я не видел способ возвратиться к стандартному служащему файлу обработчику, если запрос не является POST):
import threading
import webbrowser
from wsgiref.simple_server import make_server
FILE = 'frontend.html'
PORT = 8080
def test_app(environ, start_response):
if environ['REQUEST_METHOD'] == 'POST':
try:
request_body_size = int(environ['CONTENT_LENGTH'])
request_body = environ['wsgi.input'].read(request_body_size)
except (TypeError, ValueError):
request_body = "0"
try:
response_body = str(int(request_body) ** 2)
except:
response_body = "error"
status = '200 OK'
headers = [('Content-type', 'text/plain')]
start_response(status, headers)
return [response_body]
else:
response_body = open(FILE).read()
status = '200 OK'
headers = [('Content-type', 'text/html'),
('Content-Length', str(len(response_body)))]
start_response(status, headers)
return [response_body]
def open_browser():
"""Start a browser after waiting for half a second."""
def _open_browser():
webbrowser.open('http://localhost:%s/%s' % (PORT, FILE))
thread = threading.Timer(0.5, _open_browser)
thread.start()
def start_server():
"""Start the server."""
httpd = make_server("", PORT, test_app)
httpd.serve_forever()
if __name__ == "__main__":
open_browser()
start_server()
Взгляните на Groovy Console . Вот как это выглядит:
Консоль Groovy http://groovy.codehaus.org/download/attachments/36800/GroovyConsole.gif
Хотя это консоль для Groovy, а не произвольные команды, вы должны иметь возможность адаптировать идеи и / или код из него, чтобы получить то, что вам нужно.
Если я правильно понимаю ваш вопрос, вы хотите выполнять команды, специфичные для вашего приложения. Я бы посоветовал, если это действительно так, использовать два текстовых поля, одно из которых состоит из одной строки, а другое занимает остальное пространство. Добавьте несколько обработчиков событий нажатия клавиш в маленький, который можно будет редактировать, а другой сделайте доступным только для чтения.
Попробуйте этот код:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
*
* @author Alistair
*/
public class Console extends JPanel implements KeyListener {
private static final long serialVersionUID = -4538532229007904362L;
private JLabel keyLabel;
private String prompt = "";
public boolean ReadOnly = false;
private ConsoleVector vec = new ConsoleVector();
private ConsoleListener con = null;
private String oldTxt = "";
private Vector history = new Vector();
private int history_index = -1;
private boolean history_mode = false;
public Console() {
super();
setSize(300, 200);
setLayout(new FlowLayout(FlowLayout.CENTER));
keyLabel = new JLabel("");
setFocusable(true);
keyLabel.setFocusable(true);
keyLabel.addKeyListener(this);
addKeyListener(this);
add(keyLabel);
setVisible(true);
}
public void registerConsoleListener(ConsoleListener c) {
this.con = c;
}
public String getPrompt() {
return this.prompt;
}
public void setPrompt(String s) {
this.prompt = s;
}
private void backspace() {
if (!this.vec.isEmpty()) {
this.vec.remove(this.vec.size() - 1);
this.print();
}
}
@SuppressWarnings("unchecked")
private void enter() {
String com = this.vec.toString();
String return$ = "";
if (this.con != null) {
return$ = this.con.receiveCommand(com);
}
this.history.add(com);
this.vec.clear();
if (!return$.equals("")) {
return$ = return$ + "<br>";
}
// <HTML> </HTML>
String h = this.keyLabel.getText().substring(6, this.keyLabel.getText().length() - 7);
this.oldTxt = h.substring(0, h.length() - 1) + "<BR>" + return$;
this.keyLabel.setText("<HTML>" + this.oldTxt + this.prompt + "_</HTML>");
}
private void print() {
this.keyLabel.setText("<HTML>" + this.oldTxt + this.prompt + this.vec.toString() + "_</HTML>");
this.repaint();
}
@SuppressWarnings("unchecked")
private void print(String s) {
this.vec.add(s);
this.print();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
this.handleKey(e);
}
private void history(int dir) {
if (this.history.isEmpty()) {
return;
}
if (dir == 1) {
this.history_mode = true;
this.history_index++;
if (this.history_index > this.history.size() - 1) {
this.history_index = 0;
}
// System.out.println(this.history_index);
this.vec.clear();
String p = (String) this.history.get(this.history_index);
this.vec.fromString(p.split(""));
} else if (dir == 2) {
this.history_index--;
if (this.history_index < 0) {
this.history_index = this.history.size() - 1;
}
// System.out.println(this.history_index);
this.vec.clear();
String p = (String) this.history.get(this.history_index);
this.vec.fromString(p.split(""));
}
print();
}
private void handleKey(KeyEvent e) {
if (!this.ReadOnly) {
if (e.getKeyCode() == 38 | e.getKeyCode() == 40) {
if (e.getKeyCode() == 38) {
history(1);
} else if (e.getKeyCode() == 40 & this.history_mode != false) {
history(2);
}
} else {
this.history_index = -1;
this.history_mode = false;
if (e.getKeyCode() == 13 | e.getKeyCode() == 10) {
enter();
} else if (e.getKeyCode() == 8) {
this.backspace();
} else {
if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
this.print(String.valueOf(e.getKeyChar()));
}
}
}
}
}
}
class ConsoleVector extends Vector {
private static final long serialVersionUID = -5527403654365278223L;
@SuppressWarnings("unchecked")
public void fromString(String[] p) {
for (int i = 0; i < p.length; i++) {
this.add(p[i]);
}
}
public ConsoleVector() {
super();
}
@Override
public String toString() {
StringBuffer s = new StringBuffer();
for (int i = 0; i < this.size(); i++) {
s.append(this.get(i));
}
return s.toString();
}
}
public interface ConsoleListener {
public String receiveCommand(String command);
}
Он использует JPanel как панель и JLabel как консоль. Команды передаются в объект CommandListener, а возвращаемое значение выводится на консоль.
Вы можете выполнять произвольные команды с Plexus, используя командную строку. Он обрабатывает экранирование аргументов, выполнение в зависимости от среды и позволяет вам присоединять потребителей к stdout и stderr, позволяя вам сосредоточиться на обработке.
Вот ссылка на другой ответ r, который я дал, показывая как настроить командную строку и обработать вывод.
Я бы не стал пробовать сочетания клавиш (например, groovy / beanshell), если они точно не соответствуют вашим потребностям. Попытка заставить высокоуровневый инструмент делать то, что вы хотите, когда это не то, что он уже делает, может быть самым неприятным в программировании.
Должно быть довольно легко взять текстовую область и «сделать ее своей собственной», но было бы намного проще сделать так, как предложил кто-то другой, и использовать однострочный текстовый элемент управления в сочетании с многострочным отображением.
В любом случае вы хотите сохранить довольно жесткий контроль над всей системой, перехватить и отфильтровать некоторые нажатия клавиш, отключите ввод в область «Дисплей», если вы решите пойти с этим, нажмите с усилием в области отображения, чтобы направить фокус на поле ввода, ...
Если вы сделаете одно поле, вы '
BeanShell предоставляет JConsole, консоль ввода командной строки со следующими функциями:
JAR-файлы BeanShell доступны по адресу http://www.beanshell.org/download .html , а исходный код доступен через SVN с svn co http://ikayzo.org/svn/beanshell
Для получения дополнительной информации о JConsole см. http://www.beanshell.org /manual/jconsole.html
Вот пример использования BeanShell JConsole в вашем приложении:
import java.awt.Color;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import javax.swing.JFrame;
import bsh.util.GUIConsoleInterface;
import bsh.util.JConsole;
/**
* Example of using the BeanShell project's JConsole in
* your own application.
*
* JConsole is a command line input console that has support
* for command history, cut/copy/paste, a blinking cursor,
* command completion, Unicode character input, coloured text
* output and comes wrapped in a scroll pane.
*
* For more info, see http://www.beanshell.org/manual/jconsole.html
*
* @author tukushan
*/
public class JConsoleExample {
public static void main(String[] args) {
//define a frame and add a console to it
JFrame frame = new JFrame("JConsole example");
JConsole console = new JConsole();
frame.getContentPane().add(console);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(600,400);
frame.setVisible(true);
inputLoop(console, "JCE (type 'quit' to exit): ");
System.exit(0);
}
/**
* Print prompt and echos commands entered via the JConsole
*
* @param console a GUIConsoleInterface which in addition to
* basic input and output also provides coloured text
* output and name completion
* @param prompt text to display before each input line
*/
private static void inputLoop(GUIConsoleInterface console, String prompt) {
Reader input = console.getIn();
BufferedReader bufInput = new BufferedReader(input);
String newline = System.getProperty("line.separator");
console.print(prompt, Color.BLUE);
String line;
try {
while ((line = bufInput.readLine()) != null) {
console.print("You typed: " + line + newline, Color.ORANGE);
// try to sync up the console
//System.out.flush();
//System.err.flush();
//Thread.yield(); // this helps a little
if (line.equals("quit")) break;
console.print(prompt, Color.BLUE);
}
bufInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
NB: JConsole возвращает ";" если вы нажмете Enter отдельно.