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

时间:2022-11-19 09:54:35

I noticed SwingX's Highlighter interface allows the highlighter to return a different component from the one that is being passed in. I can't actually find any examples of this being used, but I thought I would try to use it to create some kind of fake second column.

我注意到SwingX的Highlighter接口允许Highlighter返回与正在传入的那个不同的组成部分。实际上我找不到任何使用这个的例子,但是我想我会试着用它来创建一些假的第二列。

The intended result is that text in the left column should truncate where the right column starts, so I can't just use a Painter. The right column should render the same width for the whole list, which is an issue I haven't figured out yet but which doesn't seem like it will be hard.

预期的结果是左列中的文本应该在右列开始的地方截断,所以我不能只使用一个Painter。右边的列应该为整个列表呈现相同的宽度,这是我还没弄明白的问题,但看起来并不难。

As for right now though, I am finding that the row height gets compressed to be so small, you can't see any of the text.

但是现在,我发现行高度被压缩到很小,你看不到任何文本。

Here's what I mean:

我的意思:

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

Sample program:

示例程序:

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));
        }
    }

}

I'm wondering if there is a right way to use this bit of the API. I deliberately extended JRendererLabel in case that was the issue, but it seems to be something more subtle...

我想知道是否有一种正确的方法来使用这个API。我故意扩展了JRendererLabel,以防出现这种情况,但它似乎更微妙……

1 个解决方案

#1


2  

If you have a look at JRendererLabel, you will see that invalidate, revalidate, validate (and a bunch of other methods) have been set to "no operation", meaning that they no longer make notifications to the layout manager that the component should be laid out. This is done to help improve the performance of "stamping" the renderer onto the component (the JXList).

如果您查看JRendererLabel,您将看到invalidate、revalidate、validate(以及其他一些方法)已被设置为“no operation”,这意味着它们不再向布局管理器发出应该布局组件的通知。这样做是为了帮助改进将渲染器“冲压”到组件(JXList)上的性能。

Instead, use extend FixedSecondColumnRendererLabel from JPanel.

相反,使用JPanel中的extend FixedSecondColumnRendererLabel。

Instead of creating a new instance of FixedSecondColumnRendererLabel and JRendererLabel each time the method is called, you should consider optimising it so that you return the same instance, but one which is configured each time the method is called.

与每次调用方法时创建FixedSecondColumnRendererLabel和JRendererLabel的新实例不同,您应该考虑优化它,以便返回相同的实例,但每次调用方法时都配置一个实例。

Remember, this method is called for EACH row in your JXList, the more you have, the more times it will be called, the more short lived objects it will create...

记住,这个方法在JXList中的每一行都被调用,您拥有的越多,调用的时间越多,它将创建的更短的生存对象……

#1


2  

If you have a look at JRendererLabel, you will see that invalidate, revalidate, validate (and a bunch of other methods) have been set to "no operation", meaning that they no longer make notifications to the layout manager that the component should be laid out. This is done to help improve the performance of "stamping" the renderer onto the component (the JXList).

如果您查看JRendererLabel,您将看到invalidate、revalidate、validate(以及其他一些方法)已被设置为“no operation”,这意味着它们不再向布局管理器发出应该布局组件的通知。这样做是为了帮助改进将渲染器“冲压”到组件(JXList)上的性能。

Instead, use extend FixedSecondColumnRendererLabel from JPanel.

相反,使用JPanel中的extend FixedSecondColumnRendererLabel。

Instead of creating a new instance of FixedSecondColumnRendererLabel and JRendererLabel each time the method is called, you should consider optimising it so that you return the same instance, but one which is configured each time the method is called.

与每次调用方法时创建FixedSecondColumnRendererLabel和JRendererLabel的新实例不同,您应该考虑优化它,以便返回相同的实例,但每次调用方法时都配置一个实例。

Remember, this method is called for EACH row in your JXList, the more you have, the more times it will be called, the more short lived objects it will create...

记住,这个方法在JXList中的每一行都被调用,您拥有的越多,调用的时间越多,它将创建的更短的生存对象……