gpt4 book ai didi

java - JTabbedPane:选项卡位置设置为 LEFT,但图标未对齐

转载 作者:行者123 更新时间:2023-12-01 06:29:29 25 4
gpt4 key购买 nike

我有一个 JTabbedPane选项卡位置设置为 LEFT。问题是每个选项卡中的图标没有垂直对齐。

考虑这张图片:

enter image description here

如您所见,“Editar Protocolo”(第二个选项卡)的图标与“Distribuir Protocolo”(第一个选项卡)的图标不完全对齐,其他选项卡也会发生这种情况。我希望所有图标都垂直对齐到左侧。

这是我用来设置选项卡组件的代码:

...
jtabbedPane.setTabComponentAt(1, configurarJtabbedPane("Editar Protocolo", iconEditarProtocolo));
...

public JLabel configurarJtabbedPane(String title, ImageIcon icon) {
JLabel l = new JLabel(title);
l.setIcon(icon);
l.setIconTextGap(5);
l.setHorizontalTextPosition(SwingConstants.RIGHT);
return l;
}

代码摘自此问答: JTabbedPane: icon on left side of tabs .

最佳答案

What I want: the icons ALL in the LEFT, not based on the Text Size [...]



选项卡的内容以典型实现为中心,这是有道理的,因为在有效呈现选项卡之前,适合此内容所需的区域是不可预测的。由于区域取决于内容,并且不同的选项卡可能具有不同的标题长度,因此必须制定有关如何呈现这些选项卡的策略。标准是使选项卡内容居中并使选项卡区域适合此内容。当我们有一个默认的选项卡式 Pane 并在顶部放置选项卡时,我们不太关心图标/文本对齐:

top_tabbed_pane

唯一需要担心的可能是标签的长度不同,但谁在乎呢?毕竟,图标和文本是可见的,选项卡式 Pane 看起来已经足够好了。但是,当您将选项卡位置设置为 LEFT 或 RIGHT 时,情况会有所不同,并且看起来没有吸引力:

left_tabbed_pane

显然这种默认行为是一个长期存在的问题,并且有一个非常有趣的讨论 here .一些 SO 成员参与其中:@camickr、@kleopatra、@splunebob。正如在那篇文章中所讨论的,一个简单的解决方案是不可能的,并且提出了几种解决方法:基本上是自定义 UI 实现或使用面板作为渲染器并根据文本长度使用首选宽度/高度。这两种选择都涉及大量工作。

为了避免处理 UI 委托(delegate)并利用 setTabComponentAt(...)方法,我前段时间开始了一个选项卡式 Pane 扩展,我想在这里分享。该方法基于 Swing 的渲染器概念:必须生成一个组件以渲染另一个组件的部分的类,目标是提供一种灵活的机制来添加自定义选项卡组件。

我在下面使用我的自定义选项卡式 Pane 包含了一个示例,这里概述了提供上述机制所需的所有接口(interface)/类。

ITabRenderer 接口(interface)

第一步是定义一个 iterface 来提供一个合约来呈现一个标签组件。

AbstractTabRenderer 类

一个抽象类,提供基本方法来帮助 getTabRendererComponent(...)方法实现。这个抽象类具有三个主要属性:
  • prototypeText :用于定义原型(prototype)文本以生成默认渲染器组件。
  • prototypeIcon :用于定义原型(prototype)图标以生成默认渲染器。
  • horizontalTextAlignment : 选项卡的文本水平对齐方式。

  • 注意这个类是抽象的,因为它没有实现 getTabRendererComponent(...)方法。

    DefaultTabRenderer 类

    扩展 AbstractTabRenderer的具体实现类(class)。请注意,如果您想像教程演示中所示包含一个关闭按钮,那么在这个类中做一些工作就足够了。事实上,我已经这样做了,但我不会包含该部分以不扩展这篇(已经很大)的帖子。

    JXTabbedPane

    最后是选项卡式 Pane 的扩展,包括选项卡渲染器支持和覆盖 addTab(...)方法。

    例子

    我使用这些 PLAF 运行了这个示例并取得了积极的结果:
  • WindowsLookAndFeel
  • WindowsClassicLookAndFeel
  • NimbusLookAndFeel
  • 金属外观
  • Seaglass LookAndFeel

  • 另外,如果您将选项卡位置从 LEFT 切换到 TOP(默认)或 BOTTOM,那么所有选项卡仍然具有相同的宽度,从而解决了本答案第二段中描述的问题。
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Insets;
    import java.beans.PropertyChangeEvent;
    import java.beans.PropertyChangeListener;
    import java.beans.PropertyChangeSupport;
    import javax.swing.Icon;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JTabbedPane;
    import javax.swing.SwingConstants;
    import javax.swing.SwingUtilities;
    import javax.swing.UIManager;

    public class Demo {

    private void createAndShowGUI() {

    JXTabbedPane tabbedPane = new JXTabbedPane(JTabbedPane.LEFT);
    AbstractTabRenderer renderer = (AbstractTabRenderer)tabbedPane.getTabRenderer();
    renderer.setPrototypeText("This text is a prototype");
    renderer.setHorizontalTextAlignment(SwingConstants.LEADING);

    tabbedPane.addTab("Short", UIManager.getIcon("OptionPane.informationIcon"), createEmptyPanel(), "Information tool tip");
    tabbedPane.addTab("Long text", UIManager.getIcon("OptionPane.warningIcon"), createEmptyPanel(), "Warning tool tip");
    tabbedPane.addTab("This is a really long text", UIManager.getIcon("OptionPane.errorIcon"), createEmptyPanel(), "Error tool tip");

    JFrame frame = new JFrame("Demo");
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.add(tabbedPane);
    frame.pack();
    frame.setLocationByPlatform(true);
    frame.setVisible(true);

    }

    private JPanel createEmptyPanel() {
    JPanel dummyPanel = new JPanel() {

    @Override
    public Dimension getPreferredSize() {
    return isPreferredSizeSet() ?
    super.getPreferredSize() : new Dimension(400, 300);
    }

    };
    return dummyPanel;
    }

    public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
    @Override
    public void run() {
    new Demo().createAndShowGUI();
    }
    });
    }

    class JXTabbedPane extends JTabbedPane {

    private ITabRenderer tabRenderer = new DefaultTabRenderer();

    public JXTabbedPane() {
    super();
    }

    public JXTabbedPane(int tabPlacement) {
    super(tabPlacement);
    }

    public JXTabbedPane(int tabPlacement, int tabLayoutPolicy) {
    super(tabPlacement, tabLayoutPolicy);
    }

    public ITabRenderer getTabRenderer() {
    return tabRenderer;
    }

    public void setTabRenderer(ITabRenderer tabRenderer) {
    this.tabRenderer = tabRenderer;
    }

    @Override
    public void addTab(String title, Component component) {
    this.addTab(title, null, component, null);
    }

    @Override
    public void addTab(String title, Icon icon, Component component) {
    this.addTab(title, icon, component, null);
    }

    @Override
    public void addTab(String title, Icon icon, Component component, String tip) {
    super.addTab(title, icon, component, tip);
    int tabIndex = getTabCount() - 1;
    Component tab = tabRenderer.getTabRendererComponent(this, title, icon, tabIndex);
    super.setTabComponentAt(tabIndex, tab);
    }
    }

    interface ITabRenderer {

    public Component getTabRendererComponent(JTabbedPane tabbedPane, String text, Icon icon, int tabIndex);

    }

    abstract class AbstractTabRenderer implements ITabRenderer {

    private String prototypeText = "";
    private Icon prototypeIcon = UIManager.getIcon("OptionPane.informationIcon");
    private int horizontalTextAlignment = SwingConstants.CENTER;
    private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public AbstractTabRenderer() {
    super();
    }

    public void setPrototypeText(String text) {
    String oldText = this.prototypeText;
    this.prototypeText = text;
    firePropertyChange("prototypeText", oldText, text);
    }

    public String getPrototypeText() {
    return prototypeText;
    }

    public Icon getPrototypeIcon() {
    return prototypeIcon;
    }

    public void setPrototypeIcon(Icon icon) {
    Icon oldIcon = this.prototypeIcon;
    this.prototypeIcon = icon;
    firePropertyChange("prototypeIcon", oldIcon, icon);
    }

    public int getHorizontalTextAlignment() {
    return horizontalTextAlignment;
    }

    public void setHorizontalTextAlignment(int horizontalTextAlignment) {
    this.horizontalTextAlignment = horizontalTextAlignment;
    }

    public PropertyChangeListener[] getPropertyChangeListeners() {
    return propertyChangeSupport.getPropertyChangeListeners();
    }

    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
    return propertyChangeSupport.getPropertyChangeListeners(propertyName);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
    propertyChangeSupport.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
    propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
    }

    protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
    PropertyChangeListener[] listeners = getPropertyChangeListeners();
    for (int i = listeners.length - 1; i >= 0; i--) {
    listeners[i].propertyChange(new PropertyChangeEvent(this, propertyName, oldValue, newValue));
    }
    }
    }

    class DefaultTabRenderer extends AbstractTabRenderer implements PropertyChangeListener {

    private Component prototypeComponent;

    public DefaultTabRenderer() {
    super();
    prototypeComponent = generateRendererComponent(getPrototypeText(), getPrototypeIcon(), getHorizontalTextAlignment());
    addPropertyChangeListener(this);
    }

    private Component generateRendererComponent(String text, Icon icon, int horizontalTabTextAlignmen) {
    JPanel rendererComponent = new JPanel(new GridBagLayout());
    rendererComponent.setOpaque(false);

    GridBagConstraints c = new GridBagConstraints();
    c.insets = new Insets(2, 4, 2, 4);
    c.fill = GridBagConstraints.HORIZONTAL;
    rendererComponent.add(new JLabel(icon), c);

    c.gridx = 1;
    c.weightx = 1;
    rendererComponent.add(new JLabel(text, horizontalTabTextAlignmen), c);

    return rendererComponent;
    }

    @Override
    public Component getTabRendererComponent(JTabbedPane tabbedPane, String text, Icon icon, int tabIndex) {
    Component rendererComponent = generateRendererComponent(text, icon, getHorizontalTextAlignment());
    int prototypeWidth = prototypeComponent.getPreferredSize().width;
    int prototypeHeight = prototypeComponent.getPreferredSize().height;
    rendererComponent.setPreferredSize(new Dimension(prototypeWidth, prototypeHeight));
    return rendererComponent;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
    String propertyName = evt.getPropertyName();
    if ("prototypeText".equals(propertyName) || "prototypeIcon".equals(propertyName)) {
    this.prototypeComponent = generateRendererComponent(getPrototypeText(), getPrototypeIcon(), getHorizontalTextAlignment());
    }
    }
    }
    }

    截图

    金属外观

    enter image description here

    NimbusLookAndFeel

    enter image description here

    Seaglass LookAndFeel

    enter image description here

    WindowsLookAndFeel

    enter image description here

    关于java - JTabbedPane:选项卡位置设置为 LEFT,但图标未对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26308859/

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