gpt4 book ai didi

java - JXTreeTable、行条纹和适当的重画

转载 作者:太空宇宙 更新时间:2023-11-04 14:50:39 29 4
gpt4 key购买 nike

我正在使用默认情况下对表进行行条纹的外观。当我放入 JXTreeTable 时,我注意到由于某种原因它没有自动获取行 strip 化。

所以我使用荧光笔提出了一种解决方法,但看起来我遇到了重画故障:

screenshot showing the painting glitch

看起来JXTreeTable只是专门重新绘制文本的边界而不是整个单元格。我一直试图在调试器中捕获此问题以找出原因,但每次我在程序之间切换时,整个窗口都会重新绘制,因此几乎不可能捕获这种情况。

JTableJTree 都表现得很正常。这种外观和感觉是绘制 JTree 的整行(如 Quaqua 和 Synth),所以也许这也与它有关。也许 JXTreeTable 有某种假设,即外观不会绘制树的行?如果是这样,有没有办法解决这个问题?问题不仅仅在于外观和感觉。

代码:

import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.decorator.Highlighter;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;
import org.jdesktop.swingx.treetable.TreeTableModel;
import org.trypticon.haqua.HaquaLookAndFeel;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import java.awt.BorderLayout;
import java.awt.Component;
import java.util.Arrays;

public class TreeTableDemo2 implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TreeTableDemo2());
}

@Override
public void run() {
try {
UIManager.setLookAndFeel(new HaquaLookAndFeel());
} catch (Exception e) {
throw new RuntimeException(e);
}

JFrame frame = new JFrame("Tree Table Demo");
frame.setLayout(new BorderLayout());
frame.add(createPanel(), BorderLayout.CENTER);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}

public JPanel createPanel() {
JPanel panel = new JPanel(new BorderLayout());

TreeTableModel treeTableModel = new DummyTreeTableModel();
JXTreeTable treeTable = new FixedTreeTable(treeTableModel);
JScrollPane treeTableScroll = new JScrollPane(treeTable);

panel.add(treeTableScroll, BorderLayout.CENTER);
return panel;
}

private static class FixedTreeTable extends JXTreeTable {
private static final Highlighter oddRowHighlighter = new AbstractHighlighter() {
@Override
protected Component doHighlight(Component component, ComponentAdapter componentAdapter) {
if (componentAdapter.row % 2 != 0 &&
!componentAdapter.isSelected()) {
component.setBackground(UIManager.getColor("Table.alternateRowColor"));
}
return component;
}
};

public FixedTreeTable(TreeTableModel treeModel) {
super(treeModel);

// This hack makes it paint correctly after releasing the mouse, which is not quite good enough.
// getSelectionModel().addListSelectionListener(new ListSelectionListener() {
// @Override
// public void valueChanged(ListSelectionEvent e) {
// Rectangle repaintRange = getCellRect(e.getFirstIndex(), 0, true);
// repaintRange.add(getCellRect(e.getLastIndex(), 0, true));
// repaint(repaintRange);
// }
// });
}

@Override
public void updateUI() {
removeHighlighter(oddRowHighlighter);

super.updateUI();

// JTable does this striping automatically but JXTable's default renderer
// seems to ignore it, so JXTreeTable inherits this broken behaviour.
if (UIManager.get("Table.alternateRowColor") != null) {
addHighlighter(oddRowHighlighter);
}
}
}

private static class DummyTreeTableNode extends DefaultMutableTreeTableNode {
private final Object[] values;

private DummyTreeTableNode(String name) {
super(name);
values = new Object[5];
values[0] = name;
}

private DummyTreeTableNode(Object... values) {
super(values[0]);
this.values = values;
}

@Override
public Object getValueAt(int column) {
return values[column];
}
}

private static class DummyTreeTableModel extends DefaultTreeTableModel {
private static DefaultMutableTreeTableNode rootNode = new DefaultMutableTreeTableNode();
static {
DefaultMutableTreeTableNode blue = new DefaultMutableTreeTableNode("Blue");
blue.add(new DummyTreeTableNode("Orionis C", 33000, 30000.0, 18.0, 5.90));
rootNode.add(blue);

DefaultMutableTreeTableNode bluish = new DefaultMutableTreeTableNode("Bluish");
bluish.add(new DummyTreeTableNode("Becrux", 30000, 16000.0, 16.0, 5.70));
bluish.add(new DummyTreeTableNode("Spica", 22000, 8300.0, 10.5, 5.10));
bluish.add(new DummyTreeTableNode("Achernar", 15000, 750.0, 5.40, 3.70));
bluish.add(new DummyTreeTableNode("Rigel", 12500, 130.0, 3.50, 2.70));
rootNode.add(bluish);

DefaultMutableTreeTableNode blueWhite = new DefaultMutableTreeTableNode("Blue-White");
blueWhite.add(new DummyTreeTableNode("Sirius A", 9500, 63.0, 2.60, 2.30));
blueWhite.add(new DummyTreeTableNode("Fomalhaut", 9000, 40.0, 2.20, 2.00));
blueWhite.add(new DummyTreeTableNode("Altair", 8700, 24.0, 1.90, 1.80));
rootNode.add(blueWhite);

DefaultMutableTreeTableNode white = new DefaultMutableTreeTableNode("White");
white.add(new DummyTreeTableNode("Polaris A", 7400, 9.0, 1.60, 1.50));
white.add(new DummyTreeTableNode("Eta Scorpii", 7100, 6.3, 1.50, 1.30));
white.add(new DummyTreeTableNode("Procyon A", 6400, 4.0, 1.35, 1.20));
rootNode.add(white);

DefaultMutableTreeTableNode yellowWhite = new DefaultMutableTreeTableNode("Yellow-White");
yellowWhite.add(new DummyTreeTableNode("Alpha Centauri A", 5900, 1.45, 1.08, 1.05));
yellowWhite.add(new DummyTreeTableNode("The Sun", 5800, 100.0, 1.00, 1.00));
yellowWhite.add(new DummyTreeTableNode("Mu Cassiopeiae", 5600, 0.70, 0.95, 0.91));
yellowWhite.add(new DummyTreeTableNode("Tau Ceti", 5300, 0.44, 0.85, 0.87));
rootNode.add(yellowWhite);

DefaultMutableTreeTableNode orange = new DefaultMutableTreeTableNode("Orange");
orange.add(new DummyTreeTableNode("Pollux", 5100, 0.36, 0.83, 0.83));
orange.add(new DummyTreeTableNode("Epsilon Eridani", 4830, 0.28, 0.78, 0.79));
orange.add(new DummyTreeTableNode("Alpha Centauri B", 4370, 0.18, 0.68, 0.74));
rootNode.add(orange);

DefaultMutableTreeTableNode red = new DefaultMutableTreeTableNode("Red");
red.add(new DummyTreeTableNode("Lalande 21185", 3400, 0.03, 0.33, 0.36));
red.add(new DummyTreeTableNode("Ross 128", 3200, 0.0005, 0.20, 0.21));
red.add(new DummyTreeTableNode("Wolf 359", 3000, 0.0002, 0.10, 0.12));
rootNode.add(red);
}

private static final Object[] columnNames = {
"Star", "Temperature (K)", "Luminosity", "Mass", "Radius"
};

public DummyTreeTableModel() {
super(rootNode, Arrays.asList(columnNames));
}

@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return String.class;
} else {
return Double.class;
}
}

@Override
public boolean isCellEditable(Object node, int column) {
return false;
}
}
}

第一轮进一步调查:

我最终通过观察 JXTreeTable 中的绘制方法成功地捕获了调试器中的条件。我看到的是它有一个名为 ClippedTreeCellRenderer 的东西,其中有一些字段看起来与可疑行为相对应:

iconRect = {java.awt.Rectangle@2946}"java.awt.Rectangle[x=20,y=92,width=16,height=16]"
textRect = {java.awt.Rectangle@2947}"java.awt.Rectangle[x=20,y=-17,width=62,height=15]"
itemRect = {java.awt.Rectangle@2948}"java.awt.Rectangle[x=20,y=36,width=103,height=18]"

我还没有确认它确实使用这个值来绘制矩形,但是 textRect 正是它重新绘制的小窗口的大小。所以现在的问题是,JXTreeTable 到底从哪里提取这些值以及为什么要使用它们?

我的直觉告诉我,JXTreeTable 的渲染器以某种方式使用树单元渲染器直接渲染单元,而不是仅仅告诉树本身进行绘制。绘制行背景和展开/折叠图标的逻辑位于树中,而不是单元格中,因此如果它这样做,那么它没有一致地绘制树是有道理的。

第二轮进一步调查:

我认为我完全走错了路。看起来整行正在被绘制,但是tree.isPathSelected(path)为新选择的蓝色行返回false并返回true对于刚刚取消选择的行。

我可以通过 DefaultTreeSelectionModel 中的断点确认树选择仅在您放开鼠标后才会更新,这就是它最终恢复正确渲染的原因。

我必须进一步深入研究 JXTreeTable 以了解它如何保持这些同步。

最佳答案

我发现了这个错误。它看起来像是 JXTreeTable.java 中的一些善意代码,试图减少更新:

    /**
* Class responsible for calling updateSelectedPathsFromSelectedRows
* when the selection of the list changse.
*/
class ListSelectionHandler implements ListSelectionListener {
@Override
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
updateSelectedPathsFromSelectedRows();
}
}
}

如果删除 if 检查,一切都会正常工作。我想我只需要对 SwingX 进行一些本地更改,因为该项目基本上已经死了。 :(

关于java - JXTreeTable、行条纹和适当的重画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23832023/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com