Hello i'm trying to do a string inside a rectangle to make custom menus in java I'm using a canvas and doing the following method, but I can't seem to get it right!
public void render(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
Font font = new Font("Verdana", Font.PLAIN, 20);
g2d.setFont(font);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
FontMetrics fm = root.getFontMetrics(font);
g2d.drawString(option, (int)getX() - fm.stringWidth(option)/2, (int) getY() + fm.getHeight());
g2d.drawRect((int)getX() - fm.stringWidth(option)/2 - 20, (int) getY() - fm.getHeight() - 10, (int)getX() - fm.stringWidth(option)/2 + 40 , (int) getY() - fm.getHeight() + 10);
}
The basic problem you have is that you are using the components x/y position where the Graphics context is already translated so that 0x0 is the top/left corner of the component.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DrawText {
public static void main(String[] args) {
new DrawText();
}
public DrawText() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setBackground(Color.BLACK);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.RED);
g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
g2d.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
render(g);
g2d.dispose();
}
public void render(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
Font font = new Font("Verdana", Font.PLAIN, 20);
g2d.setFont(font);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
FontMetrics fm = g2d.getFontMetrics();
String option = "This is a test";
int x = (getWidth() - fm.stringWidth(option)) / 2;
int y = ((getHeight() - fm.getHeight()) / 2);
g2d.drawString(option, x, y + fm.getAscent());
g2d.drawRect(
(int)x - 20,
(int)y - 10,
(int)fm.stringWidth(option) + 40,
(int)fm.getHeight() + 20);
}
}
}
For example...
Centering String in Panel
Java center text in rectangle
Updated...
If, each menu item is printed within a single component, then the concept provided above should work. If you are printing multiple items within a single component, you could use something like...
public void render(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.WHITE);
Font font = new Font("Verdana", Font.PLAIN, 20);
g2d.setFont(font);
int x = 0;
int y = 0;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
FontMetrics fm = g2d.getFontMetrics();
String option = "This is a test";
while (x < getWidth()) {
while (y < getHeight()) {
int width = fm.stringWidth(option);
int height= fm.getHeight();
g2d.drawString(option, x + 20, y + fm.getAscent() + 10);
width += 40;
height += 20;
g2d.drawRect(
(int) x,
(int) y,
(int) width,
(int) height);
x += width;
y += height;
}
}
}
Related
I want to make JTextArea has a rounded corners, and i did this code :
public BPosTxtArea() {
super();
setOpaque(false);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
super.paintComponent(g);
}
#Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(102, 102, 102));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, 15, 15);
}
but it still has a square border outside like picture bellow :
Can anyone help me?
Start by having a look at How to Use Borders
This is a very simple example:
public class RoundBorder implements Border {
private int radius;
public RoundBorder(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.geom.RoundRectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
public class Example {
public static void main(String[] args) {
new Example();
}
public Example() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JTextArea ta = new JTextArea(10, 20);
ta.setBorder(new RoundBorder(20));
JScrollPane sp = new JScrollPane(new JTextArea(10, 20));
sp.setBorder(new RoundBorder(20));
add(ta, gbc);
add(sp, gbc);
}
}
public class RoundBorder implements Border {
private int radius;
public RoundBorder(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
#Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2d = (Graphics2D) g.create();
g2d.draw(new RoundRectangle2D.Double(x, y, width - 1, height - 1, getRadius(), getRadius()));
g2d.dispose();
}
#Override
public Insets getBorderInsets(Component c) {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
#Override
public boolean isBorderOpaque() {
return false;
}
}
}
Problems, the border is painted "within" the component fill area, meaning that the corners will be the same color as the fill area. There's no way around it using Border.
The trick would be to create a second component, onto which you could paint the border (via the paintComponent, filling the area within the border the same color as the text area) and then add the component into that.
Updated
Based on you code example, you're not overriding getInsets, which is going to be very important, the other thing is, it appears that your JTextArea is within a JScrollPane...
public class BPosTextArea extends JTextArea {
private int radius;
public BPosTextArea() {
super(10, 20);
setOpaque(false);
setBorder(null);
setRadius(20);
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(getBackground());
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
super.paintComponent(g);
}
#Override
protected void paintBorder(Graphics g) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(new Color(102, 102, 102));
g2.drawRoundRect(0, 0, getWidth() - 1, getHeight() - 1, getRadius(), getRadius());
}
public void setRadius(int radius) {
this.radius = radius;
repaint();
}
public int getRadius() {
return radius;
}
#Override
public Insets getInsets() {
int value = getRadius() / 2;
return new Insets(value, value, value, value);
}
}
A solution is to set the border to null for the JScrollPane
I have a class called "GridPanel" that paints the coordinate system on the screen.
public class GridPanel extends JPanel
{
protected paintComponent(Graphics g){
// draws the Coordinate System with grid
}
}
And another class called "Shapes" that paints custom shapes on the coordinate system.
public class Shape extends JComponent{
protected paintComponent(Graphics g){
// draws the shape on to the coordinate system
}
}
I am looking for a way to do the painting inside the shape class without having to paint the coordinate system again and again.
"How" will come down to "what".
Generally speaking, you'll find it easier to paint things onto the GridPane if you do it yourself, and not rely on things like layout managers.
For example. This creates a simple interface, with a single method which is used to paint things onto the grid.
public interface GridShape {
public void draw(Graphics2D g2d, JComponent parent);
}
This is then implemented by what ever wants to paint onto the grid
public class WaveShape implements GridShape {
#Override
public void draw(Graphics2D g2d, JComponent parent) {
g2d.setColor(Color.RED);
int xDiff = parent.getWidth() / 4;
int height = parent.getHeight() - 1;
int xPos = 0;
GeneralPath path = new GeneralPath();
path.moveTo(0, 0);
path.curveTo(xPos + xDiff, 0, xPos, height, xPos + xDiff, height);
xPos += xDiff;
path.curveTo(xPos + xDiff, height, xPos, 0, xPos + xDiff, 0);
xPos += xDiff;
path.curveTo(xPos + xDiff, 0, xPos, height, xPos + xDiff, height);
xPos += xDiff;
path.curveTo(xPos + xDiff, height, xPos, 0, xPos + xDiff, 0);
g2d.draw(path);
}
}
The GridPane then paints itself and then paints what ever "shape" it has (this example is pretty basic, but you could have a setter which changes the "shape" which is painted or, if required, have a List which allows you to paint multiple shapes simultaneously)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestGrid {
public static void main(String[] args) {
new TestGrid();
}
public TestGrid() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new GridPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GridPane extends JPanel {
private WaveShape waveShape;
public GridPane() {
waveShape = new WaveShape();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.drawLine(getWidth() / 2, 0, getWidth() / 2, getHeight());
g2d.drawLine(0, getHeight() / 2, getWidth(), getHeight() / 2);
g2d.dispose();
// I don't trust you
g2d = (Graphics2D) g.create();
waveShape.draw(g2d, this);
g2d.dispose();
}
}
public interface GridShape {
public void draw(Graphics2D g2d, JComponent parent);
}
public class WaveShape implements GridShape {
#Override
public void draw(Graphics2D g2d, JComponent parent) {
g2d.setColor(Color.RED);
int xDiff = parent.getWidth() / 4;
int height = parent.getHeight() - 1;
int xPos = 0;
GeneralPath path = new GeneralPath();
path.moveTo(0, 0);
path.curveTo(xPos + xDiff, 0, xPos, height, xPos + xDiff, height);
xPos += xDiff;
path.curveTo(xPos + xDiff, height, xPos, 0, xPos + xDiff, 0);
xPos += xDiff;
path.curveTo(xPos + xDiff, 0, xPos, height, xPos + xDiff, height);
xPos += xDiff;
path.curveTo(xPos + xDiff, height, xPos, 0, xPos + xDiff, 0);
g2d.draw(path);
}
}
}
I need to draw some squares inside other square but I don't know how to rotate my squares by center of them and make them smaller?
Here is a picture how it should looks like at the end:
Now I have some code which draw squares which make circle.
class MySquare extends JComponent {
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
for (int i = 0; i < 20; i++) {
g2d = (Graphics2D) g.create();
g2d.rotate(Math.toRadians(45 - (i * 10)), 100, 100);
// Difrent colors:
if (i % 2 == 0)
g2d.setColor(Color.black);
else
g2d.setColor(Color.green);
g2d.fillRect(50, 50, 100, 100);
}
}
}
public class DrawRect {
public static void main(String[] a) {
JFrame window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setBounds(30, 30, 800, 800);
window.getContentPane().add(new MySquare());
window.setVisible(true);
}
}
You could first draw your figure around the origin (that's easy) and then translate:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(400, 400);
frame.setVisible(true);
frame.add(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
double alpha = Math.toRadians(5);
double factor = 1 / (Math.sin(alpha) + Math.cos(alpha));
double size = 200;
g2d.translate(size, size);
for (int i = 0; i < 20; i++) {
g2d.setColor(i % 2 == 0 ? Color.black : Color.green);
int intSize = (int) Math.round(size);
g2d.fillRect(-intSize / 2, -intSize / 2, intSize, intSize);
size = size * factor;
g2d.rotate(alpha);
}
}
});
}
}
For my java application i need a Round rectangle with an outline that looks like a normal rectangle, like this
I know you can do that by drawing a normal rectangle and a RoundRect inside it but i don't want to draw a RoundRect inside it because I want to draw something else in it.
So a round rect with normal corners. How do I draw that in Java?
The problem is that the rectangle looks like this if I use layers:
The corners are filled up with the wrong color. How do I prevent that?
I can think of two approaches. The first is to generate a Shape that represents the square outter edge and the rounded inner edge.
The second would be to use a AlphaComposite to generate a masked result.
public class TestMask {
public static void main(String[] args) {
new TestMask();
}
public TestMask() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new MaskedPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MaskedPane extends JPanel {
public MaskedPane() {
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
BufferedImage outter = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = outter.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
BufferedImage inner = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
g2d = inner.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.fillRoundRect(10, 10, getWidth() - 20, getHeight() - 20, 20, 20);
g2d.dispose();
BufferedImage masked = applyMask(outter, inner, AlphaComposite.DST_OUT);
g.drawImage(masked, 0, 0, this);
}
public BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage, int method) {
BufferedImage maskedImage = null;
if (sourceImage != null) {
int width = maskImage.getWidth();
int height = maskImage.getHeight();
maskedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D mg = maskedImage.createGraphics();
int x = (width - sourceImage.getWidth()) / 2;
int y = (height - sourceImage.getHeight()) / 2;
mg.drawImage(sourceImage, x, y, null);
mg.setComposite(AlphaComposite.getInstance(method));
mg.drawImage(maskImage, 0, 0, null);
mg.dispose();
}
return maskedImage;
}
public BufferedImage applyMask(BufferedImage sourceImage, BufferedImage maskImage) {
return (BufferedImage) applyMask(sourceImage, maskImage, AlphaComposite.DST_IN);
}
}
}
Updated with Shape example
Finally had time to bang one out...
public class TestMask {
public static void main(String[] args) {
new TestMask();
}
public TestMask() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ShapedPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ShapedPane extends JPanel {
public ShapedPane() {
setBackground(Color.GREEN);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.fill(new RounedFrame(getWidth(), getHeight(), 10, 20));
g2d.dispose();
}
}
public class RounedFrame extends Path2D.Float {
public RounedFrame(float width, float height, float thickness, float radius) {
moveTo(0, 0);
lineTo(width, 0);
lineTo(width, height);
lineTo(0, height);
lineTo(0, 0);
float innerWidth = width - thickness;
float innerHeight = height - thickness;
moveTo(thickness + radius, thickness);
lineTo(innerWidth - radius, thickness);
curveTo(innerWidth, thickness, innerWidth, thickness, innerWidth, thickness + radius);
lineTo(innerWidth, innerHeight - radius);
curveTo(innerWidth, innerHeight, innerWidth, innerHeight, innerWidth - radius, innerHeight);
lineTo(thickness + radius, innerHeight);
curveTo(thickness, innerHeight, thickness, innerHeight, thickness, innerHeight - radius);
lineTo(thickness, thickness + radius);
curveTo(thickness, thickness, thickness, thickness, thickness + radius, thickness);
closePath();
setWindingRule(WIND_EVEN_ODD);
}
}
}
Updated
From a comment by Andrew, you could simplify the use of the shape example by using Area
You could replace the paintComponent from the above example with this one...
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Area area = new Area(new Rectangle(0, 0, getWidth(), getHeight()));
area.subtract(new Area(new RoundRectangle2D.Float(10, 10, getWidth() - 20, getHeight() - 20, 20, 20)));
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.BLACK);
g2d.fill(area);
g2d.dispose();
}
Which is much simpler :D
Something like:
paintComponent(Graphics g) {
//If you want more: Graphics2D g2 = (Graphics2D) g;
Rect rect = getBounds();
g.setColor(Color.BLACK);
g.fillRect(rect.x, rect,y, rect.width, rect.height);
rect.grow(-4, -4);
g.setColor(getBackground());
g.fillRoundRect(rect.x, rect,y, rect.width, rect.height, 5, 5);
}
E.G.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
class CustomBorderWithContent {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
int w = 200;
int h = 100;
int pad = 4;
BufferedImage img = new BufferedImage(
w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = img.createGraphics();
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// Ripped/adapted from Joop's answer
g.setColor(Color.BLACK);
g.fillRect(0, 0, w, h);
g.setColor(Color.ORANGE);
g.fillRoundRect(pad, pad, w-2*pad, h-2*pad, 25, 25);
// Now..
g.setColor(Color.BLUE);
g.drawString("Something else..", 20, 25);
g.dispose();
JOptionPane.showMessageDialog(
null, new JLabel(new ImageIcon(img)));
}
};
SwingUtilities.invokeLater(r);
}
}
I have gone through this website Change look and feel of JSlider
but except for Slider.altTrackColor nothing else is working. I want to do something like shown in pic1 any suggestion would be of great help. I'm working on JDK 1.6.
UIDefaults defaults = UIManager.getDefaults();
defaults.put("Slider.altTrackColor", Color.red);
defaults.put("Slider.thumb", Color.red);
I have also tried this:
WindowUtilities.setNativeLookAndFeel();
// WindowUtilities.setNimbuzzLookAndFeel();
// WindowUtilities.setJavaLookAndFeel();
WindowUtilities is class that tells the system to use native look and feel, as in previous releases. Metal (Java) LAF is the default otherwise.
public static void setNativeLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) {
System.out.println("Error setting native LAF: " + e);
}
Here is a full example of working UI that shown on 1st image:
(no magic - just a bit of work with graphics and basic UI knowledge)
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.geom.GeneralPath;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.plaf.basic.BasicSliderUI;
/**
*
* #see http://stackoverflow.com/a/12297384/714968
*/
public class CustomSliderUI extends BasicSliderUI {
private BasicStroke stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 0f, new float[]{1f, 2f}, 0f);
public CustomSliderUI(JSlider b) {
super(b);
}
#Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
#Override
protected Dimension getThumbSize() {
return new Dimension(12, 16);
}
#Override
public void paintTrack(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Stroke old = g2d.getStroke();
g2d.setStroke(stroke);
g2d.setPaint(Color.BLACK);
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2,
trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
} else {
g2d.drawLine(trackRect.x + trackRect.width / 2, trackRect.y,
trackRect.x + trackRect.width / 2, trackRect.y + trackRect.height);
}
g2d.setStroke(old);
}
#Override
public void paintThumb(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int x1 = thumbRect.x + 2;
int x2 = thumbRect.x + thumbRect.width - 2;
int width = thumbRect.width - 4;
int topY = thumbRect.y + thumbRect.height / 2 - thumbRect.width / 3;
GeneralPath shape = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
shape.moveTo(x1, topY);
shape.lineTo(x2, topY);
shape.lineTo((x1 + x2) / 2, topY + width);
shape.closePath();
g2d.setPaint(new Color(81, 83, 186));
g2d.fill(shape);
Stroke old = g2d.getStroke();
g2d.setStroke(new BasicStroke(2f));
g2d.setPaint(new Color(131, 127, 211));
g2d.draw(shape);
g2d.setStroke(old);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
JSlider slider = new JSlider(0, 100);
slider.setPaintTicks(true);
slider.setPaintLabels(true);
slider.setMinorTickSpacing(5);
slider.setMajorTickSpacing(25);
slider.setUI(new CustomSliderUI(slider));
frame.add(slider);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
You can easily modify the thumb (gripper) size by changing the returned bounds. The thumb painting will adapt to any size. And you can also easily customize painting of any other slider part.
Here is the final view by the way:
P.S. I did not adapt UI for vertical sliders, but that shouldn't take too long.