How To Enable/Disable Buttons Of JSplitPane
Posted by blogmeister on
March 2, 2013
I thought that calling setEnabled() on a JSplitPane object will also enable/disable the divider buttons. I found out it does not. Only the divider gets disabled so when you click on the buttons, the JSplitPane will still be resized.
To get a reference on the buttons, you make use of the BasicSplitPaneUI class, cast it and call setEnabled() on them.
Check the code below.
|
1 2 3 |
BasicSplitPaneUI ui = (BasicSplitPaneUI) mySplitPane.getUI(); ((JButton) ui.getDivider().getComponent(0)).setEnabled(false); ((JButton) ui.getDivider().getComponent(1)).setEnabled(false); |
That should let you enable or disable the buttons of the JSplitPane divider.
Share the post "How To Enable/Disable Buttons Of JSplitPane"
tags: basicsplitpaneuI, button, divider, jbutton, jsplitpane
No Comments
Android: Fix Alternative Thin & Thick Lines of ListView
Posted by blogmeister on
May 27, 2011
What if the divider lines of your ListView look like this? You wonder why when you clearly specified in your XML that the divider height should only be 1px. So why is it thick in alternating rows?
I am not saying this is the only solution but there is a big chance that this is the one. Check your AndroidManifest.xml and see if you have set a minimum and maximum version SDK required. If not, then add it. The divider height for your ListView will all be 1px.
Check the code below.
|
1 |
<uses-sdk android:maxSdkVersion="8" android:minSdkVersion="4" /> |
On a side note, this is also the solution for rating stars that are not displayed in crisp detail instead showing you blurred edges.
Share the post "Android: Fix Alternative Thin & Thick Lines of ListView"
tags: divider, Divider Lines, height, listview, thick, thin
No Comments
Metal Look & Feel For JSplitPane’s Divider
Posted by blogmeister on
January 21, 2010
As per version 1.6 of the JDK, there is no MetalSplitPaneDivider class in the API although if you set the JSplitPane‘s UI to use the MetalSplitPaneUI class, it will set the divider’s look and feel to metal. You may want to get access to the divider object like the left and right buttons and by using the BasicSplitPaneDivider class, the divider will not have a metal look and feel.
Luckily, while surfing through the web, I came across the work of Steve Wilson, Tom Santos and Ralph Kar who created two classes: MetalBumps and MetalSplitPaneDivider: so you could have access to the divider object and have a metal look and feel.
MetalBumps.java
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
import java.awt.*; import java.awt.image.*; import java.util.Enumeration; import java.util.Vector; import javax.swing.*; import javax.swing.plaf.metal.MetalLookAndFeel; class MetalBumps implements Icon { static final Color ALPHA = new Color(0, 0, 0, 0); protected int xBumps; protected int yBumps; protected Color topColor; protected Color shadowColor; protected Color backColor; protected static Vector buffers = new Vector(); protected BumpBuffer buffer; public MetalBumps( Dimension bumpArea ) { this( bumpArea.width, bumpArea.height ); } public MetalBumps( int width, int height ) { this(width, height, MetalLookAndFeel.getPrimaryControlHighlight(), MetalLookAndFeel.getPrimaryControlDarkShadow(), MetalLookAndFeel.getPrimaryControlShadow()); } /** * Creates MetalBumps of the specified size with the specified colors. * If <code>newBackColor</code> is null, the background will be * transparent. */ public MetalBumps( int width, int height, Color newTopColor, Color newShadowColor, Color newBackColor ) { setBumpArea( width, height ); setBumpColors( newTopColor, newShadowColor, newBackColor ); } private BumpBuffer getBuffer(GraphicsConfiguration gc, Color aTopColor, Color aShadowColor, Color aBackColor) { if (buffer != null && buffer.hasSameConfiguration( gc, aTopColor, aShadowColor, aBackColor)) { return buffer; } BumpBuffer result = null; Enumeration elements = buffers.elements(); while ( elements.hasMoreElements() ) { BumpBuffer aBuffer = (BumpBuffer)elements.nextElement(); if ( aBuffer.hasSameConfiguration(gc, aTopColor, aShadowColor, aBackColor)) { result = aBuffer; break; } } if (result == null) { result = new BumpBuffer(gc, topColor, shadowColor, backColor); buffers.addElement(result); } return result; } public void setBumpArea( Dimension bumpArea ) { setBumpArea( bumpArea.width, bumpArea.height ); } public void setBumpArea( int width, int height ) { xBumps = width / 2; yBumps = height / 2; } public void setBumpColors( Color newTopColor, Color newShadowColor, Color newBackColor ) { topColor = newTopColor; shadowColor = newShadowColor; if (newBackColor == null) { backColor = ALPHA; } else { backColor = newBackColor; } } public void paintIcon( Component c, Graphics g, int x, int y ) { GraphicsConfiguration gc = (g instanceof Graphics2D) ? (GraphicsConfiguration)((Graphics2D)g). getDeviceConfiguration() : null; buffer = getBuffer(gc, topColor, shadowColor, backColor); int bufferWidth = buffer.getImageSize().width; int bufferHeight = buffer.getImageSize().height; int iconWidth = getIconWidth(); int iconHeight = getIconHeight(); int x2 = x + iconWidth; int y2 = y + iconHeight; int savex = x; while (y < y2) { int h = Math.min(y2 - y, bufferHeight); for (x = savex; x < x2; x += bufferWidth) { int w = Math.min(x2 - x, bufferWidth); g.drawImage(buffer.getImage(), x, y, x+w, y+h, 0, 0, w, h, null); } y += bufferHeight; } } public int getIconWidth() { return xBumps * 2; } public int getIconHeight() { return yBumps * 2; } } class BumpBuffer { static final int IMAGE_SIZE = 64; static Dimension imageSize = new Dimension( IMAGE_SIZE, IMAGE_SIZE ); transient Image image; Color topColor; Color shadowColor; Color backColor; private GraphicsConfiguration gc; public BumpBuffer(GraphicsConfiguration gc, Color aTopColor, Color aShadowColor, Color aBackColor) { this.gc = gc; topColor = aTopColor; shadowColor = aShadowColor; backColor = aBackColor; createImage(); fillBumpBuffer(); } public boolean hasSameConfiguration(GraphicsConfiguration gc, Color aTopColor, Color aShadowColor, Color aBackColor) { if (this.gc != null) { if (!this.gc.equals(gc)) { return false; } } else if (gc != null) { return false; } return topColor.equals( aTopColor ) && shadowColor.equals( aShadowColor ) && backColor.equals( aBackColor ); } /** * Returns the Image containing the bumps appropriate for the passed in * <code>GraphicsConfiguration</code>. */ public Image getImage() { return image; } public Dimension getImageSize() { return imageSize; } /** * Paints the bumps into the current image. */ private void fillBumpBuffer() { Graphics g = image.getGraphics(); g.setColor( backColor ); g.fillRect( 0, 0, IMAGE_SIZE, IMAGE_SIZE ); g.setColor(topColor); for (int x = 0; x < IMAGE_SIZE; x+=4) { for (int y = 0; y < IMAGE_SIZE; y+=4) { g.drawLine( x, y, x, y ); g.drawLine( x+2, y+2, x+2, y+2); } } g.setColor(shadowColor); for (int x = 0; x < IMAGE_SIZE; x+=4) { for (int y = 0; y < IMAGE_SIZE; y+=4) { g.drawLine( x+1, y+1, x+1, y+1 ); g.drawLine( x+3, y+3, x+3, y+3); } } g.dispose(); } /** * Creates the image appropriate for the passed in * <code>GraphicsConfiguration</code>, which may be null. */ private void createImage() { if (gc != null) { image = gc.createCompatibleImage(IMAGE_SIZE, IMAGE_SIZE, (backColor != MetalBumps.ALPHA) ? Transparency.OPAQUE : Transparency.BITMASK); } else { int cmap[] = { backColor.getRGB(), topColor.getRGB(), shadowColor.getRGB() }; IndexColorModel icm = new IndexColorModel(8, 3, cmap, 0, false, (backColor == MetalBumps.ALPHA) ? 0 : -1, DataBuffer.TYPE_BYTE); image = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, BufferedImage.TYPE_BYTE_INDEXED, icm); } } } |
MetalSplitPaneDivider.java
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
import java.awt.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.plaf.basic.*; import javax.swing.plaf.metal.*; public class MetalSplitPaneDivider extends BasicSplitPaneDivider { private MetalBumps bumps = new MetalBumps(10, 10, MetalLookAndFeel.getControlHighlight(), MetalLookAndFeel.getControlDarkShadow(), MetalLookAndFeel.getControl() ); private MetalBumps focusBumps = new MetalBumps(10, 10, MetalLookAndFeel.getPrimaryControlHighlight(), MetalLookAndFeel.getPrimaryControlDarkShadow(), UIManager.getColor("SplitPane.dividerFocusColor")); private int inset = 2; private Color controlColor = MetalLookAndFeel.getControl(); private Color primaryControlColor = UIManager.getColor( "SplitPane.dividerFocusColor"); public MetalSplitPaneDivider(BasicSplitPaneUI ui) { super(ui); } public void paint(Graphics g) { MetalBumps usedBumps; if (splitPane.hasFocus()) { usedBumps = focusBumps; g.setColor(primaryControlColor); } else { usedBumps = bumps; g.setColor(controlColor); } Rectangle clip = g.getClipBounds(); Insets insets = getInsets(); g.fillRect(clip.x, clip.y, clip.width, clip.height); Dimension size = getSize(); size.width -= inset * 2; size.height -= inset * 2; int drawX = inset; int drawY = inset; if (insets != null) { size.width -= (insets.left + insets.right); size.height -= (insets.top + insets.bottom); drawX += insets.left; drawY += insets.top; } usedBumps.setBumpArea(size); usedBumps.paintIcon(this, g, drawX, drawY); super.paint(g); } /** * Creates and return an instance of JButton that can be used to * collapse the left component in the metal split pane. */ protected JButton createLeftOneTouchButton() { JButton b = new JButton() { // Sprite buffer for the arrow image of the left button int[][] buffer = {{0, 0, 0, 2, 2, 0, 0, 0, 0}, {0, 0, 2, 1, 1, 1, 0, 0, 0}, {0, 2, 1, 1, 1, 1, 1, 0, 0}, {2, 1, 1, 1, 1, 1, 1, 1, 0}, {0, 3, 3, 3, 3, 3, 3, 3, 3}}; public void setBorder(Border b) { } public void paint(Graphics g) { JSplitPane splitPane = getSplitPaneFromSuper(); if(splitPane != null) { int oneTouchSize = getOneTouchSizeFromSuper(); int orientation = getOrientationFromSuper(); int blockSize = Math.min(getDividerSize(), oneTouchSize); // Initialize the color array Color[] colors = { this.getBackground(), MetalLookAndFeel.getPrimaryControlDarkShadow(), MetalLookAndFeel.getPrimaryControlInfo(), MetalLookAndFeel.getPrimaryControlHighlight()}; // Fill the background first ... g.setColor(this.getBackground()); if (isOpaque()) { g.fillRect(0, 0, this.getWidth(), this.getHeight()); } // ... then draw the arrow. if (getModel().isPressed()) { // Adjust color mapping for pressed button state colors[1] = colors[2]; } if(orientation == JSplitPane.VERTICAL_SPLIT) { // Draw the image for a vertical split for (int i=1; i<=buffer[0].length; i++) { for (int j=1; j<blockSize; j++) { if (buffer[j-1][i-1] == 0) { continue; } else { g.setColor( colors[buffer[j-1][i-1]]); } g.drawLine(i, j, i, j); } } } else { // Draw the image for a horizontal split // by simply swaping the i and j axis. // Except the drawLine() call this code is // identical to the code block above. This was done // in order to remove the additional orientation // check for each pixel. for (int i=1; i<=buffer[0].length; i++) { for (int j=1; j<blockSize; j++) { if (buffer[j-1][i-1] == 0) { // Nothing needs // to be drawn continue; } else { // Set the color from the // color map g.setColor( colors[buffer[j-1][i-1]]); } // Draw a pixel g.drawLine(j, i, j, i); } } } } } // Don't want the button to participate in focus traversable. public boolean isFocusTraversable() { return false; } }; b.setRequestFocusEnabled(false); b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); b.setFocusPainted(false); b.setBorderPainted(false); maybeMakeButtonOpaque(b); return b; } /** * If necessary <code>c</code> is made opaque. */ private void maybeMakeButtonOpaque(JComponent c) { Object opaque = UIManager.get("SplitPane.oneTouchButtonsOpaque"); if (opaque != null) { c.setOpaque(((Boolean)opaque).booleanValue()); } } /** * Creates and return an instance of JButton that can be used to * collapse the right component in the metal split pane. */ protected JButton createRightOneTouchButton() { JButton b = new JButton() { // Sprite buffer for the arrow image of the right button int[][] buffer = {{2, 2, 2, 2, 2, 2, 2, 2}, {0, 1, 1, 1, 1, 1, 1, 3}, {0, 0, 1, 1, 1, 1, 3, 0}, {0, 0, 0, 1, 1, 3, 0, 0}, {0, 0, 0, 0, 3, 0, 0, 0}}; public void setBorder(Border border) { } public void paint(Graphics g) { JSplitPane splitPane = getSplitPaneFromSuper(); if(splitPane != null) { int oneTouchSize = getOneTouchSizeFromSuper(); int orientation = getOrientationFromSuper(); int blockSize = Math.min(getDividerSize(), oneTouchSize); // Initialize the color array Color[] colors = { this.getBackground(), MetalLookAndFeel.getPrimaryControlDarkShadow(), MetalLookAndFeel.getPrimaryControlInfo(), MetalLookAndFeel.getPrimaryControlHighlight()}; // Fill the background first ... g.setColor(this.getBackground()); if (isOpaque()) { g.fillRect(0, 0, this.getWidth(), this.getHeight()); } // ... then draw the arrow. if (getModel().isPressed()) { // Adjust color mapping for pressed button state colors[1] = colors[2]; } if(orientation == JSplitPane.VERTICAL_SPLIT) { // Draw the image for a vertical split for (int i=1; i<=buffer[0].length; i++) { for (int j=1; j<blockSize; j++) { if (buffer[j-1][i-1] == 0) { continue; } else { g.setColor( colors[buffer[j-1][i-1]]); } g.drawLine(i, j, i, j); } } } else { // Draw the image for a horizontal split // by simply swaping the i and j axis. // Except the drawLine() call this code is // identical to the code block above. This was done // in order to remove the additional orientation // check for each pixel. for (int i=1; i<=buffer[0].length; i++) { for (int j=1; j<blockSize; j++) { if (buffer[j-1][i-1] == 0) { // Nothing needs // to be drawn continue; } else { // Set the color from the // color map g.setColor( colors[buffer[j-1][i-1]]); } // Draw a pixel g.drawLine(j, i, j, i); } } } } } // Don't want the button to participate in focus traversable. public boolean isFocusTraversable() { return false; } }; b.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); b.setFocusPainted(false); b.setBorderPainted(false); b.setRequestFocusEnabled(false); maybeMakeButtonOpaque(b); return b; } /** * Used to layout a MetalSplitPaneDivider. Layout for the divider * involves appropriately moving the left/right buttons around. * <p> * This class should be treated as a "protected" inner class. * Instantiate it only within subclasses of MetalSplitPaneDivider. */ public class MetalDividerLayout implements LayoutManager { // NOTE NOTE NOTE NOTE NOTE // This class is no longer used, the functionality has // been rolled into BasicSplitPaneDivider.DividerLayout as a // defaults property public void layoutContainer(Container c) { JButton leftButton = getLeftButtonFromSuper(); JButton rightButton = getRightButtonFromSuper(); JSplitPane splitPane = getSplitPaneFromSuper(); int orientation = getOrientationFromSuper(); int oneTouchSize = getOneTouchSizeFromSuper(); int oneTouchOffset = getOneTouchOffsetFromSuper(); Insets insets = getInsets(); // This layout differs from the one used in BasicSplitPaneDivider. // It does not center justify the oneTouchExpadable buttons. // This was necessary in order to meet the spec of the Metal // splitpane divider. if (leftButton != null && rightButton != null && c == MetalSplitPaneDivider.this) { if (splitPane.isOneTouchExpandable()) { if (orientation == JSplitPane.VERTICAL_SPLIT) { int extraY = (insets != null) ? insets.top : 0; int blockSize = getDividerSize(); if (insets != null) { blockSize -= (insets.top + insets.bottom); } blockSize = Math.min(blockSize, oneTouchSize); leftButton.setBounds(oneTouchOffset, extraY, blockSize * 2, blockSize); rightButton.setBounds(oneTouchOffset + oneTouchSize * 2, extraY, blockSize * 2, blockSize); } else { int blockSize = getDividerSize(); int extraX = (insets != null) ? insets.left : 0; if (insets != null) { blockSize -= (insets.left + insets.right); } blockSize = Math.min(blockSize, oneTouchSize); leftButton.setBounds(extraX, oneTouchOffset, blockSize, blockSize * 2); rightButton.setBounds(extraX, oneTouchOffset + oneTouchSize * 2, blockSize, blockSize * 2); } } else { leftButton.setBounds(-5, -5, 1, 1); rightButton.setBounds(-5, -5, 1, 1); } } } public Dimension minimumLayoutSize(Container c) { return new Dimension(0,0); } public Dimension preferredLayoutSize(Container c) { return new Dimension(0, 0); } public void removeLayoutComponent(Component c) {} public void addLayoutComponent(String string, Component c) {} } /* * The following methods only exist in order to be able to access protected * members in the superclass, because these are otherwise not available * in any inner class. */ int getOneTouchSizeFromSuper() { return super.ONE_TOUCH_SIZE; } int getOneTouchOffsetFromSuper() { return super.ONE_TOUCH_OFFSET; } int getOrientationFromSuper() { return super.orientation; } JSplitPane getSplitPaneFromSuper() { return super.splitPane; } JButton getLeftButtonFromSuper() { return super.leftButton; } JButton getRightButtonFromSuper() { return super.rightButton; } } |
Share the post "Metal Look & Feel For JSplitPane’s Divider"










