Java 如何使用SwingX';是Highlighter返回不同的渲染器组件吗?

Java 如何使用SwingX';是Highlighter返回不同的渲染器组件吗?,java,swing,swingx,swingx-highlighter,Java,Swing,Swingx,Swingx Highlighter,我注意到SwingX的荧光笔接口允许荧光笔返回与传入的组件不同的组件。我实际上找不到任何这样的例子,但我想我会尝试用它来创建某种虚假的第二个专栏 预期的结果是,左列中的文本应该截断右列开始的位置,因此我不能只使用画笔。右边的列应该为整个列表呈现相同的宽度,这是一个我还没有弄清楚的问题,但这似乎并不难 至于现在,我发现行高度被压缩到很小,你看不到任何文本 我的意思是: 示例程序: import java.awt.BorderLayout; import java.awt.Component;

我注意到SwingX的
荧光笔
接口允许荧光笔返回与传入的组件不同的组件。我实际上找不到任何这样的例子,但我想我会尝试用它来创建某种虚假的第二个专栏

预期的结果是,左列中的文本应该截断右列开始的位置,因此我不能只使用
画笔
。右边的列应该为整个列表呈现相同的宽度,这是一个我还没有弄清楚的问题,但这似乎并不难

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

我的意思是:

示例程序:

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

}
导入java.awt.BorderLayout;
导入java.awt.Component;
导入javax.swing.DefaultListModel;
导入javax.swing.GroupLayout;
导入javax.swing.JFrame;
导入javax.swing.JScrollPane;
导入javax.swing.LayoutStyle;
导入javax.swing.SwingUtilities;
导入org.jdesktop.swingx.JXList;
导入org.jdesktop.swingx.decorator.AbstractHighlighter;
导入org.jdesktop.swingx.decorator.ComponentAdapter;
导入org.jdesktop.swingx.renderer.jrenderLabel;
导入org.jdesktop.swingx.renderer.StringValue;
公共类RenderTest实现可运行
{
公共静态void main(字符串[]args)
{
invokeLater(新的rendertest());
}
@凌驾
公开募捐
{
JFrame=新JFrame(“荧光灯测试”);
JXList list=新的JXList();
DefaultListModel listModel=新的DefaultListModel();
listModel.addElement(“一”);
listModel.addElement(“两个”);
listModel.addElement(“三”);
list.setModel(listModel);
list.setVisibleRowCount(8);
setPrototypeCellValue(“某些字符串”);
list.addHighlighter(新的AddSecondColumnHighlighter(v->((String)v.toUpperCase());
JScrollPane listScroll=新的JScrollPane(列表);
frame.setLayout(新的BorderLayout());
frame.add(列表滚动、边框布局、中间);
frame.pack();
frame.setVisible(true);
}
私有静态类AddSecondColumnHighlighter扩展了AbstractHighlighter
{
私有最终StringValue secondColumnStringValue;
public addSecondColumnShighlighter(StringValue secondColumnStringValue)
{
this.secondColumnStringValue=secondColumnStringValue;
}
@凌驾
受保护的组件doHighlight(组件组件、组件适配器)
{
JrenderLabel rightColumn=新的JrenderLabel();
setText(secondColumnStringValue.getString(adapter.getValue());
返回新的FixedSecondColumnRenderLabel(组件,右列);
}
}
私有静态类FixedSecondColumnRenderLabel扩展JRenderLabel
{
private FixedSecondColumnRenderLabel(组件引导组件、组件跟踪组件)
{
GroupLayout布局=新的GroupLayout(本);
设置布局(布局);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addComponent(leadingComponent、GroupLayout.DEFAULT\u SIZE、GroupLayout.DEFAULT\u SIZE、Short.MAX\u值)
.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(trailingComponent));
layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
.addComponent(引导组件)
.addComponent(trailingComponent));
}
}
}

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

如果您查看
jrenderlabel
,您将看到
无效
重新验证
验证
(以及一系列其他方法)已设置为“无操作”,这意味着它们不再向布局管理器发出组件应布局的通知。这样做是为了帮助提高将渲染器“标记”到组件(JXList
)上的性能

相反,请从
JPanel
使用扩展
fixedsecondColumnRenderLabel

<> P>而不是创建一个新实例:FixEddieCalnReDeRelabyLabele/Cuff>和JReNeReRealdLabele>代码>每次调用该方法时,您应该考虑优化它,以便返回同一个实例,但每次调用该方法时配置一个实例。
请记住,此方法是为
JXList
中的每一行调用的,调用的次数越多,创建的对象越短……

我担心使用
JPanel
,因为它们在注释中指出,如果不覆盖所有这些方法,会出现性能问题,我们以前也看到,在制作自定义复选框渲染器时,复选框也会出现类似的性能问题。不过,我肯定会做实例共享。是的,这是一个确定的问题,但在您的情况下,您需要此功能,因为每次更改
字符串
/text时,您都需要重新验证布局,但是,在组件实际为绘制调整大小之前,您无法执行此操作……您可以覆盖
setBounds
方法,并强制每次调用
doLayout
,作为折衷方案……这可能是实际执行此操作的方法。或者我保持我自己的layoutDirty状态,从paintComponent开始,我确信组件正在被绘制。从技术上讲,组件并不总是被绘制的