Конфликт выделения текста между JTextPane и JTextField
Почему текст в JTextPane нельзя выделить программно, если присутствует JTextField? Я думаю, что-то связано с фокусом. Спасибо.
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
public class align extends JFrame {
private align() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addPane(this, "one");
pack();
setVisible(true);
}
public static void main(String[] args) {
align t = new align();
}
private void addPane(JFrame frame, String name) {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEFT));
// if the next line is disabled, then the text is JTextPane is correctly highlighted.,,
panel.add(makeField("line1"));
JTextPane p = new JTextPane();
p.setText("abcdef");
p.setSelectionStart(2);
p.setSelectionEnd(4);
p.setFocusable(true);
p.requestFocus();
p.requestDefaultFocus();
panel.add(p);
frame.getContentPane().add(panel);
}
private JComponent makeField(String name) {
JTextField textArea = new JTextField();
textArea.setText(name);
textArea.setEditable(false);
return textArea;
}
}
РЕДАКТИРОВАТЬ:
Получил его, чтобы отобразить выделенный текст, запустив ключевое событие после того, как кадр был построен. Лучшим (более длинным) решением было бы иметь TextPane только для чтения с настраиваемым Highlighter и DocumentListener, который поддерживает обновление буфера обмена на Ctrl-C.
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(
new KeyEvent(textPane, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), 0, KeyEvent.VK_TAB));
4 ответа
Просто для забавы (в конце концов, это пятница:-) Я проследил за комментарием Станислава, расширив DefaultCaret, чтобы сделать выбор видимым для несосредоточенных текстовых компонентов.
Основные идеи
- поддержка двух выделенных декораций: сфокусированный выбор, несфокусированный выбор
- сохранить внешний вид выделенных участков как можно ближе к значению по умолчанию LAF, что сводится к повторному использованию selectionPainter (доступно только... кашель, кашель... отражение)
дурак супер верить, что выбор всегда виден
public static class WrappingCaret extends DefaultCaret { private DefaultCaret delegate; private HighlightPainter focusedSelectionPainter; private HighlightPainter unfocusedSelectionPainter; private boolean focusedSelectionVisible; public WrappingCaret(JTextComponent target) { installDelegate((DefaultCaret) target.getCaret()); target.setCaret(this); } private void installDelegate(DefaultCaret delegate) { this.delegate = delegate; setBlinkRate(delegate.getBlinkRate()); } private void installSelectionPainters() { if (delegate instanceof BasicCaret) { installDefaultPainters(); } else { try { Method method = delegate.getClass().getDeclaredMethod( "getSelectionPainter"); method.setAccessible(true); focusedSelectionPainter = (HighlightPainter) method .invoke(delegate); Constructor<?>[] constructors = focusedSelectionPainter .getClass().getDeclaredConstructors(); constructors[0].setAccessible(true); unfocusedSelectionPainter = (HighlightPainter) constructors[0] .newInstance(getUnfocusedSelectionColor()); } catch (Exception e) { installDefaultPainters(); } } } private Color getUnfocusedSelectionColor() { Color first = getComponent().getSelectionColor(); // create a reasonable unfocusedSelectionColor return PaintUtils.setAlpha(first, 125); } private void installDefaultPainters() { focusedSelectionPainter = super.getSelectionPainter(); unfocusedSelectionPainter = new DefaultHighlightPainter( getUnfocusedSelectionColor()); } /** * @inherited <p> */ @Override public void install(JTextComponent c) { super.install(c); installSelectionPainters(); setSelectionVisible(isSelectionVisible()); } /** * @inherited <p> */ @Override public void setSelectionVisible(boolean vis) { focusedSelectionVisible = vis; super.setSelectionVisible(!isSelectionVisible()); super.setSelectionVisible(true); } /** * @inherited <p> */ @Override protected HighlightPainter getSelectionPainter() { return focusedSelectionVisible ? focusedSelectionPainter : unfocusedSelectionPainter; } }
Наслаждайтесь!
Текст в JTextPane
выбран. Проблема в том, что он не дает визуальной индикации, если компонент не сфокусирован. Попробуйте добавить вкладку к компоненту, как только появится GUI.
Итак, я должен выпустить это к сведению?
Нет, вам следует переделать свой сломанный графический интерфейс, который использует выделение текста для идентификации интересующего вас текста. Выбор текста важнее для конечного пользователя, а не для приложения.
Дано JTextPane
является компонентом, который поддерживает форматирование, например, может сделать текст жирным или курсивом.
Возможно, вам следует использовать Highlighter, чтобы подсветка отображалась во всех текстовых компонентах:
Highlighter.HighlightPainter yellow =
new DefaultHighlighter.DefaultHighlightPainter( Color.YELLOW );
try
{
textPane.getHighlighter().addHighlight(2, 4, yellow);
}
catch(BadLocationException ble) { System.out.println(ble); }