我试图找出在 Java Swing GUI 中显示 HTML 行列表的最佳方法。输入来自控制台标准输入捕获。然后将其解析为 HTML 行。
我尝试将它们显示为 a 中的条目JList
或显示为 a 中的完整文档JTextPane
。
- 问题
JTextPane
在于,每次从控制台接收到新行并且滚动将重置时,都会刷新整个显示。我什至尝试了各种技术来自动滚动到底部,但没有成功。 - 接缝有点慢并且
JList
闪烁很多。
显示信息的最佳方式是什么?它以 VT100 终端格式的形式出现。我真的只需要很好地显示它的格式。
这是我的JList
版本代码。
DefaultListModel dl;
...
input = new Scanner(new InputStreamReader(m_Process.getInputStream()));
while(input.hasNextLine())
{
String line = input.nextLine();
line = ConvertLineToHTML(line);
dl.addElement(htmlHead + line + htmlEnd);
}
int index = dl.getSize() - 1;
displayList.ensureIndexIsVisible(index);
对于那些需要完整程序的人,对不起,但我不能发布一些代码,但这“应该”足以让它工作,但我还没有测试过。
private class ServerReader implements Runnable
{
private JList displayList = null;
public ServerReader(Process nProcess, JList list, String type)
{
displayList = list;
if("error".equals(type))
input = new Scanner(new InputStreamReader(nProcess.getErrorStream()));
if("in".equals(type))
input = new Scanner(new InputStreamReader(nProcess.getInputStream()));
}
private Scanner input;
int forground = -1;
int background = -1;
int intensity = -1;
boolean Underline = false;
private final String htmlHead = "<html><head></head><body bgcolor=\"Black\" color=\"White\">";
private final String htmlEnd = "</body></html>";
@Override
public void run() {
while(input.hasNextLine())
{
String line = input.nextLine();
int esc;
while((esc = line.indexOf("\033[")) != -1)
{
int end = line.indexOf("m", esc);
String cmd = line.substring(esc+2, end);
String[] attrs = cmd.split(";");
for(String attr : attrs)
{
int atr = Integer.parseInt(attr);
if(atr == 0)
{
Underline = false;
intensity = -1;
forground = -1;
background = -1;
}
if(atr == 4)
Underline = true;
if(atr == 22)
intensity = -1;
if(atr >= 1 && atr <= 2)
intensity = atr;
if(atr >= 30 && atr <= 37)
forground = atr - 30;
if(atr >= 40 && atr <= 47)
background = atr - 40;
}
String Format = "";
// get forground color format.
if(forground != -1)
{
Format += " color=\"";
Format += VT100ToHTMLColor(forground, intensity);
Format += "\"";
}
if(Format.length() > 0)
{
Format = "<font" + Format + ">";
if(esc > 0)
Format = line.substring(0, esc) + Format;
line = Format + line.substring(end + 1);
// add font closing tag.
if((esc = line.indexOf("\033[")) != -1)
line = line.substring(0, esc) + "</font>" + line.substring(esc);
else
line += "</font>";
}
else
line = line.substring(0, esc) + line.substring(end+1);
}
if(displayList != null && line.length() > 0)
{
ListModel mod = displayList.getModel();
if(mod instanceof DefaultListModel)
{
DefaultListModel dl = (DefaultListModel)mod;
dl.addElement(htmlHead + line + htmlEnd);
}
int index = mod.getSize() - 1;
displayList.ensureIndexIsVisible(index);
}
}
input.close();
}
private String VT100ToHTMLColor(int attribute, int intensity)
{
if(attribute >= 0 || attribute <= 7)
{
// Black Red Green Yellow Blue Magenta Cyan White
String[] Colors = { "#000000", "#AA0000", "#00AA00", "#AA5500", "#0000AA", "#AA00AA", "#00AAAA", "#AAAAAA" };
String[] BrightColors = { "#000000", "#FF5555", "#55FF55", "#FFFFAA", "#5555FF", "#FF55FF", "#55FFFF", "#FFFFFF" };
String[] DimColors = { "#000000", "#800000", "#008000", "#804000", "#000080", "#800080", "#008080", "#808080" };
if(intensity == 1)
return BrightColors[attribute];
if(intensity == 2)
return DimColors[attribute];
return Colors[attribute];
}
return "#000000";
}
}
public class MyFrame extends javax.swing.JFrame {
public MyFrame() {
initComponents();
}
private void initComponents() {
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
OutputList = new javax.swing.JList();
OutputList.setBackground(new java.awt.Color(0, 0, 0));
OutputList.setForeground(new java.awt.Color(204, 204, 204));
OutputList.setModel(new DefaultListModel());
jScrollPane1.setViewportView(OutputList);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 684, Short.MAX_VALUE)
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 255, Short.MAX_VALUE)
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
pack();
}
private javax.swing.JList OutputList;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private Process m_Process = null;
private Thread inThread = null;
private OutputStreamWriter outStream = null;
private void StartServer(String Executable, String WorkingDir)
{
Runtime r = Runtime.getRuntime();
try {
// create builder with executable.
ProcessBuilder pb = new ProcessBuilder(Executable);
// set working directory.
pb.directory(new File(WorkingDir));
// start the process.
m_Process = pb.start();
// start the server listener.
inThread = new Thread(new ServerReader(m_Process, OutputList, "in"));
inThread.start();
// open a stream to the server.
outStream = new OutputStreamWriter(m_Process.getOutputStream());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
}
private boolean StopServer()
{
try
{
// check to see if the process has stopped.
m_Process.exitValue();
// close the output stram.
if(outStream != null)
outStream.close();
// destoy the objects.
outStream = null;
inThread = null;
m_Process = null;
}
catch (IllegalThreadStateException ex) {
try {
// send exit command.
outStream.write("exit");
} catch (IOException ex2) {
System.out.println(ex2.getMessage());
}
// process has still not completed.
return false;
} catch (IOException ex) {
// error with output stream just kill it.
outStream = null;
return false;
}
return true;
}