How can I change the shape of a JTabbedPane tab? - java

I am trying to change the shape of the tabs in a JTabbedPane. Using setTabComponentAt(0, someComponent); doesn't change the exterior of the tab, which is a rectangle with a diagonal top-left corner. What may be done to change the shape?

correct way is only to change Look and Feel, nice example from Old.Java.Forums.Sun
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
public class TabbedPane extends JPanel {
private static final long serialVersionUID = 1L;
public TabbedPane() {
setLayout(new BorderLayout());
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JTabbedPane tb = new JTabbedPane();
tb.setUI(new CustomTabbedPaneUI());
tb.add("Tab1", new JTextArea(""));
tb.add("Tab2", new JTextArea(""));
tb.add("Tab3", new JTextArea(""));
tb.add("Tab4", new JTextArea(""));
tb.add("Tab5", new JTextArea(""));
jp.add(tb, BorderLayout.CENTER);
add(jp, BorderLayout.CENTER);
tb.setEnabledAt(1, false);
tb.setEnabledAt(3, false);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new TabbedPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setVisible(true);
}
}
and
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.*;
import javax.swing.plaf.basic.*;
import javax.swing.text.View;
public class CustomTabbedPaneUI extends BasicTabbedPaneUI {
private Color selectColor;
private Color deSelectColor;
private int inclTab = 4;
private int anchoFocoV = inclTab;
private int anchoFocoH = 4;
private int anchoCarpetas = 18;
private Polygon shape;
public static ComponentUI createUI(JComponent c) {
return new CustomTabbedPaneUI();
}
#Override
protected void installDefaults() {
super.installDefaults();
selectColor = new Color(250, 192, 192);
deSelectColor = new Color(197, 193, 168);
tabAreaInsets.right = anchoCarpetas;
}
#Override
protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
if (runCount > 1) {
int lines[] = new int[runCount];
for (int i = 0; i < runCount; i++) {
lines[i] = rects[tabRuns[i]].y + (tabPlacement == TOP ? maxTabHeight : 0);
}
Arrays.sort(lines);
if (tabPlacement == TOP) {
int fila = runCount;
for (int i = 0; i < lines.length - 1; i++, fila--) {
Polygon carp = new Polygon();
carp.addPoint(0, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 2, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i] + 3);
if (i < lines.length - 2) {
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i + 1]);
carp.addPoint(0, lines[i + 1]);
} else {
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i] + rects[selectedIndex].height);
carp.addPoint(0, lines[i] + rects[selectedIndex].height);
}
carp.addPoint(0, lines[i]);
g.setColor(hazAlfa(fila));
g.fillPolygon(carp);
g.setColor(darkShadow.darker());
g.drawPolygon(carp);
}
} else {
int fila = 0;
for (int i = 0; i < lines.length - 1; i++, fila++) {
Polygon carp = new Polygon();
carp.addPoint(0, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 1, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 1, lines[i + 1] - 3);
carp.addPoint(tabPane.getWidth() - 2 * fila - 3, lines[i + 1]);
carp.addPoint(0, lines[i + 1]);
carp.addPoint(0, lines[i]);
g.setColor(hazAlfa(fila + 2));
g.fillPolygon(carp);
g.setColor(darkShadow.darker());
g.drawPolygon(carp);
}
}
}
super.paintTabArea(g, tabPlacement, selectedIndex);
}
#Override
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
Graphics2D g2D = (Graphics2D) g;
GradientPaint gradientShadow;
int xp[] = null; // Para la forma
int yp[] = null;
switch (tabPlacement) {
case LEFT:
xp = new int[]{x, x, x + w, x + w, x};
yp = new int[]{y, y + h - 3, y + h - 3, y, y};
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, Color.ORANGE);
break;
case RIGHT:
xp = new int[]{x, x, x + w - 2, x + w - 2, x};
yp = new int[]{y, y + h - 3, y + h - 3, y, y};
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, new Color(153, 186, 243));
break;
case BOTTOM:
xp = new int[]{x, x, x + 3, x + w - inclTab - 6, x + w - inclTab - 2, x + w - inclTab, x + w - 3, x};
yp = new int[]{y, y + h - 3, y + h, y + h, y + h - 1, y + h - 3, y, y};
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, Color.BLUE);
break;
case TOP:
default:
xp = new int[]{x, x, x + 3, x + w - inclTab - 6, x + w - inclTab - 2, x + w - inclTab, x + w - inclTab, x};
yp = new int[]{y + h, y + 3, y, y, y + 1, y + 3, y + h, y + h};
gradientShadow = new GradientPaint(0, 0, Color.ORANGE, 0, y + h / 2, new Color(240, 255, 210));
break;
}
// ;
shape = new Polygon(xp, yp, xp.length);
if (isSelected) {
g2D.setColor(selectColor);
g2D.setPaint(gradientShadow);
} else {
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
g2D.setColor(deSelectColor);
GradientPaint gradientShadowTmp = new GradientPaint(0, 0, new Color(255, 255, 200), 0, y + h / 2, new Color(240, 255, 210));
g2D.setPaint(gradientShadowTmp);
} else {
GradientPaint gradientShadowTmp = new GradientPaint(0, 0, new Color(240, 255, 210), 0, y + 15 + h / 2, new Color(204, 204, 204));
g2D.setPaint(gradientShadowTmp);
}
}
//selectColor = new Color(255, 255, 200);
//deSelectColor = new Color(240, 255, 210);
g2D.fill(shape);
if (runCount > 1) {
g2D.setColor(hazAlfa(getRunForTab(tabPane.getTabCount(), tabIndex) - 1));
g2D.fill(shape);
}
g2D.fill(shape);
}
#Override
protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) {
super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected);
g.setFont(font);
View v = getTextViewForTab(tabIndex);
if (v != null) {
// html
v.paint(g, textRect);
} else {
// plain text
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
g.setColor(tabPane.getForegroundAt(tabIndex));
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
} else { // tab disabled
g.setColor(Color.BLACK);
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1);
}
}
}
/*protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) {
g.setFont(font);
View v = getTextViewForTab(tabIndex);
if (v != null) {
// html
v.paint(g, textRect);
} else {
// plain text
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
Color fg = tabPane.getForegroundAt(tabIndex);
if (isSelected && (fg instanceof UIResource)) {
Color selectedFG = UIManager.getColor("TabbedPane.selectedForeground");
if (selectedFG != null) {
fg = selectedFG;
}
}
g.setColor(fg);
SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
} else { // tab disabled
//PAY ATTENTION TO HERE
g.setColor(tabPane.getBackgroundAt(tabIndex).brighter());
SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
SwingUtilities2.drawStringUnderlineCharAt(tabPane, g, title, mnemIndex,
textRect.x - 1, textRect.y + metrics.getAscent() - 1);
}
}
}*/
#Override
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
return 20 + inclTab + super.calculateTabWidth(tabPlacement, tabIndex, metrics);
}
#Override
protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight) {
if (tabPlacement == LEFT || tabPlacement == RIGHT) {
return super.calculateTabHeight(tabPlacement, tabIndex, fontHeight);
} else {
return anchoFocoH + super.calculateTabHeight(tabPlacement, tabIndex, fontHeight);
}
}
#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) {
if (tabPane.hasFocus() && isSelected) {
g.setColor(UIManager.getColor("ScrollBar.thumbShadow"));
g.drawPolygon(shape);
}
}
protected Color hazAlfa(int fila) {
int alfa = 0;
if (fila >= 0) {
alfa = 50 + (fila > 7 ? 70 : 10 * fila);
}
return new Color(0, 0, 0, alfa);
}
}

The shape is under the aegis of the tabbed pane's UI delegate, which descends from TabbedPaneUI. The MetalTabbedPaneUI subclass is an example that may help you decide how badly you want to replace the delegate.

You can put html tags into the first parameter of addTab method as following :
MyJTabbedPane.addTab("<html><h1 style='padding:20px;'>TEST</h1></html>", new JPanel());

Related

Eclipse game window opening very small

Whenever I run my game, the game window opens up very small, like below, how can I fix this. I believe it is something to do with JFrame.setPreferredSize(new Dimension(x,y)); but I don't know where to implement this in the code for it to work.
This is what it shows:
enter image description here
Where do I implement the code? Like in the class, outside the class, or do I need to show my current code for someone to help me here?
This is my code:
public class RoadAppMain extends JFrame {
private static final int D_W = 1920; //Window dimension
private static final int D_H = 1280; //Window height
int grassWidth = 1920; //Width of grass
int vanishHeight = 768; // Height of vanishing point
int roadWidth = 900; //Width of the road
int rumbleLen = 800; //Length of each track stripe
double camDist = 0.8; //Camera distance
int N; //Size of each row or line
int playerPosX = 0; //Movement of player left and right
int playerPosY = 0; //Movement of player up and down
List<Line> lines = new ArrayList<RoadAppMain.Line>();
List<Integer> listValues = new ArrayList<Integer>();
DrawPanel drawPanel = new DrawPanel();
public RoadAppMain() {
for (int i = 0; i < 1600; i++) {
Line line = new Line();
line.z = i * rumbleLen;
int curveAngle = (int) (Math.random() * 15 + 1);
if (i > 20 && i < 70) {
line.curve = curveAngle;
}
else if (i > 100 && i < 150) {
line.curve = -curveAngle;
}
else if (i > 180 && i < 230) {
line.curve = curveAngle;
}
else if (i > 260 && i < 310) {
line.curve = -curveAngle;
}
else if (i > 340 && i < 390) {
line.curve = curveAngle;
}
else if (i > 400 && i < 420) {
}
lines.add(line);
}
N = lines.size();
//Handles action events by user
ActionListener listener = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
drawPanel.repaint();
}
};
Timer timer = new Timer(1, listener);
timer.start();
add(drawPanel);
pack();
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
//Moves screen using arrow keys
private class DrawPanel extends JPanel {
public DrawPanel() {
String VK_LEFT = "VK_LEFT";
KeyStroke W = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0);
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); //necessary
inputMap.put(W, VK_LEFT);
ActionMap actionMap = getActionMap(); //necessary
actionMap.put(VK_LEFT, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosX -= 200;
drawPanel.repaint();
}
});
String VK_RIGHT = "VK_RIGHT";
KeyStroke WVK_RIGHT = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0);
inputMap.put(WVK_RIGHT, VK_RIGHT);
actionMap.put(VK_RIGHT, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosX += 200;
drawPanel.repaint();
}
});
String VK_UP = "VK_UP";
KeyStroke WVK_UP = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0);
inputMap.put(WVK_UP, VK_UP);
actionMap.put(VK_UP, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosY += 200;
drawPanel.repaint();
}
});
String VK_DOWN = "VK_DOWN";
KeyStroke WVK_DOWN = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0);
inputMap.put(WVK_DOWN, VK_DOWN);
actionMap.put(VK_DOWN, new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
playerPosY -= 200;
drawPanel.repaint();
}
});
}
//Drawing components feature
protected void paintComponent(Graphics g) {
drawValues(g);
g.setColor(Color.black);
g.fillRect(0, 0, 1920, 395);
}
}
private void drawValues(Graphics g) {
int startPos = playerPosY / rumbleLen;
double x = 0; //Initial X position of screen on road
double dx = 0; //Correlation between the angle of the road and player
double maxY = vanishHeight;
int camH = 1700 + (int) lines.get(startPos).y; //Height of the camera
//Starting position
for (int n = startPos; n < startPos + 300; n++) {
Line l = lines.get(n % N); //Position of line
l.project(playerPosX - (int) x, camH, playerPosY);
x += dx;
dx += l.curve;
if (l.Y > 0 && l.Y < maxY) {
maxY = l.Y;
Color grass = ((n / 2) % 2) == 0 ? new Color(21, 153, 71) : new Color(22, 102, 52); //Color for grass (first is for lighter, second for darker)
Color rumble = ((n / 2) % 2) == 0 ? new Color(255, 255, 255) : new Color(222, 4, 4); // Color for rumble (first is white, second is red)
Color road = new Color(54, 52, 52); // Color of road or asphalt
Color midel = ((n / 2) % 2) == 0 ? new Color(255, 255, 255) : new Color(54, 52, 52); //Color of hashed lines (first for white lines, second for gap)
Color car = new Color(104, 104, 104);
Color tire = new Color(0, 0, 0);
Color stripe = new Color(0, 0, 0);
Color light = new Color(253, 0, 0);
Color hood = new Color(0, 0, 0);
Color frame = new Color(0,0,255);
Line p = null;
if (n == 0) {
p = l;
} else {
p = lines.get((n - 1) % N);
}
draw(g, grass, 0, (int) p.Y, grassWidth, 0, (int) l.Y, grassWidth); //(Graphics g, Color c, int x1, int y1, int w1, int x2, int y2, int w2)
draw(g, rumble, (int) p.X, (int) p.Y, (int) (p.W * 2.03), (int) l.X, (int) l.Y, (int) (l.W * 2.03)); //Affects width of rumble
draw(g, road, (int) p.X, (int) p.Y, (int) (p.W * 1.8), (int) l.X, (int) l.Y, (int) (l.W * 1.8));
draw(g, midel, (int) p.X, (int) p.Y, (int) (p.W * 0.78), (int) l.X, (int) l.Y, (int) (l.W * 0.78)); //ADD HERE
draw(g, road, (int) p.X, (int) p.Y, (int) (p.W * 0.7), (int) l.X, (int) l.Y, (int) (l.W* 0.7)); //To cover the gap in between each midel. Must be after to allow it to colour over it
draw(g, car, 965, 927, 125, 965, 1005, 125);
draw(g, tire, 875, 1005, 35, 875, 1050, 35);
draw(g, tire, 1055, 1005, 35, 1055, 1050, 35);
draw(g, stripe, 1050, 965, 30, 870, 980, 30);
draw(g, stripe, 1050, 950, 30, 870, 965, 30);
draw(g, hood, 965, 880, 90, 965, 927, 125);
draw(g, light, 875, 950, 5, 875, 980, 5);
draw(g, light, 890, 950, 5, 890, 980, 5);
draw(g, light, 905, 950, 5, 905, 980, 5);
draw(g, light, 1025, 950, 5, 1025, 980, 5);
draw(g, light, 1040, 950, 5, 1040, 980, 5);
draw(g, light, 1055, 950, 5, 1055, 980, 5);
draw(g, frame, 965, 874, 86, 965, 880, 90);
draw(g, light, 965, 874, 35, 965, 880, 45);
}
}
}
void draw(Graphics g, Color c, int x1, int y1, int w1, int x2, int y2, int w2) {
Graphics g9d = g;
int[] x9Points = { x1 - w1, x2 - w2, x2 + w2, x1 + w1 };
int[] y9Points = { y1, y2, y2, y1 };
int n9Points = 4;
g9d.setColor(c);
g9d.fillPolygon(x9Points, y9Points, n9Points);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new RoadAppMain();
}
});
}
class Line {
double x, y, z;
double X, Y, W;
double scale, curve;
public Line() {
curve = x = y = z = 0;
}
void project(int camX, int camY, int camZ) {
scale = camDist / (z - camZ);
X = (1 + scale * (x - camX)) * grassWidth / 2;
Y = (1 - scale * (y - camY)) * vanishHeight / 2;
W = scale * roadWidth * grassWidth / 2;
}
}
}

How to add close button in BasicTabbedPaneUI?

I'm trying to build a JTabbedPane using BasicTabbedPaneUI. I found an example of it which doesn't works perfectly. But it doesn't have a close button so that i can close the current tab.
How can i add a close button in it?
Here is my code:
public class TabbedPane extends JPanel {
private static final long serialVersionUID = 1L;
public static final JButton backButton = new JButton();
public TabbedPane() {
setLayout(new BorderLayout());
JPanel jp = new JPanel();
jp.setLayout(new BorderLayout());
JTabbedPane tb = new JTabbedPane();
tb.setUI(new CustomTabbedPaneUI());
JPanel pane = new JPanel();
tb.add("Tab1", pane);
MyCloseButton button = new MyCloseButton();
jp.add(new JLayer<JTabbedPane>(tb));
jp.add(new JButton(new AbstractAction("add tab") {
#Override
public void actionPerformed(ActionEvent e) {
tb.addTab("test", new JPanel());
}
}), BorderLayout.SOUTH);
jp.add(tb, BorderLayout.CENTER);
add(jp, BorderLayout.CENTER);
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new TabbedPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 200);
frame.setVisible(true);
}
}
and
public class CustomTabbedPaneUI extends BasicTabbedPaneUI {
private Color selectColor;
private Color deSelectColor;
private int inclTab = 4;
private int anchoFocoV = inclTab;
private int anchoFocoH = 4;
private int anchoCarpetas = 18;
private Polygon shape;
public static ComponentUI createUI(JComponent c) {
return new CustomTabbedPaneUI();
}
#Override
protected void installDefaults() {
super.installDefaults();
selectColor = new Color(250, 192, 192);
deSelectColor = new Color(197, 193, 168);
tabAreaInsets.right = anchoCarpetas;
}
#Override
protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) {
if (runCount > 1) {
int lines[] = new int[runCount];
for (int i = 0; i < runCount; i++) {
lines[i] = rects[tabRuns[i]].y + (tabPlacement == TOP ? maxTabHeight : 0);
}
Arrays.sort(lines);
if (tabPlacement == TOP) {
int fila = runCount;
for (int i = 0; i < lines.length - 1; i++, fila--) {
Polygon carp = new Polygon();
carp.addPoint(0, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 2, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i] + 3);
if (i < lines.length - 2) {
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i + 1]);
carp.addPoint(0, lines[i + 1]);
} else {
carp.addPoint(tabPane.getWidth() - 2 * fila, lines[i] + rects[selectedIndex].height);
carp.addPoint(0, lines[i] + rects[selectedIndex].height);
}
carp.addPoint(0, lines[i]);
g.setColor(hazAlfa(fila));
g.fillPolygon(carp);
g.setColor(darkShadow.darker());
g.drawPolygon(carp);
}
} else {
int fila = 0;
for (int i = 0; i < lines.length - 1; i++, fila++) {
Polygon carp = new Polygon();
carp.addPoint(0, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 1, lines[i]);
carp.addPoint(tabPane.getWidth() - 2 * fila - 1, lines[i + 1] - 3);
carp.addPoint(tabPane.getWidth() - 2 * fila - 3, lines[i + 1]);
carp.addPoint(0, lines[i + 1]);
carp.addPoint(0, lines[i]);
g.setColor(hazAlfa(fila + 2));
g.fillPolygon(carp);
g.setColor(darkShadow.darker());
g.drawPolygon(carp);
}
}
}
super.paintTabArea(g, tabPlacement,selectedIndex);
}
#Override
protected void paintTabBackground(Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h, boolean isSelected) {
Graphics2D g2D = (Graphics2D) g;
GradientPaint gradientShadow;
int xp[] = null; // Para la forma
int yp[] = null;
switch (tabPlacement) {
case LEFT:
xp = new int[]{x, x, x + w, x + w, x};
yp = new int[]{y, y + h - 3, y + h - 3, y, y};
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, Color.ORANGE);
break;
case RIGHT:
xp = new int[]{x, x, x + w - 2, x + w - 2, x};
yp = new int[]{y, y + h - 3, y + h - 3, y, y};
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, new Color(153, 186, 243));
break;
case BOTTOM:
xp = new int[]{x, x, x + 3, x + w - inclTab - 6, x + w - inclTab - 2, x + w - inclTab, x + w - 3, x};
yp = new int[]{y, y + h - 3, y + h, y + h, y + h - 1, y + h - 3, y, y};
gradientShadow = new GradientPaint(x, y, new Color(100, 100, 255), x, y + h, Color.BLUE);
break;
case TOP:
default:
xp = new int[]{x, x, x + 3, x + w - inclTab - 6, x + w - inclTab - 2, x + w - inclTab, x + w - inclTab, x};
yp = new int[]{y + h, y + 3, y, y, y + 1, y + 3, y + h, y + h};
gradientShadow = new GradientPaint(0, 0, Color.ORANGE, 0, y + h / 2, new Color(240, 255, 210));
break;
}
shape = new Polygon(xp, yp, xp.length);
if (isSelected) {
g2D.setColor(selectColor);
g2D.setPaint(gradientShadow);
} else {
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
g2D.setColor(deSelectColor);
GradientPaint gradientShadowTmp = new GradientPaint(0, 0, new Color(255, 255, 200), 0, y + h / 2, new Color(240, 255, 210));
g2D.setPaint(gradientShadowTmp);
} else {
GradientPaint gradientShadowTmp = new GradientPaint(0, 0, new Color(240, 255, 210), 0, y + 15 + h / 2, new Color(204, 204, 204));
g2D.setPaint(gradientShadowTmp);
}
}
g2D.fill(shape);
if (runCount > 1) {
g2D.setColor(hazAlfa(getRunForTab(tabPane.getTabCount(), tabIndex) - 1));
g2D.fill(shape);
}
g2D.fill(shape);
}
#Override
protected void paintText(Graphics g, int tabPlacement, Font font, FontMetrics metrics, int tabIndex, String title, Rectangle textRect, boolean isSelected) {
super.paintText(g, tabPlacement, font, metrics, tabIndex, title, textRect, isSelected);
g.setFont(font);
View v = getTextViewForTab(tabIndex);
if (v != null) {
// html
v.paint(g, textRect);
} else {
// plain text
int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex);
if (tabPane.isEnabled() && tabPane.isEnabledAt(tabIndex)) {
MyCloseButton button = new MyCloseButton();
g.setColor(tabPane.getForegroundAt(tabIndex));
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
} else { // tab disabled
g.setColor(Color.BLACK);
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x, textRect.y + metrics.getAscent());
g.setColor(tabPane.getBackgroundAt(tabIndex).darker());
BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, textRect.x - 1, textRect.y + metrics.getAscent() - 1);
}
}
}
#Override
protected int calculateTabWidth(int tabPlacement, int tabIndex, FontMetrics metrics) {
return 20 + inclTab + super.calculateTabWidth(tabPlacement, tabIndex, metrics);
}
#Override
protected int calculateTabHeight(int tabPlacement, int tabIndex, int fontHeight) {
if (tabPlacement == LEFT || tabPlacement == RIGHT) {
return super.calculateTabHeight(tabPlacement, tabIndex, fontHeight);
} else {
return anchoFocoH + super.calculateTabHeight(tabPlacement, tabIndex, fontHeight);
}
}
#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) {
if (tabPane.hasFocus() && isSelected) {
g.setColor(UIManager.getColor("ScrollBar.thumbShadow"));
g.drawPolygon(shape);
}
}
protected Color hazAlfa(int fila) {
int alfa = 0;
if (fila >= 0) {
alfa = 50 + (fila > 7 ? 70 : 10 * fila);
}
return new Color(0, 0, 0, alfa);
}
}
Here is my Button class which i want to add in the code above
class MyCloseButton extends JButton{
public MyCloseButton() {
super("X");
setBorder(BorderFactory.createEmptyBorder());
setFocusPainted(false);
setBorderPainted(false);
setContentAreaFilled(false);
setRolloverEnabled(false);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(16, 16);
}
}

Java custom control repaint causes incorrect (different) drawing

I have just started Java in school and I'm trying out custom controls and graphics. I'm currently working on a pattern lock and it started out perfectly fine, but all of a sudden it's drawing incorrectly. I did change some code, but as soon as I saw the error, I changed it right back (undo, ftw), but it still gives me the same error.
The problem is that when I repaint, the way my points are drawn, changes,- even though it isn't supposed to....
Here's a couple of images describing what I mean:
http://imgur.com/a/ObmFa
Hopefully this was clear enough, otherwise leave a comment instead of a minus point.
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import javax.swing.JPanel;
public class Lock extends JPanel
{
class Line
{
//Properties
public Point start;
public Point end;
public float thickness;
public Color color = new Color(63, 152, 137);
public Color highlightColor = new Color(73, 162, 147);
public Color borderColor = Color.BLACK;
public Line()
{
}
public Line(Point start, Point end, float thickness)
{
this.start = start;
this.end = end;
this.thickness = thickness;
}
public Line(Point start, Point end, float thickness, Color color, Color borderColor, Color highlightColor)
{
this.start = start;
this.end = end;
this.thickness = thickness;
this.color = color;
this.borderColor = borderColor;
this.highlightColor = highlightColor;
}
public void Draw(Graphics2D g)
{
//Set the line thickness
g.setStroke(new BasicStroke(thickness));
//Border
g.setColor(borderColor);
g.drawLine(start.x, start.y, end.x, end.y);
//Highlight
g.setStroke(new BasicStroke(thickness - 1));
g.setColor(highlightColor);
g.drawLine(start.x, start.y, end.x, end.y);
//Base color
g.setStroke(new BasicStroke(thickness - 2));
g.setColor(color);
g.drawLine(start.x, start.y, end.x, end.y);
//Reset the line thickness
g.setStroke(new BasicStroke(Lock.this.drawnLineThickness));
}
}
//Properties
public Dimension gridSize = new Dimension(3, 3);
public Dimension pointSize = new Dimension(50, 50);
public boolean stealth = false;
public Color backgroundColor = new Color(255, 0, 0, 0); //Transparent
public float drawingLineThickness = 1;
public float drawnLineThickness = 12;
public Color drawingLineColor = new Color(0, 128, 128); //Teal
public Color drawnLineColor = new Color(63, 152, 137); //Teal like color
public Color drawnLineBorderColor = Color.BLACK;
public Color drawnLineHighlightColor = new Color(73, 162, 147); //Teal like color
private static final long serialVersionUID = 1L;
private ArrayList<Rectangle> Points = new ArrayList<Rectangle>();
private ArrayList<Line> Lines = new ArrayList<Line>();
private boolean Dragging, Done;
private Point LineStartPoint, LineEndPoint;
private Rectangle StartPoint;
class MouseEventHandler extends MouseAdapter
{
#Override
public void mousePressed(MouseEvent e)
{
if(!Done)
{
for(Rectangle Point : Points)
{
if(IsInCircle(new Point(e.getX(), e.getY()), Point))
{
StartPoint = Point;
LineStartPoint = new Point(StartPoint.x + (StartPoint.width / 2), StartPoint.y + (StartPoint.height / 2));
}
}
}
}
#Override
public void mouseDragged(MouseEvent e)
{
Dragging = true;
LineEndPoint = new Point(e.getX(), e.getY());
for(Rectangle Point : Points)
{
//If the mouse is within one of the points and it's not the start point
if(IsInCircle(new Point(e.getX(), e.getY()), Point) && Point != StartPoint)
{
LineEndPoint = new Point(Point.x + (Point.width / 2), Point.y + (Point.height / 2));
Line LineToAdd = new Line(LineStartPoint, LineEndPoint, drawnLineThickness, drawnLineColor, drawnLineBorderColor, drawnLineHighlightColor);
if(CheckLines(LineToAdd))
{
Lines.add(LineToAdd);
LineStartPoint = LineEndPoint;
}
}
}
Lock.this.repaint();
}
#Override
public void mouseReleased(MouseEvent e)
{
//If the Lines array size is more than 0, that means that a line has been created and the control should now be "locked"
if(Lines.size() > 0)
{
Done = true; //We are now done and should not be able to add more lines.
}
//We are no longer dragging, so we set this to false, so that we won't be drawing a line on the control after we are done
Dragging = false;
//Update controls graphics
Lock.this.repaint();
}
}
public Lock()
{
CreateGrid();
addMouseListener(new MouseEventHandler());
addMouseMotionListener(new MouseEventHandler());
}
public void paintComponent(Graphics oldG)
{
super.paintComponent(oldG);
//Create a Graphics2D object as this class has more options
Graphics2D g = (Graphics2D) oldG;
//Rendering hints: https://docs.oracle.com/javase/tutorial/2d/advanced/quality.html
//Change render quality to be prettier
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
//Set the controls background color
g.setColor(backgroundColor);
g.fillRect(0, 0, getWidth(), getHeight());
if(!stealth)
{
if(Dragging)
{
g.setStroke(new BasicStroke(3));
g.setColor(new Color(0, 128, 128));
g.drawLine(LineStartPoint.x, LineStartPoint.y, LineEndPoint.x, LineEndPoint.y);
}
for(Line Line : Lines)
{
Line.Draw(g);
}
}
for(Rectangle Point : Points)
{
//Outer ring (black)
GradientPaint Black = new GradientPaint(Point.x, Point.y, new Color(24, 25, 24), Point.width, Point.height, new Color(14, 15, 14));
g.setPaint(Black);
g.fill(new Ellipse2D.Double(Point.x, Point.y, Point.width, Point.height));
//Outer ring highlight
g.setColor(new Color(255, 255, 255, 20));
g.draw(new Ellipse2D.Double(Point.x + 1, Point.y + 1, Point.width - 3, Point.height - 3));
//Inner ring (teal)
GradientPaint Teal = new GradientPaint(Point.x + (Point.width / 4) - 1, Point.y + (Point.height / 4) - 1, new Color(63, 152, 137), Point.width / 2 + 3, Point.height / 2 + 3, new Color(0, 128, 128));
g.setPaint(Teal);
g.fill(new Ellipse2D.Double(Point.x + (Point.width / 4) - 1, Point.y + (Point.height / 4) - 1, Point.width / 2 + 3, Point.height / 2 + 3));
//Inner ring highlight
g.setColor(new Color(0, 0, 0));
g.draw(new Ellipse2D.Double(Point.x + (Point.width / 4) - 1, Point.y + (Point.height / 4) - 1, Point.width / 2 + 3, Point.height / 2 + 3));
g.setColor(new Color(255, 255, 255, 30));
g.draw(new Ellipse2D.Double(Point.x + (Point.width / 4) - 2, Point.y + (Point.height / 4) - 2, Point.width / 2 + 4, Point.height / 2 + 4));
}
}
//Method is used to check whether a point is inside a rectangle/circle
private boolean IsInCircle(Point MouseLocation, Rectangle Rectangle)
{
boolean Result;
//Get center of rectangle/circle
Point CenterPoint = new Point(Rectangle.x + (Rectangle.width / 2), Rectangle.y + (Rectangle.height / 2));
//Get distance from centerpoint to mouselocation
int DistanceX = Math.abs(CenterPoint.x - MouseLocation.x);
int DistanceY = Math.abs(CenterPoint.y - MouseLocation.y);
//The distance squared
int DistanceSquared = (int) Math.sqrt(DistanceX * DistanceX + DistanceY * DistanceY);
//The radious
int Radius = Rectangle.width / 2;
//If the radious is more or equal to the distance squared, the point is inside the circle
Result = Radius >= DistanceSquared;
return Result;
}
//Method is used to check whether a line has previously been drawn to a specific point
private boolean CheckLines(Line Line)
{
boolean Result = true;
for(Line _Line : Lines)
{
//If a point has previously been drawn to, return false to not make it possible to draw another line to that point
if(_Line.end.getX() == Line.end.getX() && _Line.end.getY() == Line.end.getY() || _Line.start.getX() == Line.start.getX() && _Line.start.getY() == Line.start.getY())
{
Result = false;
}
}
//Same idea as above
if(Lines.contains(Line))
{
Result = false;
}
return Result;
}
//Method is used to generate a grid of points
private void CreateGrid()
{
int X = 0, Y = 0, ControlHeight = 0;
for(int i = 0; i < gridSize.width; i++)
{
for(int ii = 0; ii < gridSize.height; ii++)
{
Points.add(new Rectangle(X, Y, pointSize.width, pointSize.height));
Y += pointSize.height * 2;
ControlHeight = Y;
if(ii == gridSize.height - 1)
{
Y = 0;
}
}
X += pointSize.width * 2;
}
this.setMinimumSize(new Dimension(X - pointSize.width + 1, ControlHeight - pointSize.height + 1));
this.setMaximumSize(new Dimension(X - pointSize.width + 1, ControlHeight - pointSize.height + 1));
this.setSize(new Dimension(X - pointSize.width + 1, ControlHeight - pointSize.height + 1));
}
//Method is used to get the current pattern code as a string
public String GetPattern()
{
String Result = "";
for(Line Line : Lines)
{
Result += Line.start.toString() + ";" + Line.end.toString() + ": \n";
}
return Result;
}
//Method is used to clear the current pattern
public void ClearPattern()
{
//Clear the lines
Lines.clear();
//Reset the *
Done = false;
//Repaint the control to show that there no longer are any lines.
this.repaint();
}
}
I found the problem....
This line of code was the problem. The BasicStroke value was not the orignal value I had entered (c+p), but something close to the name.
//Reset the line thickness
g.setStroke(new BasicStroke(Lock.this.drawnLineThickness));
I fixed it by correcting the code to the original:
//Reset the line thickness
g.setStroke(new BasicStroke(Lock.this.drawingLineThickness));

How to optimize this kind of loop?

I'm trying to make this GUi.
I write my own layout because existing layout manager don't meet my requirements
It works but I attempt to optimize the creation of all buttons by using loops.
Test.class
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame();
JPanel parent = new JPanel();
f.add(parent);
parent.setLayout(new BoxLayout(parent, BoxLayout.X_AXIS));
JPanel[] children = new JPanel[6];
for (int i = 1; i < children.length; i++) {
children[i] = new JPanel();
children[i].setLayout(new XYLayout());
children[i].setBorder(new LineBorder(Color.red));
parent.add(children[i]);
}
int x = 0, y = 375, w = 0, h = 50;
children[1].add(new JButton("8"), new XYConstraints(0, 25, 0, 50));
children[1].add(new JButton("7"), new XYConstraints(0, 75, 0, 50));
children[1].add(new JButton("6"), new XYConstraints(0, 125, 0, 50));
children[1].add(new JButton("5"), new XYConstraints(0, 175, 0, 50));
children[1].add(new JButton("4"), new XYConstraints(0, 225, 0, 50));
children[1].add(new JButton("3"), new XYConstraints(0, 275, 0, 50));
children[1].add(new JButton("2"), new XYConstraints(0, 325, 0, 50));
children[1].add(new JButton("1"), new XYConstraints(0, 375, 0, 50));
children[2].add(new JButton("7"), new XYConstraints(240, 25, 0, 100));
children[2].add(new JButton("6"), new XYConstraints(200, 75, 0, 100));
children[2].add(new JButton("5"), new XYConstraints(160, 125, 0, 100));
children[2].add(new JButton("4"), new XYConstraints(120, 175, 0, 100));
children[2].add(new JButton("3"), new XYConstraints(80, 225, 0, 100));
children[2].add(new JButton("2"), new XYConstraints(40, 275, 0, 100));
children[2].add(new JButton("1"), new XYConstraints(0, 325, 0, 100));
children[3].add(new JButton("6"), new XYConstraints(200, 25, 0, 150));
children[3].add(new JButton("5"), new XYConstraints(160, 75, 0, 150));
children[3].add(new JButton("4"), new XYConstraints(120, 125, 0, 150));
children[3].add(new JButton("3"), new XYConstraints(80, 175, 0, 150));
children[3].add(new JButton("2"), new XYConstraints(40, 225, 0, 150));
children[3].add(new JButton("1"), new XYConstraints(0, 275, 0, 150));
//children[4],//children[5]...
f.setSize(800, 600);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
The custom layout in one file : XYLayout
public class XYLayout implements LayoutManager2, Serializable {
private int width;
private int height;
Hashtable<Component, Object> info;
static final XYConstraints defaultConstraints = new XYConstraints();
public XYLayout() {
info = new Hashtable<Component, Object>();
}
public XYLayout(int width, int height) {
info = new Hashtable<Component, Object>();
this.width = width;
this.height = height;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("XYLayout [width=").append(width).append(", height=").append(height).append("]");
return builder.toString();
}
public void addLayoutComponent(String s, Component component1) {
}
public void removeLayoutComponent(Component component) {
info.remove(component);
}
public Dimension preferredLayoutSize(Container target) {
return getLayoutSize(target, true);
}
public Dimension minimumLayoutSize(Container target) {
return getLayoutSize(target, false);
}
public void layoutContainer(Container target) {
Insets insets = target.getInsets();
int count = target.getComponentCount();
for (int i = 0; i < count; i++) {
Component component = target.getComponent(i);
if (component.isVisible()) {
Rectangle r = getComponentBounds(component, true);
component.setBounds(insets.left + r.x, insets.top + r.y, r.width, r.height);
}
}
}
public void addLayoutComponent(Component component, Object constraints) {
if (constraints instanceof XYConstraints)
info.put(component, constraints);
}
public Dimension maximumLayoutSize(Container target) {
return new Dimension(0x7fffffff, 0x7fffffff);
}
public float getLayoutAlignmentX(Container target) {
return 0.5F;
}
public float getLayoutAlignmentY(Container target) {
return 0.5F;
}
public void invalidateLayout(Container container) {
}
public Rectangle getComponentBounds(Component component, boolean doPreferred) {
XYConstraints constraints = (XYConstraints) info.get(component);
if (constraints == null)
constraints = defaultConstraints;
Rectangle r = new Rectangle(constraints.getX(), constraints.getY(), constraints.getW(), constraints.getH());
if (r.width <= 0 || r.height <= 0) {
Dimension d = doPreferred ? component.getPreferredSize() : component.getMinimumSize();
if (r.width <= 0)
r.width = d.width;
if (r.height <= 0)
r.height = d.height;
}
return r;
}
public Dimension getLayoutSize(Container target, boolean doPreferred) {
Dimension dim = new Dimension(0, 0);
if (width <= 0 || height <= 0) {
int count = target.getComponentCount();
for (int i = 0; i < count; i++) {
Component component = target.getComponent(i);
if (component.isVisible()) {
Rectangle r = getComponentBounds(component, doPreferred);
dim.width = Math.max(dim.width, r.x + r.width);
dim.height = Math.max(dim.height, r.y + r.height);
}
}
}
if (width > 0)
dim.width = width;
if (height > 0)
dim.height = height;
Insets insets = target.getInsets();
dim.width += insets.left + insets.right;
dim.height += insets.top + insets.bottom;
return dim;
}
}
class XYConstraints implements Cloneable, Serializable {
private int x;
private int y;
private int w;
private int h;
public XYConstraints() {
this(0, 0, 0, 0);
}
public XYConstraints(int x, int y, int w, int h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getW() {
return w;
}
public void setW(int w) {
this.w = w;
}
public int getH() {
return h;
}
public void setH(int h) {
this.h = h;
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + h;
result = prime * result + w;
result = prime * result + x;
result = prime * result + y;
return result;
// return x ^ y * 37 ^ w * 43 ^ h * 47;
}
public boolean equals(Object that) {
if (that instanceof XYConstraints) {
XYConstraints other = (XYConstraints) that;
return other.x == x && other.y == y && other.w == w && other.h == h;
} else {
return false;
}
}
public Object clone() {
return new XYConstraints(x, y, w, h);
}
/*
* (non-Javadoc)
*
* #see java.lang.Object#toString()
*/
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("XYConstraints [x=").append(x).append(", y=").append(y).append(", w=").append(w).append(", h=").append(h).append("]");
return builder.toString();
}
My first attempt was:
for (y = 375; y > 0; y = y - 50)
children[1].add(new JButton("1"), new XYConstraints(x, y, w, h));
for (y = 325, x = 0; y > 0 && x < 280; y = y - 50, x = x + 40)
children[2].add(new JButton("2"), new XYConstraints(x, y, w, 2 * h));
for (y = 275, x = 0; y > 0 && x < 240; y = y - 50, x = x + 40)
children[3].add(new JButton("3"), new XYConstraints(x, y, w, 3 * h));
but something's missing like a loop for "children[i]".I'm sure there is a better solution to improve the loop Any idea of improvement or suggestion ? Thanks
I write my own layout because existing layout manager don't meet my requirements
Right idea, but your implementation is incorrect. The fact that you need to provide the x/y values means you are not using a layout manager but just hardcoding some values.
Instead you need to provide information to the layout manager to define the parameters of the layout, maybe something like:
MyLayout layout = new MyLayout(xSize, ySize, xOffset, yOffset);
So for the first panel you would use:
MyLayout layout = new MyLayout(50, 50, 0, 50);
This code would say that each component is (50, 50). As you add components to the panel you change the x offset by 0 and the y offset = -50.
You know you have 8 buttons so you can use math to figure out the width/height of the panel. You can then use a loop inside the layout manager to position each component.
So now you add components to the panel like:
panel.add( new JButton("1") );
panel.add( new JButton("2") );
panel.add( new JButton("3") );
For the second panel you might use:
MyLayout layout = new MyLayout(50, 100, 50, 50);
So this time it means each button know has a size of (50, 100) and each button is placed (50, -50) to the previous button.
This is how layout managers should be created. You should not need complex loops to build the constraints of each component that you add to the panel. That is the job of the layout manager.
You could try:
for( int i=1; i<=3; i++ ) {
x = 0;
for( y=375-((i-1)*50; y>0; y-=50, x+=40 ) {
children[i].add(new JButton((String)i), new XYConstraints(x, y, w, i*h));
}
}

Bar Chart in java

I want to change the height of each bar (for example 10 for red part and 20 for blue part). But when I increase the height value it will increase the chart from bottom whereas I want the change to top! Do you know what is wrong with it?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ChartPanel extends JPanel {
private double[] values;
private String[] names;
private String title;
public ChartPanel(double[] v, String[] n, String t) {
names = n;
values = v;
title = t;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (values == null || values.length == 0)
return;
double minValue = 0;
double maxValue = 0;
for (int i = 0; i < values.length; i++) {
if (minValue > values[i])
minValue = values[i];
if (maxValue < values[i])
maxValue = values[i];
}
Dimension d = getSize();
int clientWidth = d.width;
int clientHeight = d.height;
int barWidth = clientWidth / values.length;
Font titleFont = new Font("SansSerif", Font.BOLD, 20);
FontMetrics titleFontMetrics = g.getFontMetrics(titleFont);
Font labelFont = new Font("SansSerif", Font.PLAIN, 10);
FontMetrics labelFontMetrics = g.getFontMetrics(labelFont);
int titleWidth = titleFontMetrics.stringWidth(title);
int y = titleFontMetrics.getAscent();
int x = (clientWidth - titleWidth) / 2;
g.setFont(titleFont);
g.drawString(title, x, y);
int top = titleFontMetrics.getHeight();
int bottom = labelFontMetrics.getHeight();
if (maxValue == minValue)
return;
double scale = (clientHeight - top - bottom) / (maxValue - minValue);
y = clientHeight - labelFontMetrics.getDescent();
g.setFont(labelFont);
for (int i = 0; i < values.length; i++) {
int valueX = i * barWidth + 1;
int valueY = top;
int height = (int) (values[i] * scale);
if (values[i] >= 0)
valueY += (int) ((maxValue - values[i]) * scale);
else {
valueY += (int) (maxValue * scale);
height = -height;
}
g.setColor(Color.red);
g.fillRect(valueX, valueY, barWidth - 80, height);
g.setColor(Color.black);
g.drawRect(valueX, valueY, barWidth - 80, height);
g.setColor(Color.blue);
g.fillRect(valueX, valueY + 20, barWidth - 80, height-20 );
g.setColor(Color.black);
g.drawRect(valueX, valueY + 20, barWidth - 80, height-20 );
int labelWidth = labelFontMetrics.stringWidth(names[i]);
x = i * barWidth + (barWidth - labelWidth) / 2;
g.drawString(names[i], x, y);
}
}
public static void main(String[] argv) {
JFrame f = new JFrame();
f.setSize(400, 300);
double[] values = new double[3];
String[] names = new String[3];
values[0] = 1;
names[0] = "Item 1";
values[1] = 2;
names[1] = "Item 2";
values[2] = 4;
names[2] = "Item 3";
f.getContentPane().add(new ChartPanel(values, names, "title"));
WindowListener wndCloser = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
f.addWindowListener(wndCloser);
f.setVisible(true);
}
}
Because Java's graphics uses the top left corner as the origin, when you add to the height it will increase down instead of up. Try changing this:
g.setColor(Color.red);
g.fillRect(valueX, valueY, barWidth - 80, height);
g.setColor(Color.black);
g.drawRect(valueX, valueY, barWidth - 80, height);
To this:
g.setColor(Color.red);
g.fillRect(valueX, valueY - 20, barWidth - 80, height);
g.setColor(Color.black);
g.drawRect(valueX, valueY - 20, barWidth - 80, height);
I tried this and it added to the red portion of the bar at the top.
Here is a shot of the original code:
And with the change:

Categories

Resources