📄 basictabbedpaneui.java
字号:
map.put("navigateNext", new NextAction()); map.put("navigatePrevious", new PreviousAction()); map.put("navigateRight", new RightAction()); map.put("navigateLeft", new LeftAction()); map.put("navigateUp", new UpAction()); map.put("navigateDown", new DownAction()); map.put("navigatePageUp", new PageUpAction()); map.put("navigatePageDown", new PageDownAction()); map.put("requestFocus", new RequestFocusAction()); map.put("requestFocusForVisibleComponent", new RequestFocusForVisibleAction()); map.put("setSelectedIndex", new SetSelectedIndexAction()); map.put("scrollTabsForwardAction", new ScrollTabsForwardAction()); map.put("scrollTabsBackwardAction",new ScrollTabsBackwardAction()); return map; } protected void uninstallKeyboardActions() { SwingUtilities.replaceUIActionMap(tabPane, null); SwingUtilities.replaceUIInputMap(tabPane, JComponent. WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_FOCUSED, null); } /** * Reloads the mnemonics. This should be invoked when a memonic changes, * when the title of a mnemonic changes, or when tabs are added/removed. */ private void updateMnemonics() { resetMnemonics(); for (int counter = tabPane.getTabCount() - 1; counter >= 0; counter--) { int mnemonic = tabPane.getMnemonicAt(counter); if (mnemonic > 0) { addMnemonic(counter, mnemonic); } } } /** * Resets the mnemonics bindings to an empty state. */ private void resetMnemonics() { if (mnemonicToIndexMap != null) { mnemonicToIndexMap.clear(); mnemonicInputMap.clear(); } } /** * Adds the specified mnemonic at the specified index. */ private void addMnemonic(int index, int mnemonic) { if (mnemonicToIndexMap == null) { initMnemonics(); } mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK), "setSelectedIndex"); mnemonicToIndexMap.put(new Integer(mnemonic), new Integer(index)); } /** * Installs the state needed for mnemonics. */ private void initMnemonics() { mnemonicToIndexMap = new Hashtable(); mnemonicInputMap = new InputMapUIResource(); mnemonicInputMap.setParent(SwingUtilities.getUIInputMap(tabPane, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)); SwingUtilities.replaceUIInputMap(tabPane, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, mnemonicInputMap); }// Geometry public Dimension getPreferredSize(JComponent c) { // Default to LayoutManager's preferredLayoutSize return null; } public Dimension getMinimumSize(JComponent c) { // Default to LayoutManager's minimumLayoutSize return null; } public Dimension getMaximumSize(JComponent c) { // Default to LayoutManager's maximumLayoutSize return null; }// UI Rendering public void paint(Graphics g, JComponent c) { int tc = tabPane.getTabCount(); if (tabCount != tc) { tabCount = tc; updateMnemonics(); } int selectedIndex = tabPane.getSelectedIndex(); int tabPlacement = tabPane.getTabPlacement(); ensureCurrentLayout(); // Paint tab area // If scrollable tabs are enabled, the tab area will be // painted by the scrollable tab panel instead. // if (!scrollableTabLayoutEnabled()) { // WRAP_TAB_LAYOUT paintTabArea(g, tabPlacement, selectedIndex); } // Paint content border paintContentBorder(g, tabPlacement, selectedIndex); } /** * Paints the tabs in the tab area. * Invoked by paint(). * The graphics parameter must be a valid <code>Graphics</code> * object. Tab placement may be either: * <code>JTabbedPane.TOP</code>, <code>JTabbedPane.BOTTOM</code>, * <code>JTabbedPane.LEFT</code>, or <code>JTabbedPane.RIGHT</code>. * The selected index must be a valid tabbed pane tab index (0 to * tab count - 1, inclusive) or -1 if no tab is currently selected. * The handling of invalid parameters is unspecified. * * @param g the graphics object to use for rendering * @param tabPlacement the placement for the tabs within the JTabbedPane * @param selectedIndex the tab index of the selected component * * @since 1.4 */ protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) { int tabCount = tabPane.getTabCount(); Rectangle iconRect = new Rectangle(), textRect = new Rectangle(); Rectangle clipRect = g.getClipBounds(); // Paint tabRuns of tabs from back to front 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 (rects[j].intersects(clipRect)) { paintTab(g, tabPlacement, rects, j, iconRect, textRect); } } } // Paint selected tab if its in the front run // since it may overlap other tabs if (selectedIndex >= 0 && getRunForTab(tabCount, selectedIndex) == 0) { if (rects[selectedIndex].intersects(clipRect)) { paintTab(g, tabPlacement, rects, selectedIndex, iconRect, textRect); } } } protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, int tabIndex, Rectangle iconRect, Rectangle textRect) { Rectangle tabRect = rects[tabIndex]; int selectedIndex = tabPane.getSelectedIndex(); boolean isSelected = selectedIndex == tabIndex; Graphics2D g2 = null; Polygon cropShape = null; Shape save = null; int cropx = 0; int cropy = 0; if (scrollableTabLayoutEnabled()) { if (g instanceof Graphics2D) { g2 = (Graphics2D)g; // Render visual for cropped tab edge... Rectangle viewRect = tabScroller.viewport.getViewRect(); int cropline; switch(tabPlacement) { case LEFT: case RIGHT: cropline = viewRect.y + viewRect.height; if ((tabRect.y < cropline) && (tabRect.y + tabRect.height > cropline)) { cropShape = createCroppedTabClip(tabPlacement, tabRect, cropline); cropx = tabRect.x; cropy = cropline-1; } break; case TOP: case BOTTOM: default: cropline = viewRect.x + viewRect.width; if ((tabRect.x < cropline) && (tabRect.x + tabRect.width > cropline)) { cropShape = createCroppedTabClip(tabPlacement, tabRect, cropline); cropx = cropline-1; cropy = tabRect.y; } } if (cropShape != null) { save = g2.getClip(); g2.clip(cropShape); } } } paintTabBackground(g, tabPlacement, tabIndex, tabRect.x, tabRect.y, tabRect.width, tabRect.height, isSelected); paintTabBorder(g, tabPlacement, tabIndex, tabRect.x, tabRect.y, tabRect.width, tabRect.height, isSelected); String title = tabPane.getTitleAt(tabIndex); Font font = tabPane.getFont(); FontMetrics metrics = g.getFontMetrics(font); Icon icon = getIconForTab(tabIndex); layoutLabel(tabPlacement, metrics, tabIndex, title, icon, tabRect, iconRect, textRect, isSelected); paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected); paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); paintFocusIndicator(g, tabPlacement, rects, tabIndex, iconRect, textRect, isSelected); if (cropShape != null) { paintCroppedTabEdge(g, tabPlacement, tabIndex, isSelected, cropx, cropy); g2.setClip(save); } } /* This method will create and return a polygon shape for the given tab rectangle * which has been cropped at the specified cropline with a torn edge visual. * e.g. A "File" tab which has cropped been cropped just after the "i": * ------------- * | ..... | * | . | * | ... . | * | . . | * | . . | * | . . | * -------------- * * The x, y arrays below define the pattern used to create a "torn" edge * segment which is repeated to fill the edge of the tab. * For tabs placed on TOP and BOTTOM, this righthand torn edge is created by * line segments which are defined by coordinates obtained by * subtracting xCropLen[i] from (tab.x + tab.width) and adding yCroplen[i] * to (tab.y). * For tabs placed on LEFT or RIGHT, the bottom torn edge is created by * subtracting xCropLen[i] from (tab.y + tab.height) and adding yCropLen[i] * to (tab.x). */ private int xCropLen[] = {1,1,0,0,1,1,2,2}; private int yCropLen[] = {0,3,3,6,6,9,9,12}; private static final int CROP_SEGMENT = 12; private Polygon createCroppedTabClip(int tabPlacement, Rectangle tabRect, int cropline) { int rlen = 0; int start = 0; int end = 0; int ostart = 0; switch(tabPlacement) { case LEFT: case RIGHT: rlen = tabRect.width; start = tabRect.x; end = tabRect.x + tabRect.width; ostart = tabRect.y; break; case TOP: case BOTTOM: default: rlen = tabRect.height; start = tabRect.y; end = tabRect.y + tabRect.height; ostart = tabRect.x; } int rcnt = rlen/CROP_SEGMENT; if (rlen%CROP_SEGMENT > 0) { rcnt++; } int npts = 2 + (rcnt*8); int xp[] = new int[npts]; int yp[] = new int[npts]; int pcnt = 0; xp[pcnt] = ostart; yp[pcnt++] = end; xp[pcnt] = ostart; yp[pcnt++] = start; for(int i = 0; i < rcnt; i++) { for(int j = 0; j < xCropLen.length; j++) { xp[pcnt] = cropline - xCropLen[j]; yp[pcnt] = start + (i*CROP_SEGMENT) + yCropLen[j]; if (yp[pcnt] >= end) { yp[pcnt] = end; pcnt++; break; } pcnt++; } } if (tabPlacement == JTabbedPane.TOP || tabPlacement == JTabbedPane.BOTTOM) { return new Polygon(xp, yp, pcnt); } else { // LEFT or RIGHT return new Polygon(yp, xp, pcnt); } } /* If tabLayoutPolicy == SCROLL_TAB_LAYOUT, this method will paint an edge * indicating the tab is cropped in the viewport display */ private void paintCroppedTabEdge(Graphics g, int tabPlacement, int tabIndex, boolean isSelected, int x, int y) { switch(tabPlacement) { case LEFT: case RIGHT: int xx = x; g.setColor(shadow); while(xx <= x+rects[tabIndex].width) { for (int i=0; i < xCropLen.length; i+=2) { g.drawLine(xx+yCropLen[i],y-xCropLen[i], xx+yCropLen[i+1]-1,y-xCropLen[i+1]); } xx+=CROP_SEGMENT; } break; case TOP: case BOTTOM: default: int yy = y; g.setColor(shadow); while(yy <= y+rects[tabIndex].height) { for (int i=0; i < xCropLen.length; i+=2) { g.drawLine(x-xCropLen[i],yy+yCropLen[i], x-xCropLen[i+1],yy+yCropLen[i+1]-1); } yy+=CROP_SEGMENT; } } } protected void layoutLabel(int tabPlacement, FontMetrics metrics, int tabIndex, String title, Icon icon, Rectangle tabRect, Rectangle iconRect, Rectangle textRect, boolean isSelected ) { textRect.x = textRect.y = iconRect.x = iconRect.y = 0; View v = getTextViewForTab(tabIndex); if (v != null) { tabPane.putClientProperty("html", v); } SwingUtilities.layoutCompoundLabel((JComponent) tabPane, metrics, title, icon, SwingUtilities.CENTER, SwingUtilities.CENTER, SwingUtilities.CENTER, SwingUtilities.TRAILING, tabRect, iconRect, textRect, textIconGap); tabPane.putClientProperty("html", null);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -