Java 如何使用setFocusable(false)突出显示JTextPane中的文本?
所以我有一个Java 如何使用setFocusable(false)突出显示JTextPane中的文本?,java,swing,highlight,jtextpane,focusable,Java,Swing,Highlight,Jtextpane,Focusable,所以我有一个JTextPane,基本上用作控制台。我把它放在JFrame的中心区域,而JTextField放在南部区域。JTextField将获取它拥有的文本,并在用户按enter键时将其添加到JTextPane。为了使JTextPane不能被用户编辑,我必须setFocusable(false),因为使用setEditable(false)可以阻止任何文本出现在JTextPane上。但是,虽然我不希望用户编辑窗格,但我仍然希望用户能够突出显示窗格中的文本,但我似乎找不到这样做的方法 下面是一个
JTextPane
,基本上用作控制台。我把它放在JFrame
的中心区域,而JTextField
放在南部区域。JTextField
将获取它拥有的文本,并在用户按enter键时将其添加到JTextPane
。为了使JTextPane
不能被用户编辑,我必须setFocusable(false)
,因为使用setEditable(false)
可以阻止任何文本出现在JTextPane
上。但是,虽然我不希望用户编辑窗格,但我仍然希望用户能够突出显示窗格中的文本,但我似乎找不到这样做的方法
下面是一个示例,演示了我的意思
样本
package resources;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class SampeTextPane extends JFrame
{
public SampeTextPane()
{
setPreferredSize(new Dimension(350, 200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
JTextPane display = new JTextPane();
display.setBorder(new EmptyBorder(5, 5, 5, 5));
display.setMargin(new Insets(5, 5, 5, 5));
display.setFocusable(false);
appendToPane(display, "Example", Color.BLUE);
JTextField field = new JTextField();
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
appendToPane(display, field.getText(), Color.BLACK);
field.setText("");
}
});
add(display, BorderLayout.CENTER);
add(field, BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void appendToPane(JTextPane pane, String text, Color color)
{
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, color);
aset = sc.addAttribute(aset, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED);
int len = pane.getDocument().getLength();
pane.setCaretPosition(len);
pane.setCharacterAttributes(aset, false);
pane.replaceSelection(text + "\n");
}
public static void main(String[] args)
{
new SampeTextPane();
}
}
提前感谢您的帮助
使用setEditable(false)可阻止任何文本出现在JTextPane上
您可以使JTextPane
不可编辑,但不能通过文本窗格更新文本
相反,您可以通过文档
更新文本:
//int len = pane.getDocument().getLength();
//pane.setCaretPosition(len);
//pane.setCharacterAttributes(aset, false);
//pane.replaceSelection(text + "\n");
try
{
StyledDocument doc = pane.getStyledDocument();
doc.insertString(doc.getLength(), text, aset);
}
catch(BadLocationException e) { System.out.println(e); }
使用setEditable(false)可阻止任何文本出现在JTextPane上
您可以使JTextPane
不可编辑,但不能通过文本窗格更新文本
相反,您可以通过文档
更新文本:
//int len = pane.getDocument().getLength();
//pane.setCaretPosition(len);
//pane.setCharacterAttributes(aset, false);
//pane.replaceSelection(text + "\n");
try
{
StyledDocument doc = pane.getStyledDocument();
doc.insertString(doc.getLength(), text, aset);
}
catch(BadLocationException e) { System.out.println(e); }
StanislavL建议的另一种选择是使用布尔标志来允许或不允许对文档进行更改,尽管它更复杂 在您的情况下,它可能看起来像:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.DocumentFilter;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
@SuppressWarnings("serial")
public class SampeTextPane extends JFrame {
private boolean isApi = false;
public SampeTextPane() {
setPreferredSize(new Dimension(350, 200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
JTextPane display = new JTextPane();
((DefaultStyledDocument) display.getDocument()).setDocumentFilter(new DocFilter());
display.setBorder(new EmptyBorder(5, 5, 5, 5));
display.setMargin(new Insets(5, 5, 5, 5));
// !! display.setFocusable(false);
appendToPane(display, "Example", Color.BLUE);
JTextField field = new JTextField();
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
appendToPane(display, field.getText(), Color.BLACK);
field.setText("");
}
});
add(display, BorderLayout.CENTER);
add(field, BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void appendToPane(JTextPane pane, String text, Color color) {
isApi = true;
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground,
color);
aset = sc.addAttribute(aset, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED);
int len = pane.getDocument().getLength();
String selection = pane.getSelectedText();
if (selection == null) {
pane.setCaretPosition(len);
text += "\n";
}
pane.setCharacterAttributes(aset, false);
pane.replaceSelection(text);
isApi = false;
}
private class DocFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
if (isApi) {
super.insertString(fb, offset, string, attr);
}
}
@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
if (isApi) {
super.remove(fb, offset, length);
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
if (isApi) {
super.replace(fb, offset, length, text, attrs);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SampeTextPane());
}
}
StanislavL建议的另一种选择是使用布尔标志来允许或不允许对文档进行更改,尽管它更复杂 在您的情况下,它可能看起来像:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.DocumentFilter;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
@SuppressWarnings("serial")
public class SampeTextPane extends JFrame {
private boolean isApi = false;
public SampeTextPane() {
setPreferredSize(new Dimension(350, 200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
JTextPane display = new JTextPane();
((DefaultStyledDocument) display.getDocument()).setDocumentFilter(new DocFilter());
display.setBorder(new EmptyBorder(5, 5, 5, 5));
display.setMargin(new Insets(5, 5, 5, 5));
// !! display.setFocusable(false);
appendToPane(display, "Example", Color.BLUE);
JTextField field = new JTextField();
field.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
appendToPane(display, field.getText(), Color.BLACK);
field.setText("");
}
});
add(display, BorderLayout.CENTER);
add(field, BorderLayout.SOUTH);
pack();
setVisible(true);
}
private void appendToPane(JTextPane pane, String text, Color color) {
isApi = true;
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground,
color);
aset = sc.addAttribute(aset, StyleConstants.Alignment, StyleConstants.ALIGN_JUSTIFIED);
int len = pane.getDocument().getLength();
String selection = pane.getSelectedText();
if (selection == null) {
pane.setCaretPosition(len);
text += "\n";
}
pane.setCharacterAttributes(aset, false);
pane.replaceSelection(text);
isApi = false;
}
private class DocFilter extends DocumentFilter {
@Override
public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
throws BadLocationException {
if (isApi) {
super.insertString(fb, offset, string, attr);
}
}
@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
if (isApi) {
super.remove(fb, offset, length);
}
}
@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException {
if (isApi) {
super.replace(fb, offset, length, text, attrs);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SampeTextPane());
}
}
这是一种很有趣的方式,从我所看到的情况来看,它也做了同样的事情,但它稍微超出了我的Java知识。谢谢你@瑞恩:是的,卡米克尔的建议更干净,我很高兴你同意了。我是在他发布正确答案之前创建代码的,所以我讨厌不发布我的“努力”。当然,我投票给了他的答案。这是一种有趣的方式,从我所看到的情况来看,它做了同样的事情,但它稍微超出了我的Java知识。谢谢你@瑞恩:是的,卡米克尔的建议更干净,我很高兴你同意了。我是在他发布正确答案之前创建代码的,所以我讨厌不发布我的“努力”。当然,我投票支持他的答案。