如何使用SwingX的荧光笔返回不同的渲染器组件?

时间:2014-12-02 00:16:40

标签: java swing swingx swingx-highlighter

我注意到SwingX的Highlighter界面允许荧光笔从传入的组件中返回一个不同的组件。我实际上找不到任何使用它的例子,但是我以为我会尝试用它来创造某种虚假的第二列。

预期的结果是左列中的文字应截断右列开始的位置,因此我不能只使用Painter。右列应该为整个列表呈现相同的宽度,这是我尚未弄清楚的问题,但看起来并不难。

至于现在,我发现行高被压缩到如此之小,你无法看到任何文字。

这就是我的意思:

screenshot

示例程序:

import java.awt.BorderLayout;
import java.awt.Component;

import javax.swing.DefaultListModel;
import javax.swing.GroupLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.LayoutStyle;
import javax.swing.SwingUtilities;

import org.jdesktop.swingx.JXList;
import org.jdesktop.swingx.decorator.AbstractHighlighter;
import org.jdesktop.swingx.decorator.ComponentAdapter;
import org.jdesktop.swingx.renderer.JRendererLabel;
import org.jdesktop.swingx.renderer.StringValue;

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

    @Override
    public void run()
    {
        JFrame frame = new JFrame("Highlighter test");
        JXList list = new JXList();
        DefaultListModel<String> listModel = new DefaultListModel<>();
        listModel.addElement("one");
        listModel.addElement("two");
        listModel.addElement("three");
        list.setModel(listModel);
        list.setVisibleRowCount(8);
        list.setPrototypeCellValue("some string");
        list.addHighlighter(new AddSecondColumnHighlighter(v -> ((String) v).toUpperCase()));
        JScrollPane listScroll = new JScrollPane(list);
        frame.setLayout(new BorderLayout());
        frame.add(listScroll, BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }

    private static class AddSecondColumnHighlighter extends AbstractHighlighter
    {
        private final StringValue secondColumnStringValue;

        public AddSecondColumnHighlighter(StringValue secondColumnStringValue)
        {
            this.secondColumnStringValue = secondColumnStringValue;
        }

        @Override
        protected Component doHighlight(Component component, ComponentAdapter adapter)
        {
            JRendererLabel rightColumn = new JRendererLabel();
            rightColumn.setText(secondColumnStringValue.getString(adapter.getValue()));

            return new FixedSecondColumnRendererLabel(component, rightColumn);
        }
    }

    private static class FixedSecondColumnRendererLabel extends JRendererLabel
    {
        private FixedSecondColumnRendererLabel(Component leadingComponent, Component trailingComponent)
        {
            GroupLayout layout = new GroupLayout(this);
            setLayout(layout);

            layout.setHorizontalGroup(layout.createSequentialGroup()
                                            .addComponent(leadingComponent, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                            .addComponent(trailingComponent));

            layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                          .addComponent(leadingComponent)
                                          .addComponent(trailingComponent));
        }
    }

}

我想知道是否有正确的方法来使用这一部分API。我故意延长JRendererLabel,以防出现问题,但这似乎更微妙......

1 个答案:

答案 0 :(得分:2)

如果查看JRendererLabel,您会看到invalidaterevalidatevalidate(以及其他一些方法)设置为“否” “操作”,意味着他们不再向布局管理器发出组件应该布局的通知。这样做是为了帮助提高渲染器“压印”到组件(JXList)的性能。

相反,请使用FixedSecondColumnRendererLabel中的扩展JPanel

每次调用方法时,不应该创建FixedSecondColumnRendererLabelJRendererLabel的新实例,而应该考虑对其进行优化,以便返回相同的实例,但每次执行时都会配置一个实例。被称为。

请记住,在JXList中为每一行调用此方法,您拥有的越多,调用的次数越多,它将创建的短暂对象就越多......