JTextAreaとJFrameで幅固定、文字列の折り返し、親枠外まで高さ拡大可能なセルエディタを作成する
Total: 2527
, Today: 1
, Yesterday: 1
Posted by aterai at
Last-modified:
概要
JTextArea
を幅固定、文字列の長さに応じた折り返しで高さ伸縮可能に設定し、これをJFrame
に配置して親枠外でも表示可能なJList
セルラベルエディタとして使用します。
Screenshot
![Swing/LineWrapListEditor screenshot](https://ateraimemo.com/swing/linewraplisteditor/screenshot.png)
Advertisement
サンプルコード
// private final Container glassPane = new EditorGlassPane();
// private final JPopupMenu popup = new JPopupMenu();
private final JFrame window = new JFrame();
// private final JTextField editor = new JTextField();
private final JTextArea editor = new JTextArea();
// ...
window.setUndecorated(true);
window.setAlwaysOnTop(true);
window.addWindowListener(new WindowAdapter() {
@Override public void windowDeactivated(WindowEvent e) {
if (editor.isEditable()) {
renameTitle.actionPerformed(new ActionEvent(editor, ActionEvent.ACTION_PERFORMED, ""));
}
}
});
window.add(editor);
editor.setBorder(BorderFactory.createLineBorder(Color.BLACK));
editor.setLineWrap(true);
editor.setFont(UIManager.getFont("TextField.font"));
editor.setComponentPopupMenu(new TextComponentPopupMenu());
editor.getDocument().addDocumentListener(new DocumentListener() {
private int prev = -1;
private void update() {
EventQueue.invokeLater(() -> {
int h = editor.getPreferredSize().height;
if (prev != h) {
Rectangle rect = editor.getBounds();
rect.height = h;
editor.setBounds(rect);
window.pack(); // popup.pack();
editor.requestFocusInWindow();
}
prev = h;
});
}
@Override public void insertUpdate(DocumentEvent e) {
update();
}
@Override public void removeUpdate(DocumentEvent e) {
update();
}
@Override public void changedUpdate(DocumentEvent e) {
update();
}
});
View in GitHub: Java, Kotlin解説
GlassPane
+JTextField
JTextField#setHorizontalAlignment(SwingConstants.CENTER)
を設定して中央揃えが可能JTextField
を使用するため1
行エディタになる- 参考: JListのセルに配置したJLabelのテキストを編集する
GlassPane
+JTextArea
JTextArea#setLineWrap(true)
を設定すれば、幅固定で文字列長に応じて行方向に拡大縮小が可能になるJTextArea
の折り返しが変化すると推奨サイズの高さが更新される
JTextArea
を使用するため中央揃えが不可- 本文スタイルに中央揃え属性を設定し、かつ折り返し設定を変更した
JTextPane
で代用可能 - JTextPaneで中央揃え、行折返し可能なリストセルエディタを作成するに移動
- 本文スタイルに中央揃え属性を設定し、かつ折り返し設定を変更した
- 行数が増加して親
JFrame
外になるとエディタが途切れてしまう
JPopupMenu
+JTextArea
- 親
JFrame
外にエディタを配置可能 - エディタの折り返しが変化すると
JPopupMenu#pack()
を使用してJPopupMenu
のサイズをJTextArea
と同じになるよう更新JPopupMenu#pack()
を実行すると子のJTextArea
からフォーカスが移動してしまうのでJTextArea#requestFocusInWindow()
で再設定する必要がある- 親
JFrame
外に表示さている場合(HeavyWeightWindow
(JWindow
)に配置されている場合)一瞬親JFrame
タイトルバーの描画などが乱れる
JPopupMenu
にPopupMenuListener
を追加してエディタでの編集のコミットを実行JPopupMenu
内のJTextArea
からJPopupMenu
を開くことができない
- 親
JFrame
+JTextArea
JFrame#setUndecorated(true)
とJFrame#setAlwaysOnTop(true)
を設定したJFrame
をJPopupMenu
の代わりに使用JWindow内にフォーカス可能なコンポーネントを配置するのように所有フレームを表示中のJFrame
ではなくJWindow
を使用すると子コンポーネントがフォーカスが取得できないJFrame
を指定してJWindow
を作成すれば子コンポーネントがフォーカス取得可能になる- 親
JFrame
がアクティブWindow
でなくなるためグローバルフォーカスが外れる
JFrame
内のJTextArea
からJPopupMenu
を開くことが可能になるJFrame
にWindowListener
を追加してエディタでの編集のコミットを実行- 編集キャンセルの場合はコミットせずに
JFrame
を非表示にするよう注意が必要
- 編集キャンセルの場合はコミットせずに
JFrame
のタイトルバーをクリックしても編集終了できない
参考リンク
- JListのセルに配置したJLabelのテキストを編集する
- JTextArea#setLineWrap(boolean) (Java Platform SE 8)
- JWindow内にフォーカス可能なコンポーネントを配置する