Java JTextPane 垂直对齐
Java JTextPane Vertical Alignment
我正在开发一款简单的文字冒险游戏,它应该允许用户输入文字并得到他们的回应,就像一个简单的命令提示符一样。
出于各种原因,我正在尝试使用 JPanel window 和其他一些东西,以便我可以控制内容的显示方式。以下是我目前的代码。
但是我遇到了一些问题:JTextPane 中的文本与 window 的顶部而不是底部对齐,并且文本不可滚动。基本上,您刚刚输入的文本应该像命令提示符一样出现在文本输入框上方,并且旧文本应该是可滚动的。有谁知道我应该如何解决这个问题?
提前致谢。
小修改:这是它当前的截图。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class TextDemo extends JPanel implements ActionListener {
protected JTextField textField;
protected JTextPane textArea;
private final static String newline = "\n";
public static Color fg = Color.WHITE, bg = Color.BLACK;
public static final Font header = new Font("Times New Roman", Font.PLAIN, 96);
public static final Font normal = new Font("Times New Roman", Font.PLAIN, 24);
public TextDemo() {
super(new GridBagLayout());
textField = new JTextField();
textField.setFont(normal);
textField.setForeground(fg);
textField.setBackground(bg);
textField.setPreferredSize(new Dimension(640, 30));
textField.addActionListener(this);
textArea = new JTextPane();
textArea.setFont(normal);
//textArea.setLineWrap(true);
//textArea.setWrapStyleWord(true);
textArea.setForeground(fg);
textArea.setBackground(bg);
textArea.setPreferredSize(new Dimension(640, 450));
textArea.setEditable(false);
//textArea.setAlignmentY(Component.BOTTOM_ALIGNMENT);
JScrollPane scrollPane = new JScrollPane(textArea);
//scrollPane.setAlignmentY(JScrollPane.BOTTOM_ALIGNMENT);
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.BOTH;`
c.weightx = 1.0;
c.weighty = 1.0;
add(scrollPane, c);
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
//add(textArea, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent evt) {
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setAlignment(sas, StyleConstants.ALIGN_RIGHT);
StyleConstants.setForeground(sas, Color.WHITE);
String text = textField.getText();
Document doc = textArea.getStyledDocument();
try {
doc.insertString(doc.getLength(), text + newline, sas);
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//textArea.append(text + newline);
textField.setText("");
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TextDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new TextDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
TextDemo.createAndShowGUI();
}
}
通过谷歌搜索就能找到令人惊奇的东西。
所以,下面的例子是基于Centering text vertically in JEditorPane的。该示例确实在视图底部留下了一条 "blank" 行,我相信只要稍作努力,您就可以弄清楚如何删除它,但这将为您提供一个起点。
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int lineCount = 0;
public TestPane() {
setLayout(new BorderLayout());
JTextPane tp = new JTextPane();
tp.setEditorKit(new MyEditorKit());
add(new JScrollPane(tp));
JButton btn = new JButton("Add");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
Document doc = tp.getDocument();
int end = doc.getLength();
doc.insertString(end, (++lineCount) + " some more text\n", null);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});
add(btn, BorderLayout.SOUTH);
}
}
class MyEditorKit extends StyledEditorKit {
public ViewFactory getViewFactory() {
return new StyledViewFactory();
}
class StyledViewFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new CenteredBoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
return new LabelView(elem);
}
}
}
class CenteredBoxView extends BoxView {
public CenteredBoxView(Element elem, int axis) {
super(elem, axis);
}
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
super.layoutMajorAxis(targetSpan, axis, offsets, spans);
int textBlockHeight = 0;
int offset = 0;
for (int i = 0; i < spans.length; i++) {
textBlockHeight += spans[i];
}
offset = targetSpan - textBlockHeight;
for (int i = 0; i < offsets.length; i++) {
offsets[i] += offset;
}
}
}
}
奇迹发生在 layoutMajorAxis
方法中
我正在开发一款简单的文字冒险游戏,它应该允许用户输入文字并得到他们的回应,就像一个简单的命令提示符一样。
出于各种原因,我正在尝试使用 JPanel window 和其他一些东西,以便我可以控制内容的显示方式。以下是我目前的代码。
但是我遇到了一些问题:JTextPane 中的文本与 window 的顶部而不是底部对齐,并且文本不可滚动。基本上,您刚刚输入的文本应该像命令提示符一样出现在文本输入框上方,并且旧文本应该是可滚动的。有谁知道我应该如何解决这个问题?
提前致谢。
小修改:这是它当前的截图。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class TextDemo extends JPanel implements ActionListener {
protected JTextField textField;
protected JTextPane textArea;
private final static String newline = "\n";
public static Color fg = Color.WHITE, bg = Color.BLACK;
public static final Font header = new Font("Times New Roman", Font.PLAIN, 96);
public static final Font normal = new Font("Times New Roman", Font.PLAIN, 24);
public TextDemo() {
super(new GridBagLayout());
textField = new JTextField();
textField.setFont(normal);
textField.setForeground(fg);
textField.setBackground(bg);
textField.setPreferredSize(new Dimension(640, 30));
textField.addActionListener(this);
textArea = new JTextPane();
textArea.setFont(normal);
//textArea.setLineWrap(true);
//textArea.setWrapStyleWord(true);
textArea.setForeground(fg);
textArea.setBackground(bg);
textArea.setPreferredSize(new Dimension(640, 450));
textArea.setEditable(false);
//textArea.setAlignmentY(Component.BOTTOM_ALIGNMENT);
JScrollPane scrollPane = new JScrollPane(textArea);
//scrollPane.setAlignmentY(JScrollPane.BOTTOM_ALIGNMENT);
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.BOTH;`
c.weightx = 1.0;
c.weighty = 1.0;
add(scrollPane, c);
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
//add(textArea, BorderLayout.SOUTH);
}
public void actionPerformed(ActionEvent evt) {
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setAlignment(sas, StyleConstants.ALIGN_RIGHT);
StyleConstants.setForeground(sas, Color.WHITE);
String text = textField.getText();
Document doc = textArea.getStyledDocument();
try {
doc.insertString(doc.getLength(), text + newline, sas);
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//textArea.append(text + newline);
textField.setText("");
}
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TextDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add contents to the window.
frame.add(new TextDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
TextDemo.createAndShowGUI();
}
}
通过谷歌搜索就能找到令人惊奇的东西。
所以,下面的例子是基于Centering text vertically in JEditorPane的。该示例确实在视图底部留下了一条 "blank" 行,我相信只要稍作努力,您就可以弄清楚如何删除它,但这将为您提供一个起点。
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.BadLocationException;
import javax.swing.text.BoxView;
import javax.swing.text.ComponentView;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.IconView;
import javax.swing.text.LabelView;
import javax.swing.text.ParagraphView;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.View;
import javax.swing.text.ViewFactory;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int lineCount = 0;
public TestPane() {
setLayout(new BorderLayout());
JTextPane tp = new JTextPane();
tp.setEditorKit(new MyEditorKit());
add(new JScrollPane(tp));
JButton btn = new JButton("Add");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
Document doc = tp.getDocument();
int end = doc.getLength();
doc.insertString(end, (++lineCount) + " some more text\n", null);
} catch (BadLocationException ex) {
ex.printStackTrace();
}
}
});
add(btn, BorderLayout.SOUTH);
}
}
class MyEditorKit extends StyledEditorKit {
public ViewFactory getViewFactory() {
return new StyledViewFactory();
}
class StyledViewFactory implements ViewFactory {
public View create(Element elem) {
String kind = elem.getName();
if (kind != null) {
if (kind.equals(AbstractDocument.ContentElementName)) {
return new LabelView(elem);
} else if (kind.equals(AbstractDocument.ParagraphElementName)) {
return new ParagraphView(elem);
} else if (kind.equals(AbstractDocument.SectionElementName)) {
return new CenteredBoxView(elem, View.Y_AXIS);
} else if (kind.equals(StyleConstants.ComponentElementName)) {
return new ComponentView(elem);
} else if (kind.equals(StyleConstants.IconElementName)) {
return new IconView(elem);
}
}
return new LabelView(elem);
}
}
}
class CenteredBoxView extends BoxView {
public CenteredBoxView(Element elem, int axis) {
super(elem, axis);
}
protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
super.layoutMajorAxis(targetSpan, axis, offsets, spans);
int textBlockHeight = 0;
int offset = 0;
for (int i = 0; i < spans.length; i++) {
textBlockHeight += spans[i];
}
offset = targetSpan - textBlockHeight;
for (int i = 0; i < offsets.length; i++) {
offsets[i] += offset;
}
}
}
}
奇迹发生在 layoutMajorAxis
方法中