Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 选项卡在自定义JTabbedPane中的呈现顺序_Java_Swing_Tabs_Rendering_Jtabbedpane - Fatal编程技术网

Java 选项卡在自定义JTabbedPane中的呈现顺序

Java 选项卡在自定义JTabbedPane中的呈现顺序,java,swing,tabs,rendering,jtabbedpane,Java,Swing,Tabs,Rendering,Jtabbedpane,大家好,我在2017年的第一篇帖子里祝大家新年快乐!:) 问题解释 我目前正在编写一个定制的JTabbedPane,一切正常,但在呈现选项卡时,我遇到了一个意想不到的(对我来说)设计问题 问题是,所有未选择的选项卡都从左到右渲染,并且由于我使用GeneralPath类自定义的形状超出了默认选项卡边界,因此渲染的每个选项卡都与左侧选项卡的一部分重叠。您可以在下图中进行检查: 如您所见,选定的选项卡与右侧的任何选项卡重叠,但未选定的选项卡重叠,如命名的“CustomPanel2”在下一个选项卡之前

大家好,我在2017年的第一篇帖子里祝大家新年快乐!:)

问题解释 我目前正在编写一个定制的
JTabbedPane
,一切正常,但在呈现选项卡时,我遇到了一个意想不到的(对我来说)设计问题

问题是,所有未选择的选项卡都从左到右渲染,并且由于我使用
GeneralPath
类自定义的形状超出了默认选项卡边界,因此渲染的每个选项卡都与左侧选项卡的一部分重叠。您可以在下图中进行检查:

如您所见,选定的选项卡与右侧的任何选项卡重叠,但未选定的选项卡重叠,如命名的“CustomPanel2”在下一个选项卡之前呈现,依此类推

问题: 我在一篇帖子中看到,我正在使用
BasicTabbedPaneUI
类中的
paintTab
方法,但我不知道如何实现这一点,因此我希望您向我展示渲染选项卡的正确方法,以便在Google Chrome中获得类似选项卡的内容,如下所示:

提前谢谢你,祝你度过愉快的一天!;)


PD:我认为没有相关的代码可以添加。如果您需要它,请向我索要。

如何尝试将未选中的选项卡形状设置为五角大楼

注意:当设置了
JTabbedPane#setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT)
JTabbedPane#setTabPlacement(JTabbedPane.BOTTOM)
时,此示例不进行测试:

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class TabsOverlapTest {
  private JComponent makeUI() {
    Color selectedTabColor = UIManager.getColor("TabbedPane.selected");
    Color tabBackgroundColor = Color.LIGHT_GRAY;
    Color tabBorderColor = Color.GRAY;
    UIManager.put("TabbedPane.highlight", tabBorderColor);

    JTabbedPane tabs = new JTabbedPane();
    tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    tabs.setUI(new BasicTabbedPaneUI() {
      @Override protected void paintTabBorder(
          Graphics g, int tabPlacement, int tabIndex,
          int x, int y, int w, int h, boolean isSelected) {
      }
      @Override protected void paintFocusIndicator(
          Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex,
          Rectangle iconRect, Rectangle textRect, boolean isSelected) {
      }
      @Override protected void paintContentBorderTopEdge(
          Graphics g, int tabPlacement, int selectedIndex,
          int x, int y, int w, int h) {
        super.paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
        Rectangle selRect = getTabBounds(selectedIndex, calcRect);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(selectedTabColor);
        g2.drawLine(selRect.x - 2, y, selRect.x + selRect.width + 2, y);
        g2.dispose();
      }
      @Override protected void paintTabBackground(
          Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h,
          boolean isSelected) {

        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int a = isSelected ? 0 : 1;

        GeneralPath shape = new GeneralPath();
        shape.moveTo(x - 3, y + h);
        shape.lineTo(x + 3, y + a);
        shape.lineTo(x + w - 3, y + a);
        shape.lineTo(x + w + 3, y + h);
        shape.closePath();
        g2.setColor(isSelected ? selectedTabColor : tabBackgroundColor);
        g2.fill(shape);

        GeneralPath border = new GeneralPath();
        if (isSelected || tabIndex == 0) {
          border.moveTo(x - 3, y + h - 1);
        } else {
          border.moveTo(x + 3, y + h - 1);
          border.lineTo(x, (y + h - 1) / 2);
        }
        border.lineTo(x + 3, y + a);
        border.lineTo(x + w - 3, y + a);
        border.lineTo(x + w + 3, y + h - 1);

        g2.setColor(tabBorderColor);
        g2.draw(border);

        g2.dispose();
      }
    });
    tabs.addTab("JTextArea",  new JScrollPane(new JTextArea()));
    tabs.addTab("JTree",      new JScrollPane(new JTree()));
    tabs.addTab("JButton",    new JButton("button"));
    tabs.addTab("JSplitPane", new JSplitPane());
    return tabs;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TabsOverlapTest().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

如果尝试将未选中的选项卡形状设置为五边形,会怎么样

注意:当设置了
JTabbedPane#setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT)
JTabbedPane#setTabPlacement(JTabbedPane.BOTTOM)
时,此示例不进行测试:

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;

public class TabsOverlapTest {
  private JComponent makeUI() {
    Color selectedTabColor = UIManager.getColor("TabbedPane.selected");
    Color tabBackgroundColor = Color.LIGHT_GRAY;
    Color tabBorderColor = Color.GRAY;
    UIManager.put("TabbedPane.highlight", tabBorderColor);

    JTabbedPane tabs = new JTabbedPane();
    tabs.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
    tabs.setUI(new BasicTabbedPaneUI() {
      @Override protected void paintTabBorder(
          Graphics g, int tabPlacement, int tabIndex,
          int x, int y, int w, int h, boolean isSelected) {
      }
      @Override protected void paintFocusIndicator(
          Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex,
          Rectangle iconRect, Rectangle textRect, boolean isSelected) {
      }
      @Override protected void paintContentBorderTopEdge(
          Graphics g, int tabPlacement, int selectedIndex,
          int x, int y, int w, int h) {
        super.paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h);
        Rectangle selRect = getTabBounds(selectedIndex, calcRect);
        Graphics2D g2 = (Graphics2D) g.create();
        g2.setColor(selectedTabColor);
        g2.drawLine(selRect.x - 2, y, selRect.x + selRect.width + 2, y);
        g2.dispose();
      }
      @Override protected void paintTabBackground(
          Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h,
          boolean isSelected) {

        Graphics2D g2 = (Graphics2D) g.create();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int a = isSelected ? 0 : 1;

        GeneralPath shape = new GeneralPath();
        shape.moveTo(x - 3, y + h);
        shape.lineTo(x + 3, y + a);
        shape.lineTo(x + w - 3, y + a);
        shape.lineTo(x + w + 3, y + h);
        shape.closePath();
        g2.setColor(isSelected ? selectedTabColor : tabBackgroundColor);
        g2.fill(shape);

        GeneralPath border = new GeneralPath();
        if (isSelected || tabIndex == 0) {
          border.moveTo(x - 3, y + h - 1);
        } else {
          border.moveTo(x + 3, y + h - 1);
          border.lineTo(x, (y + h - 1) / 2);
        }
        border.lineTo(x + 3, y + a);
        border.lineTo(x + w - 3, y + a);
        border.lineTo(x + w + 3, y + h - 1);

        g2.setColor(tabBorderColor);
        g2.draw(border);

        g2.dispose();
      }
    });
    tabs.addTab("JTextArea",  new JScrollPane(new JTextArea()));
    tabs.addTab("JTree",      new JScrollPane(new JTree()));
    tabs.addTab("JButton",    new JButton("button"));
    tabs.addTab("JSplitPane", new JSplitPane());
    return tabs;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TabsOverlapTest().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

好的,我最终通过重写
basictabedpaneui
类中的
paintTabArea
方法找到了解决方案

默认代码为:

protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
    int tabCount = tabPane.getTabCount();

    Rectangle iconRect = new Rectangle(),
              textRect = new Rectangle();
    Rectangle clipRect = g.getClipBounds();

    for (int i = runCount - 1; i >= 0; i--) {
        int start = tabRuns[i];
        int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
        int end = (next != 0? next - 1: tabCount - 1);
        for (int j = start; j <= end; j++) {
            if (j != selectedIndex && rects[j].intersects(clipRect)) {
                paintTab(g, tabPlacement, rects, j, iconRect, textRect);
            }
        }
    }

    if (selectedIndex >= 0 && rects[selectedIndex].intersects(clipRect)) {
        paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect);
    }

}
protectedvoid paintTabArea(图形g、int-tabplace、int-selectedIndex){
int tabCount=tabPane.getTabCount();
矩形iconRect=新矩形(),
textRect=新矩形();
矩形clipRect=g.getClipBounds();
对于(int i=runCount-1;i>=0;i--){
int start=tabRuns[i];
int next=tabRuns[(i==runCount-1)?0:i+1];
int end=(next!=0?next-1:tabCount-1);
对于(int j=start;j=0&&rects[selectedIndex]。相交(clipRect)){
paintTab(g、tabPlacement、rects、selectedIndex、iconRect、textRect);
}
}
在第二个
for
语句中,您可以看到条件:


(int j=start;j=start;j--)

好吧,我最终通过重写
basictabedpaneui
类中的
paintTabArea
方法找到了解决方案

默认代码为:

protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
    int tabCount = tabPane.getTabCount();

    Rectangle iconRect = new Rectangle(),
              textRect = new Rectangle();
    Rectangle clipRect = g.getClipBounds();

    for (int i = runCount - 1; i >= 0; i--) {
        int start = tabRuns[i];
        int next = tabRuns[(i == runCount - 1)? 0 : i + 1];
        int end = (next != 0? next - 1: tabCount - 1);
        for (int j = start; j <= end; j++) {
            if (j != selectedIndex && rects[j].intersects(clipRect)) {
                paintTab(g, tabPlacement, rects, j, iconRect, textRect);
            }
        }
    }

    if (selectedIndex >= 0 && rects[selectedIndex].intersects(clipRect)) {
        paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect);
    }

}
protectedvoid paintTabArea(图形g、int-tabplace、int-selectedIndex){
int tabCount=tabPane.getTabCount();
矩形iconRect=新矩形(),
textRect=新矩形();
矩形clipRect=g.getClipBounds();
对于(int i=runCount-1;i>=0;i--){
int start=tabRuns[i];
int next=tabRuns[(i==runCount-1)?0:i+1];
int end=(next!=0?next-1:tabCount-1);
对于(int j=start;j=0&&rects[selectedIndex]。相交(clipRect)){
paintTab(g、tabPlacement、rects、selectedIndex、iconRect、textRect);
}
}
在第二个
for
语句中,您可以看到条件:


(int j=start;j=start;j--)

也许你应该看看
basictabedpaneui
paintTabArea
paintTab
方法的源代码。谢谢@explv。我一直在努力学习这个类,也许我被卡住了,但我不明白它到底是如何工作的。为了把事情做好,我只是在寻找合适的步骤也许你应该看看
basictabedpaneui
Thank you@explv中
paintTabArea
paintTab
方法的源代码。我一直在努力学习这个类,也许我被卡住了,但我不明白它到底是如何工作的。为了把事情做好,我只是在寻找suita这可能是一个很好的解决方案,但我的老板让我做那个具体的形状(如问题的第一张图片所示),因此,尝试表示这样的形状可能更难,效率也不高,我想是的。我想找到一种方法来编辑渲染顺序或类似的东西会很好。嗨!谢谢@aterai。这可能是一个很好的解决方案,但我的老板让我做那个具体的形状(如问题的第一张图片所示),因此,尝试表示这样的形状可能更难,效率也不高,我想是的。我想找到一种方法来编辑渲染顺序或类似的东西会很好。