を実装するカスタムJTree実装がありconvertValueToText
ます。この実装は、グローバルな状態に依存します。返された文字列が以前に返された文字列よりも長い場合(実際にはピクセルのように幅が広いと思います)、テキストは切り捨てられ、「...」が埋め込まれます。repaint
これは、ツリー上の要素またはaを(非)選択することによって再描画が発生した場合に当てはまります。
そのような方法で実装することは有効ですconvertValueToText
か?(ツリーの表示は自動的に更新されないことを認識しています)。
「...」を取り除き、すべての要素を現在のテキスト値で正しく描画するにはどうすればよいですか?
Update2:
どうやら私はSwingsのかなり厳格なトレッドポリシーに違反したようです(http://docs.oracle.com/javase/6/docs/api/javax/swing/package-summary.html)。更新の実行:
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
for (int row = 0; row < tree.getRowCount(); row++) {
((DefaultTreeModel) tree.getModel())
.nodeChanged((TreeNode) tree.getPathForRow(row)
.getLastPathComponent());
}
}
});
正しく機能しているようです。
アップデート:
最小限の例を次に示します。
import java.util.Enumeration;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JTree;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
public class WeirdTreeFrame extends JFrame {
public class WeirdTree extends JTree {
public WeirdTree(TreeNode root) {
super(root);
}
@Override
public String convertValueToText(Object value, boolean selected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
return super.convertValueToText(value, selected, expanded, leaf, row, hasFocus);
}
}
public class WeirdNode implements TreeNode {
protected WeirdNode parent;
protected WeirdNode children[];
protected int dephth;
protected String name;
protected String names[] = {"Foo", "Bar", "Ohh"};
public long superCrazyNumber;
public WeirdNode(WeirdNode parent, String name) {
this.parent = parent;
this.name = name;
if (parent != null) {
dephth = parent.dephth + 1;
} else {
dephth = 0;
}
if (dephth < 10) {
children = new WeirdNode[3];
for (int i = 0; i < 3; i++) {
children[i] = new WeirdNode(this, name + names[i]);
}
}
}
@Override
public TreeNode getChildAt(int childIndex) {
if (childIndex >= getChildCount()) return null;
return children[childIndex];
}
@Override
public int getChildCount() {
return (children != null) ? children.length : 0;
}
@Override
public TreeNode getParent() {
return parent;
}
@Override
public int getIndex(TreeNode node) {
for (int i = 0; i < children.length; i++) {
if (children[i] == node) return i;
}
throw new RuntimeException();
}
@Override
public boolean getAllowsChildren() {
return true;
}
@Override
public boolean isLeaf() {
return getChildCount() == 0;
}
@Override
public Enumeration children() {
return new Enumeration<TreeNode>() {
int nextIdx = 0;
@Override
public boolean hasMoreElements() {
return nextIdx < getChildCount();
}
@Override
public TreeNode nextElement() {
return getChildAt(nextIdx++);
}
};
}
@Override
public String toString() {
return "[" + dephth + "]" + name + "@" + superCrazyNumber;
}
}
public WeirdNode root;
private WeirdTree tree;
public WeirdTreeFrame() {
root = new WeirdNode(null, "Blubb");
tree = new WeirdTree(root);
add(tree);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,500);
setVisible(true);
}
public void update() {
for (int row = 0; row < tree.getRowCount(); row++) {
((DefaultTreeModel) tree.getModel()).nodeChanged((TreeNode)tree.getPathForRow(row).getLastPathComponent());
}
}
public static void main(String[] args) {
WeirdTreeFrame frame = new WeirdTreeFrame();
Random rnd = new Random(41);
for (long i = 0; ; i++) {
for (WeirdNode node = frame.root; node != null; node = (WeirdNode)node.getChildAt(rnd.nextInt(3))) {
node.superCrazyNumber++;
}
if (i % 1e7 == 0) {
System.out.println("Update: " + i);
frame.update();
}
}
}
}
このupdate()
方法では、適切なイベントを発生させて、表示されているすべてのノードが正しく更新されていることを確認しました。ご覧のとおり、計算中にいくつかの計算が並行して定期的に行われているので、ツリーラベル(構造ではなく)を更新したいと思います。
この方法の問題はupdate()
、添付の図に示されているように、一部のノードが完全に間違ってラベル付けされていることです(ルートノードの場合は「[0] ...」、n番目のレベルの場合は「[n] ..」である必要があります)
これは何らかの競合状態だと思います。