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

[…]

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

唯一关心的可能是具有不同长度的标签,但是谁在乎呢?毕竟,图标和文本是可见的,并且选项卡式窗格看起来足够好.但是,将选项卡的位置设置为LEFT或RIGHT时,情况会有所不同,并且看起来不那么吸引人:

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

为了避免与UI委托打交道并利用setTabComponentAt(…)方法,我前段时间已开始在此处共享一个选项卡式窗格扩展.该方法基于Swing的renderer概念:必须生成一个组件以渲染另一个组件的零件的类,目标是提供一种灵活的机制来添加自定义选项卡组件.

我使用自定义选项卡式窗格在下面提供了一个示例,这是提供上述机制所需的所有接口/类的概述.

ITabRenderer界面

第一步是定义一个Iterface,以提供合同来渲染Tab组件.

AbstractTabRenderer类

提供基本方法以帮助实现getTabRendererComponent(…)方法的抽象类.该抽象类具有三个主要属性:

> prototypeText:用于定义原型文本以生成默认渲染器组件.

> prototypeIcon:用于定义原型图标以生成默认渲染器.

> horizo??ntalTextAlignment:制表符的文本水平对齐方式.

请注意,此类是抽象的,因为它没有实现getTabRendererComponent(…)方法.

DefaultTabRenderer类

通过扩展AbstractTabRenderer类的具体实现.请注意,如果您想包括一个如教程演示中所示的关闭按钮,那么在此类中进行一些工作就足够了.事实上,我已经这样做了,但是我不会包括不扩展此(已经很大)帖子的那一部分.

JXTabbedPane

最后,选项卡式窗格的扩展包括选项卡渲染器支持并覆盖addTab(…)方法.

我使用这些PLAF运行了这个示例,并获得了积极的结果:

> WindowsLookAndFeel

> WindowsClassicLookAndFeel

>雨云LookAndFeel

> MetalLookAndFeel

> SeaglassLookAndFeel

另外,如果将选项卡的位置从“左”切换到“顶部”(默认)或“底部”,则所有选项卡的宽度仍然相同,从而解决了此答案第二段中所述的问题.

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

}

}

}

}

截图

MetalLookAndFeel

NimbusLookAndFeel

SeaglassLookAndFeel

WindowsLookAndFeel

java 选项卡放左边_java-JTabbedPane:选项卡位置设置为LEFT但图标...相关推荐

  1. java按钮位置_java窗口按钮位置设置

    java窗口按钮位置设置 代码如下: package Day08; import java.awt.BorderLayout; import javax.swing.JButton; import j ...

  2. java scrollpane放按钮_java – 如何在BoxLayout上放置scrollPane?

    我想让我的JFrame有一个BoxLayout能够有一个滚动窗格,所以我可以继续添加组,如果它是收据或发票打印机.有没有办法添加ScrollPane? 问题:如何将ScrollPane添加到JFram ...

  3. java slf4j日志级别_java - 在slf4j中设置运行时消息的日志级别 - 堆栈内存溢出

    ===============>>#1 票数:41 已采纳 使用slf4j无法做到这slf4j . 我想,缺少这个功能的原因是,几乎不可能为slf4j构建一个Level类型,它可以有效地映 ...

  4. java背景颜色代码_java窗口背景颜色设置

    窗口背景颜色是指直接调用JFrame或者Frame的setBackground(Color color)方法设置后显示出来的颜色. 如果直接调用这个方法后,的确设置了背景颜色,但看到的却不是直接的JF ...

  5. java图形界面设置背景_java窗口背景颜色设置

    详细内容 窗口背景颜色是指直接调用JFrame或者Frame的setBackground(Color color)方法设置后显示出来的颜色. 如果直接调用这个方法后,的确设置了背景颜色,但看到的却不是 ...

  6. java jbutton 背景颜色_java – 在Windows上设置JButton背景颜色

    我有一个JButton,我想将背景设置为一种颜色. JButton button = new JButton(); button.setVisible(true); button.setPreferr ...

  7. java线程池参数_java线程池参数设置原则,如何设置线程池参数比较合理?

    线程池的参数应该怎样设置呢?相信对于很多的人来说这也是一个比较难的问题,下面就让我们一起来解决一下,究竟应该如何设置线程池的参数才是最合理的吧! 首先在设置参数的时候,有以下的几点是我们需要考虑到的! ...

  8. java对象前后改变_java对象改变而不设置它们

    我想了解下面的代码是如何工作的: public class Sample { public static void main(String[] args) { Name defaultName = n ...

  9. java 更改屏幕分辨率_Java 多屏(双屏)设置屏幕显示器分辨率方法代码(SetRes)

    1.SetRes下载 2.修改单屏代码 将下载的SetRes.exe拷到当前目录即可//String homeDirectory = System.getProperty("user.hom ...

最新文章

  1. Hive的伴奏_Position Music顶级背景音乐合集243CD
  2. hue是不是集成了oozie_在hue里面集成spark2,使用oozie的调度
  3. 力扣679.24点游戏
  4. python信息安全书籍_信息安全从业者书单推荐
  5. 中国首张5G电话卡推出,DMA基金会持续为5G助力。
  6. 全国程序员工资最新统计来了,平均 14,542 元!
  7. 计算机键盘英语单词怎么写,输入单词_如何用电脑键盘打出英文单词需要那种只要一个字母就可以自己弹出单词的那种_淘题吧...
  8. 【分享】微信H5游戏制作教程,用唤境引擎轻松开发微信AVG小游戏
  9. Android分享wifi给电脑,使用Android手机共享手机网络给PC上网
  10. 古墓丽影10linux,《古墓丽影:崛起》Linux 版上架 Steam
  11. Bullshit Bingo
  12. 利用Cloudflare Workers部署臭鼬在线接头霸王项目实例
  13. C语言的access函数的用法
  14. Codeforces #308 C. Vanya and Scales
  15. Linux内核基础篇——常用调试技巧汇总
  16. VF03发票凭证增强
  17. arm powerpc mips dsp
  18. 取消Outlook脱机工作
  19. keil提示No ULINK Device found应该如何解决
  20. javaweb JAVAJSP高校学生宿舍管理系统JSP宿舍管理系统学生公寓管理系统校园宿舍管理

热门文章

  1. 微信公众号登录和获得access_token和发送模板消息
  2. linux禅道在线迁移,禅道从windows迁移到linux
  3. [netfilter]-ip_rcv包转发流程
  4. Docker Swarm 练习:投票 App
  5. 生成.bks格式文件
  6. amcharts图表使用总结
  7. 计算机主板复位电路的组成,主板复位电路图解 - 主板知识
  8. 很多人知道外包的种种不好,但还是选择去外包,这是为什么呢?
  9. c语言化验诊断题目,医学检验技师模拟考试题(含答案)
  10. 虚拟存储器和cache的异同