Icon is not set right on GlassPane - java

I have a class that sets warning icons behind a textField when the input is different from what i expect form the user. For textfield this class works perfect, but when i'm trying to use it with a textArea the warning icons aren't set on the right location .
here is the class that sets and removes the warning icons:
public class GlassValidationPane extends JComponent {
private HashMap<Component, JLabel> warningLabels = new HashMap<>();
private ImageIcon warningIcon;
private final ImageUtilities iU = new ImageUtilities();
public GlassValidationPane() {
setLayout(null);
setOpaque(false);
Icon icon = UIManager.getIcon("OptionPane.warningIcon");
int imgW = icon.getIconWidth();
int imgH = icon.getIconHeight();
BufferedImage img = iU.getBufferedImageOfIcon(icon, imgW, imgH);
warningIcon = new ImageIcon(iU.resize(img, 18, 18));
}
void showWarningIcon(Component c) {
if (warningLabels.containsKey(c)) {
return;
}
JLabel label = new JLabel();
label.setIcon(warningIcon);
//int x=c.getX();//this will make it insode the component
int x = c.getWidth() + c.getX() + label.getIcon().getIconWidth();//this makes it appear outside/next to component);
int y = c.getY();
System.out.println("ïn show warning: " + y);
label.setBounds(x, y, label.getIcon().getIconWidth(), label.getIcon().getIconHeight());
add(label);
label.setVisible(true);
revalidate();
repaint();
warningLabels.put(c, label);
}
public void removeWarningIcon(Component c) {
for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) {
Component component = entry.getKey();
JLabel jLabel = entry.getValue();
if (component == c) {
remove(jLabel);
revalidate();
repaint();
break;
}
}
warningLabels.remove(c);
}
public void refreshLocations() {
for (Map.Entry<Component, JLabel> entry : warningLabels.entrySet()) {
Component c = entry.getKey();
JLabel label = entry.getValue();
int x = c.getWidth() + c.getX() + label.getIcon().getIconWidth();//this makes it appear outside/next to component
int y = c.getY();
label.setBounds(x, y, label.getIcon().getIconWidth(), label.getIcon().getIconHeight());
revalidate();
repaint();
}
}
public boolean allSet(){
if(!warningLabels.isEmpty()){
JOptionPane.showMessageDialog(null, "Please fill every text field in, or adjust te wrong input", "Empty input/Wrong input", JOptionPane.ERROR_MESSAGE);
return false;
}
return true;
}
private class ImageUtilities {
public BufferedImage resize(BufferedImage image, int width, int height) {
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D g2d = (Graphics2D) bi.createGraphics();
g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
g2d.drawImage(image, 0, 0, width, height, null);
g2d.dispose();
return bi;
}
public BufferedImage getBufferedImageOfIcon(Icon icon, int imgW, int imgH) {
BufferedImage img = new BufferedImage(imgW, imgH, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = (Graphics2D) img.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
icon.paintIcon(null, g2d, 0, 0);
g2d.dispose();
return img;
}
}
}
I have found that the getY() function for the textArea always gives 0 back, but i can't find why it always return 0. here is the code who calls the class ClaxxValidationPane:
public class JobInput extends JFrame {
private JPanel contentPane;
private JTextField txtJobId;
private GlassValidationPane gvp;
private JTextArea textAreaDesription;
private boolean INSERT;
/**
* Create the frame.
*/
public JobInput(String titel, boolean INSERT) {
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
}
});
setBounds(100, 100, 296, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
GridBagLayout gbl_contentPane = new GridBagLayout();
gbl_contentPane.columnWidths = new int[]{0, 0, 0};
gbl_contentPane.rowHeights = new int[]{0, 0, 0, 0, 0, 0};
gbl_contentPane.columnWeights = new double[]{0.0, 0.0, Double.MIN_VALUE};
gbl_contentPane.rowWeights = new double[]{0.0, 0.0, 0.0, 1.0, 0.0, Double.MIN_VALUE};
contentPane.setLayout(gbl_contentPane);
JLabel lblTitel = new JLabel(titel);
lblTitel.setFont(new Font("Arial", Font.BOLD, 15));
GridBagConstraints gbc_lblTitel = new GridBagConstraints();
gbc_lblTitel.gridwidth = 2;
gbc_lblTitel.insets = new Insets(0, 0, 5, 0);
gbc_lblTitel.gridx = 0;
gbc_lblTitel.gridy = 0;
contentPane.add(lblTitel, gbc_lblTitel);
JSeparator separator = new JSeparator();
GridBagConstraints gbc_separator = new GridBagConstraints();
gbc_separator.fill = GridBagConstraints.BOTH;
gbc_separator.gridwidth = 2;
gbc_separator.insets = new Insets(0, 0, 5, 0);
gbc_separator.gridx = 0;
gbc_separator.gridy = 1;
contentPane.add(separator, gbc_separator);
JLabel lblJobid = new JLabel("JobID");
GridBagConstraints gbc_lblJobid = new GridBagConstraints();
gbc_lblJobid.anchor = GridBagConstraints.EAST;
gbc_lblJobid.insets = new Insets(0, 0, 5, 5);
gbc_lblJobid.gridx = 0;
gbc_lblJobid.gridy = 2;
contentPane.add(lblJobid, gbc_lblJobid);
txtJobId = new JTextField();
GridBagConstraints gbc_txtJobId = new GridBagConstraints();
gbc_txtJobId.insets = new Insets(0, 0, 5, 0);
gbc_txtJobId.fill = GridBagConstraints.HORIZONTAL;
gbc_txtJobId.gridx = 1;
gbc_txtJobId.gridy = 2;
contentPane.add(txtJobId, gbc_txtJobId);
txtJobId.setColumns(10);
JLabel lblDescription = new JLabel("Description");
GridBagConstraints gbc_lblDescription = new GridBagConstraints();
gbc_lblDescription.anchor = GridBagConstraints.NORTH;
gbc_lblDescription.insets = new Insets(0, 0, 5, 5);
gbc_lblDescription.gridx = 0;
gbc_lblDescription.gridy = 3;
contentPane.add(lblDescription, gbc_lblDescription);
textAreaDesription = new JTextArea();
textAreaDesription.setLineWrap(true);
textAreaDesription.setWrapStyleWord(true);
GridBagConstraints gbc_textArea = new GridBagConstraints();
gbc_textArea.insets = new Insets(0, 0, 5, 0);
gbc_textArea.fill = GridBagConstraints.BOTH;
gbc_textArea.gridx = 1;
gbc_textArea.gridy = 3;
JScrollPane scroll = new JScrollPane (textAreaDesription,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
contentPane.add(scroll, gbc_textArea);
JButton btnOk = new JButton("Ok");
GridBagConstraints gbc_btnOk = new GridBagConstraints();
gbc_btnOk.gridwidth = 2;
gbc_btnOk.gridx = 0;
gbc_btnOk.gridy = 4;
contentPane.add(btnOk, gbc_btnOk);
gvp = new GlassValidationPane();
FocusAdapter fl = new FocusAdapter() {
#Override
public void focusGained(FocusEvent fe) {
super.focusGained(fe);
((JTextComponent) fe.getSource()).setBorder(BorderFactory.createLineBorder(Color.gray));
}
public void focusLost(FocusEvent fe) {
super.focusLost(fe);
if(fe.getSource().equals(txtJobId)){
validationForInteger(txtJobId);
} else if(fe.getSource().equals(textAreaDesription)){
validationForText(textAreaDesription);
} else{
gvp.removeWarningIcon(((Component) fe.getSource()));
((JTextComponent) fe.getSource()).setBorder(BorderFactory.createLineBorder(Color.gray));
}
}
};
txtJobId.addFocusListener(fl);
textAreaDesription.addFocusListener(fl);
setGlassPane(gvp);
gvp.setVisible(true);
}
private void validationForInteger(JTextComponent comp){
String temp = comp.getText();
if(temp.matches("^[1-9]\\d*$")){
setGreen(comp);
} else {
setRed(comp);
}
}
private void validationForText(JTextComponent comp) {
System.out.println("In validation for text " + textAreaDesription.getY());
String temp = comp.getText();
if (temp.matches("^[a-zA-Z0-9][a-zA-Z0-9\\s_/-]+$")) {
setGreen(comp);
} else {
setRed(comp);
}
}
private void setRed(JTextComponent comp) {
comp.setBorder(BorderFactory.createLineBorder(Color.red));
gvp.showWarningIcon(comp);
}
private void setGreen(JTextComponent comp) {
comp.setBorder(BorderFactory.createLineBorder(Color.green));
gvp.removeWarningIcon(comp);
}
}
thus the focus listners shall call for validation and there the classValidaionPane shall be called. If it is called then it goes wrong (but only for textArea's and not for textField) can somebody help me with this?

The parent component of the JTextArea is not the same as the parent component of the JTextField, since the JTextArea is inside a JScrollPane. I have not taken the time to read and understand all the code you posted, but you should probably placed the label relative to the position of the JScrollPane, and not relative to the position of the JTextArea.

Related

GridBagConstraints ipad lock size

I'm new to Java Swing and am working on a project to help me become more familiar with it. I've noticed while changing the label text, the cell in the GridBagLayout increases/decreases (you can tell by the borderline resizing). I was wondering if there was a way to lock the ipad size, so it doesn't change (after it is set). Is there a way to lock the ipad size?
Below are images so you can see what I'm talking about.
Before:
After:
Notice how the label shrinks when a single digit is put in. And if a double digit is put in, the label expands (larger than the "- -" label)
Here is the code:
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class StartGuiTest extends JFrame implements ActionListener {
private static final int unselectedDefaultElement = 0;
private static final String unselectedLvl = "- -";
private static final int maxLvl = 99;
private static final String[] GuiCharSel = {"--- Select Character ---", "Cloud", "Barret", "Tifa", "Aeris", "Red XIII", "Yuffie", "Cait Sith", "Vincent", "Cid"};
private String[] lvlRange = createArrRange(unselectedLvl, 1, maxLvl);
/*
* Interactive GUI Objects
*/
JLabel charPic;
JComboBox charSelCombo = new JComboBox(GuiCharSel);
JComboBox pickLvlAns = new JComboBox(lvlRange);
JLabel nextLvlAns = new JLabel(unselectedLvl);
public StartGuiTest() {
JPanel topFrame = new JPanel();
JPanel bottomFrame = new JPanel();
JPanel selPane = new JPanel();
JLabel pickLvl = new JLabel("Pick Current Level:");
JLabel nextLvl = new JLabel("Next Level:");
TitledBorder topFrameTitle;
Border blackLine = BorderFactory.createLineBorder(Color.black);
Border raisedBevel = BorderFactory.createRaisedBevelBorder();
Border loweredBevel = BorderFactory.createLoweredBevelBorder();
Border compound = BorderFactory.createCompoundBorder(raisedBevel, loweredBevel);
topFrameTitle = BorderFactory.createTitledBorder(compound, "Character");
topFrameTitle.setTitleJustification(TitledBorder.CENTER);
topFrame.setBorder(topFrameTitle);
topFrame.setLayout(new BoxLayout(topFrame, BoxLayout.X_AXIS));
/*
* Adds Character Picture
*/
charPic = new JLabel("", null, JLabel.CENTER);
charPic.setPreferredSize(new Dimension(100,100));
topFrame.add(charPic);
//*******************************************************************************
/*
* Selection Pane Settings
*/
selPane.setLayout(new GridBagLayout());
/*
* Adds Character Selection ComboBox
*/
charSelCombo.setPrototypeDisplayValue(charSelCombo.getItemAt(unselectedDefaultElement));
selPane.add(charSelCombo, setGbc(0,0, 0, 0, "WEST", 0, 1, setInsets(0, 10, 0, 0)));
charSelCombo.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
charSelCombo.removeItem(GuiCharSel[unselectedDefaultElement]);
pickLvlAns.removeItem(lvlRange[unselectedDefaultElement]);
}
}
);
/*
* Adds "Pick Current Level:" Label
*/
selPane.add(pickLvl, setGbc(0,1, 0, 0, "EAST", 0, 1, setInsets(0, 0, 0, 0)));
/*
* Adds Character Current Level ComboBox
*/
pickLvlAns.setPrototypeDisplayValue(pickLvlAns.getItemAt(lvlRange.length - 1));
selPane.add(pickLvlAns, setGbc(1,1, 0, 0, "WEST", 1, 1, setInsets(0, 10, 0, 0)));
pickLvlAns.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
String currLvl = ((JComboBox)(e.getSource())).getSelectedItem().toString();
if(isInteger(currLvl)){
if (Integer.parseInt(currLvl) == maxLvl){
nextLvlAns.setText(unselectedLvl);
} else {
nextLvlAns.setText(Integer.toString(Integer.parseInt(currLvl) + 1));
}
} else {
nextLvlAns.setText(unselectedLvl);
}
}
}
);
/*
* Adds "Next Level:" Label
*/
selPane.add(nextLvl, setGbc(0,2, 0, 0, "EAST", 0, 1, setInsets(0, 0, 0, 0)));
/*
* Adds Character Next Level Label
*/
nextLvlAns.setBorder(blackLine);
nextLvlAns.setHorizontalAlignment(JLabel.CENTER);
selPane.add(nextLvlAns, setGbc(1,2, 28, 5, "WEST", 1, 1, setInsets(0, 10, 0, 0)));
//*******************************************************************************
topFrame.add(selPane);
//*******************************************************************************
/*
* BOTTOM PANE
*/
TitledBorder bottomFrameTitle;
bottomFrameTitle = BorderFactory.createTitledBorder(compound, "Stats");
bottomFrameTitle.setTitleJustification(TitledBorder.CENTER);
bottomFrame.setBorder(bottomFrameTitle);
//*******************************************************************************
/*
* Display everything in GUI to user
*/
add(topFrame, BorderLayout.NORTH);
add(bottomFrame,BorderLayout.CENTER);
setSize(800,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent arg0) {
}
private GridBagConstraints setGbc(int gridx, int gridy, int ipadx, int ipady, String anchorLocation, double weightx, double weighty, Insets insets){
GridBagConstraints gbc = new GridBagConstraints();
if (anchorLocation.toUpperCase().equals("NORTHWEST")){
gbc.anchor = GridBagConstraints.NORTHWEST;
} else if (anchorLocation.toUpperCase().equals("NORTH")){
gbc.anchor = GridBagConstraints.NORTH;
} else if (anchorLocation.toUpperCase().equals("NORTHEAST")){
gbc.anchor = GridBagConstraints.NORTHEAST;
} else if (anchorLocation.toUpperCase().equals("WEST")){
gbc.anchor = GridBagConstraints.WEST;
} else if (anchorLocation.toUpperCase().equals("EAST")){
gbc.anchor = GridBagConstraints.EAST;
} else if (anchorLocation.toUpperCase().equals("SOUTHWEST")){
gbc.anchor = GridBagConstraints.SOUTHWEST;
} else if (anchorLocation.toUpperCase().equals("SOUTH")){
gbc.anchor = GridBagConstraints.SOUTH;
} else if (anchorLocation.toUpperCase().equals("SOUTHEAST")){
gbc.anchor = GridBagConstraints.SOUTHEAST;
} else {
gbc.anchor = GridBagConstraints.CENTER;
}
gbc.gridx = gridx;
gbc.gridy = gridy;
gbc.ipadx = ipadx;
gbc.ipady = ipady;
gbc.weightx = weightx;
gbc.weighty = weighty;
gbc.insets = insets;
return gbc;
}
private Insets setInsets(int top, int left, int bottom, int right){
Insets insets = new Insets(top,left,bottom,right);
return insets;
}
protected static String[] createArrRange(String firstElement, int startNum, int endNum) {
String[] strArr = new String[endNum+1];
strArr[0] = firstElement;
for (int num = startNum, element = 1; num <= endNum; num++, element++){
strArr[element] = Integer.toString(num);
}
return strArr;
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
} catch(NumberFormatException e) {
return false;
} catch(NullPointerException e) {
return false;
}
// only got here if we didn't return false
return true;
}
public static void main(String[] args) {
new StartGuiTest();
}
}
I've tried using label.setPrototypeDisplayValue(), but I guess this only works for the combo boxes in locking them so they don't change the size. I can't seem to find anything in the libraries or google that shows how to do this.
Welcome to the wonderful world of variable width fonts.
I would summiuse that the issue isn't with the nextLvlAns, but with the pickLvlAns
The problem seems to be -- is a different size then 2, which is changing the size of the combo box.
You started in the right direction with the using setPrototypeDisplayValue, but I'd suggest using something long pickLvlAns.setPrototypeDisplayValue("00"); for example or even maybe pickLvlAns.setPrototypeDisplayValue("----");, so that it covers a larger possible range.
Remember, when using variable width fonts, 0 is likely to be larger the -
Another trick might be to use a non editable JTextField instead of a JLabel, this because, JLabel keeps wanting to accommodate itself to the text content
JTextField nextLvlAns = new JTextField(unselectedLvl, 3);
//...
nextLvlAns.setEditable(false);

JTextField horizontal scrolling java swing

I have a JTextField inside a JPanel . The user can type text as big as she wants in the textfield , however horizontal scrolling should appear when the text goes beyond the screen of the textfield. At this point if the user backspace the text and shrink the text within the screen of the textfield , the scrolling should disappear. So basically scrolling should appear only when its needed. How to do it ? Help please.
If you don't like the behavior of the JScrollPane + JTextField, you need to use JScrollBar#setModel(BoundedRangeModel) + JTextField#getHorizontalVisibility():
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicScrollBarUI;
public class TextFieldScrollBarTest {
private static final String TEXT = "javascript:(function(){var l=location,m=l.href.match('^(https?://)(.+)(api[^+]+|technotes[^+]+)');if(m)l.href=m[1]+'docs.oracle.com/javase/8/docs/'+decodeURIComponent(m[3]).replace(/\\+.*$/,'').replace(/\\[\\]/g,':A').replace(/, |\\(|\\)/g,'-');}());";
public JComponent makeUI() {
JScrollPane scroll = new JScrollPane(new JTextField(TEXT));
scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
JTextField textField = new JTextField(TEXT);
JScrollBar scroller = new JScrollBar(Adjustable.HORIZONTAL) {
#Override public void updateUI() {
//super.updateUI();
setUI(new ArrowButtonlessScrollBarUI());
}
#Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
d.height = 5;
return d;
}
};
scroller.setModel(textField.getHorizontalVisibility());
Box box = Box.createVerticalBox();
box.add(scroll);
box.add(Box.createVerticalStrut(50));
box.add(textField);
box.add(Box.createVerticalStrut(2));
box.add(scroller);
box.add(Box.createVerticalGlue());
JPanel p = new JPanel(new BorderLayout());
p.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
p.add(box, BorderLayout.NORTH);
return p;
}
public static void main(String... args) {
EventQueue.invokeLater(() -> {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new TextFieldScrollBarTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
class ZeroSizeButton extends JButton {
private static final Dimension ZERO_SIZE = new Dimension();
#Override public Dimension getPreferredSize() {
return ZERO_SIZE;
}
}
class ArrowButtonlessScrollBarUI extends BasicScrollBarUI {
private static final Color DEFAULT_COLOR = new Color(220, 100, 100);
private static final Color DRAGGING_COLOR = new Color(200, 100, 100);
private static final Color ROLLOVER_COLOR = new Color(255, 120, 100);
#Override protected JButton createDecreaseButton(int orientation) {
return new ZeroSizeButton();
}
#Override protected JButton createIncreaseButton(int orientation) {
return new ZeroSizeButton();
}
#Override protected void paintTrack(Graphics g, JComponent c, Rectangle r) {
//Graphics2D g2 = (Graphics2D) g.create();
//g2.setPaint(new Color(100, 100, 100));
//g2.fillRect(r.x, r.y, r.width - 1, r.height - 1);
//g2.dispose();
}
#Override protected void paintThumb(Graphics g, JComponent c, Rectangle r) {
JScrollBar sb = (JScrollBar) c;
if (!sb.isEnabled()) {
return;
}
BoundedRangeModel m = sb.getModel();
int iv = m.getMaximum() - m.getMinimum() - m.getExtent() - 1; // -1: bug?
if (iv > 0) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color;
if (isDragging) {
color = DRAGGING_COLOR;
} else if (isThumbRollover()) {
color = ROLLOVER_COLOR;
} else {
color = DEFAULT_COLOR;
}
g2.setPaint(color);
g2.fillRect(r.x, r.y, r.width - 1, r.height - 1);
g2.dispose();
}
}
}

Add a button over image

How can I add a button over an image created with JLabel?
Even if I put the same coordinates on ".setbounds" the image usually gets behind the buttons.
public class Tatica extends JFrame {
JPanel jl = new JPanel();
JLabel jp = new JLabel();
public Tatica(){
jl.setLayout(null);
jp.setIcon(new ImageIcon("C:\\Users\\LG\\workspace\\Teste\\src\\snippet\\asdiuashd.Jpg"));
jl.add(jp);
add(jl);
jp.setBounds(100, 0, 1000, 1000);
validate();
JButton team2 = new JButton("Gk");
jl.add(team2);
team2.setBounds(400, 0, 100, 20);
team2.setVisible(true);
team2.setLayout(null);
JButton dc = new JButton("Dc");
jl.add(dc);
dc.setBounds(300, 200, 100, 20);
dc.setVisible(true);
JButton dc2 = new JButton("Dc");
jl.add(dc2);
dc2.setBounds(500, 200, 100, 20);
dc2.setVisible(true);
JButton dl = new JButton("Dl");
jl.add(dl);
dl.setBounds(100, 200, 100, 20);
dl.setVisible(true);
JButton dr = new JButton("Dr");
jl.add(dr);
dr.setBounds(700, 200, 100, 20);
dr.setVisible(true);
}
}
I'd instead slice up the image and use the sub-images as icons for either buttons or labels. Then arrange them all in a GridBagLayout.
Here is an example of what I mean (special thanks to #camickr for solving the bug in my layout code!):
(It uses a an icon with a transparent shade of white for mouse hover, black for pressed. The mouse was pointing at the left center forward when the screen shot was taken. It is left as an exercise for the reader to implement the logic needed to alternate between labels and buttons as required, in the GUI formed from 81 sub images.)
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
import javax.imageio.ImageIO;
public class SoccerField {
private JPanel ui = null;
int[] x = {0, 35, 70, 107, 142, 177, 212, 247, 282, 315};
int[] y = {0, 45, 85, 140, 180, 225, 265, 280, 320, 345};
Color brighter = new Color(255,255,255,92);
Color darker = new Color(0,0,0,92);
SoccerField() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new GridBagLayout());
ui.setBackground(Color.RED);
try {
URL url = new URL("http://i.stack.imgur.com/9E5ky.jpg");
BufferedImage img = ImageIO.read(url);
BufferedImage field = img.getSubimage(100, 350, 315, 345);
BufferedImage[] bi = subSampleImageColumns(field);
BufferedImage[][] fieldParts = new BufferedImage[bi.length][];
for (int ii=0; ii<bi.length; ii++) {
fieldParts[ii] = subSampleImageRows(bi[ii]);
}
for (int ii=0; ii<fieldParts[0].length; ii++) {
for (int jj=0; jj<fieldParts.length; jj++) {
addImageToPanel(ui, fieldParts[ii][jj], ii, jj);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private void addImageToPanel(
JPanel panel, BufferedImage img, int row, int col) {
Insets insets = new Insets(0,0,0,0);
double weighty = img.getHeight()==40 ? .5 : .1;
GridBagConstraints gbc = new GridBagConstraints(
row, col,
1, 1,
.5, weighty,
GridBagConstraints.CENTER,
GridBagConstraints.BOTH,
insets, 0, 0);
ImageIcon ii = new ImageIcon(img);
JButton b = new JButton(ii);
b.setRolloverIcon(new ImageIcon(getFadeImage(img, brighter)));
b.setPressedIcon(new ImageIcon(getFadeImage(img, darker)));
b.setBorder(null);
b.setBorder(new EmptyBorder(0, 0, 0, 0));
b.setBorderPainted(false);
b.setContentAreaFilled(false);
b.setFocusPainted(false);
panel.add(b, gbc);
}
private BufferedImage[] subSampleImageColumns(BufferedImage img) {
BufferedImage[] imageRows = new BufferedImage[x.length - 1];
for (int ii = 0; ii < x.length - 1; ii++) {
BufferedImage bi = img.getSubimage(
x[ii], 0, x[ii + 1] - x[ii], img.getHeight());
imageRows[ii] = bi;
}
return imageRows;
}
private BufferedImage[] subSampleImageRows(BufferedImage img) {
BufferedImage[] imageRows = new BufferedImage[y.length - 1];
for (int ii = 0; ii < y.length - 1; ii++) {
BufferedImage bi = img.getSubimage(
0, y[ii], img.getWidth(), y[ii + 1] - y[ii]);
imageRows[ii] = bi;
}
return imageRows;
}
private BufferedImage getFadeImage(BufferedImage img, Color clr) {
BufferedImage bi = new BufferedImage(
img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics g = bi.getGraphics();
g.drawImage(img, 0, 0, ui);
g.setColor(clr);
g.fillRect(0, 0, img.getWidth(), img.getHeight());
g.dispose();
return bi;
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
SoccerField o = new SoccerField();
JFrame f = new JFrame(o.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}
How can I add a button over an image created with JLabel?
Add the buttons to the label, not the panel.
So the basic code is:
JPanel panel = new JPanel();
JLabel label = new JLabel( new ImageIcon(...) );
label.setLayout( new FlowLayout() );
JButton button1 = new JButton("Button1");
label.add(button1);
JButton button2 = new JButton("Button1");
label.add(button2);
So now the label will be the size of the image. The buttons will be displayed in a FlowLayout on the image. It is your responsibility to make sure the buttons fit on the image or the buttons will not be displayed properly.
The question is do you really need to add the label to the panel or should you just add the label to the frame?

Swing - positioning some JButtons

I'm trying to make a little game with JButton objects. My problem is, when I add buttons to my panel, they don't position where I need them. To be more clear.
This is the Image I have :
Here's my code :
My main class which extends JFrame adds a new Board1 which extends JPanel
public class Main2 extends JFrame {
public Main2() {
setVisible(true);
setSize(500, 500);
add(new Board1());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setTitle("Zombicide");
setResizable(false);
}
public static void main(String[] args) {
new Main2();
}
}
My Board class which extends JPanel and adds some Zone objects which extend JButton.
public class Board1 extends JPanel implements Board {
private List<Zone> zones = new ArrayList<Zone>();
public Board1() {
zones.add(new Zone(1, false, true, null, "/zone1D1C.jpg", 0, 0, this));
zones.add(new Zone(2, false, false, null, "/zone2D1C.jpg", 150, 0, this));
zones.add(new Zone(3, false, false, null, "/zone3D1C.jpg", 300, 0, this));
zones.add(new Zone(4, true, false, null, "/zone4D1C.jpg", 0, 150, this));
zones.add(new Zone(5, false, false, null, "/zone5D1C.jpg", 300, 150, this));
zones.add(new Zone(6, true, false, null, "/zone6D1C.jpg", 0, 300, this));
zones.add(new Zone(7, true, false, null, "/zone7D1C.jpg", 150, 300, this));
zones.add(new Zone(8, false, false, null, "/zone8D1C.jpg", 300, 300, this));
}
}
And finally my zone class which extends JButton
public class Zone extends JButton implements ActionListener {
private final Zone zone;
private final Board board;
private Integer id;
private boolean piece;
private boolean egout;
private Integer x;
private Integer y;
private Integer x_end;
private Integer y_end;
public Zone(Integer id, boolean piece, boolean egout, Dalle[] dalles, List<Connexion> connexions, String image_name, Integer x, Integer y, Board board) {
zone = this;
addMouseListener(new TAdapter());
this.board = board;
this.piece = piece;
this.egout = egout;
this.id = id;
this.setLayout(null);
this.setBorder(null);
this.setText(null);
ImageIcon ii = new ImageIcon(this.getClass().getResource(image_name));
this.setIcon(ii);
this.x = x;
this.y = y;
this.setBounds(x, y, ii.getIconWidth(), ii.getIconHeight());
this.x_end = x + ii.getIconWidth();
this.y_end = y + ii.getIconHeight();
this.setSize(ii.getIconWidth(), ii.getIconHeight());
}
private class TAdapter extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
if (gotoZone()) {
...
} else {
System.out.println("error");
}
}
}
}
The GridBagLayout is the best suitable layout for what you try to achieve. It could be something like this :
public class Board1 extends JPanel implements Board {
public Board1() {
super();
this.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 0;
constraints.gridy = 0;
this.add(new Zone(...), constraints);
constraints.gridx = 1;
constraints.gridy = 0;
this.add(new Zone(...), constraints);
// You caught the point I think
}
}
You have a good tutorial made by Oracle here.
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;
public class ZombiecideLayout {
private JComponent ui = null;
ZombiecideLayout() {
initUI();
}
public void initUI() {
if (ui != null) {
return;
}
ui = new JPanel(new GridBagLayout());
ui.setBorder(new EmptyBorder(4, 4, 4, 4));
try {
URL dayAddress = new URL("http://i.stack.imgur.com/OVOg3.jpg");
URL nightAddress = new URL("http://i.stack.imgur.com/lxthA.jpg");
BufferedImage biDay = ImageIO.read(
dayAddress).getSubimage(180, 0, 300, 300);
BufferedImage biNight = ImageIO.read(
nightAddress).getSubimage(180, 0, 300, 300);
GridBagConstraints gbc = new GridBagConstraints();
Insets pad = new Insets(0,0,0,0);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = pad;
gbc.gridwidth = 1;
gbc.gridheight = 1;
JButton b1 = new JButton();
b1.setContentAreaFilled(false);
b1.setBorder(null);
b1.setMargin(pad);
b1.setIcon(new ImageIcon(biDay.getSubimage(0, 0, 100, 100)));
b1.setRolloverIcon(new ImageIcon(biNight.getSubimage(0, 0, 100, 100)));
ui.add(b1, gbc);
gbc.gridx = 1;
JButton b2 = new JButton();
b2.setContentAreaFilled(false);
b2.setBorder(null);
b2.setMargin(pad);
b2.setIcon(new ImageIcon(biDay.getSubimage(100, 0, 100, 100)));
b2.setRolloverIcon(new ImageIcon(biNight.getSubimage(100, 0, 100, 100)));
ui.add(b2, gbc);
gbc.gridx = 2;
JButton b3 = new JButton();
b3.setContentAreaFilled(false);
b3.setBorder(null);
b3.setMargin(pad);
b3.setIcon(new ImageIcon(biDay.getSubimage(200, 0, 100, 100)));
b3.setRolloverIcon(new ImageIcon(biNight.getSubimage(200, 0, 100, 100)));
ui.add(b3, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 2;
JButton b4 = new JButton();
b4.setContentAreaFilled(false);
b4.setBorder(null);
b4.setMargin(pad);
b4.setIcon(new ImageIcon(biDay.getSubimage(0, 100, 200, 100)));
b4.setRolloverIcon(new ImageIcon(biNight.getSubimage(0, 100, 200, 100)));
ui.add(b4, gbc);
gbc.gridx = 2;
gbc.gridy = 1;
gbc.gridwidth = 1;
JButton b5 = new JButton();
b5.setContentAreaFilled(false);
b5.setBorder(null);
b5.setMargin(pad);
b5.setIcon(new ImageIcon(biDay.getSubimage(200, 100, 100, 100)));
b5.setRolloverIcon(new ImageIcon(biNight.getSubimage(200, 100, 100, 100)));
ui.add(b5, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
JButton b6 = new JButton();
b6.setContentAreaFilled(false);
b6.setBorder(null);
b6.setMargin(pad);
b6.setIcon(new ImageIcon(biDay.getSubimage(0, 200, 100, 100)));
b6.setRolloverIcon(new ImageIcon(biNight.getSubimage(0, 200, 100, 100)));
ui.add(b6, gbc);
gbc.gridx = 1;
JButton b7 = new JButton();
b7.setContentAreaFilled(false);
b7.setBorder(null);
b7.setMargin(pad);
b7.setIcon(new ImageIcon(biDay.getSubimage(100, 200, 100, 100)));
b7.setRolloverIcon(new ImageIcon(biNight.getSubimage(100, 200, 100, 100)));
ui.add(b7, gbc);
gbc.gridx = 2;
JButton b8 = new JButton();
b8.setContentAreaFilled(false);
b8.setBorder(null);
b8.setMargin(pad);
b8.setIcon(new ImageIcon(biDay.getSubimage(200, 200, 100, 100)));
b8.setRolloverIcon(new ImageIcon(biNight.getSubimage(200, 200, 100, 100)));
ui.add(b8, gbc);
} catch (Exception ex) {
ex.printStackTrace();
}
}
public JComponent getUI() {
return ui;
}
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
ZombiecideLayout o = new ZombiecideLayout();
JFrame f = new JFrame("Zombiecide Layout");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setLocationByPlatform(true);
f.setContentPane(o.getUI());
f.pack();
f.setMinimumSize(f.getSize());
f.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
}
}

What do I need to do to replicate this component with gradient paint?

I attempted to replicate this component (at the bottom of the post), but I can't seem to get it to look nice.
So I'm wondering, how do I replicate this gradient paint? Or if it isn't the gradient paint, what do I do to get similar results?
My attempt turned out very flat black compared to this component. Also it had the JFrame options (close, minimize, etc) and it didn't have a 'rounded' look to the components. I'm looking for someone who can improve what I have and explain where I went wrong. I know I can simply use an already made Look and Feel, but I would like to get my example project as close as possible to the BitDefender GUI in the image excluding the text. (I can provide code if need be)
Also notice I skipped the panel between Background and the 'Virus Shield', 'Auto Scan', 'My BitDefender' panels. I did this mainly because I wanted to keep my SSCCE as small as possible.
Also I want to note that setting the insets to gbc.insets = new Insets(2,10,2,10); on the 3 TopPanels makes it look much closer to the spacing of the BitDefender GUI. (I just didn't have the time to upload the picture at the moment. So I left the code as is, but I do realize that it can be updated to the above insets.
Edit - Updated with more source
Here is my code / SSCCE (it is 3 separate classes, but I consilidated them into one .java)
package testgui;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestGui {
public TestGui() {
JFrame frame = new JFrame();
MidPanel midPanel = new MidPanel();
TopPanel topPanel1 = new TopPanel();
TopPanel topPanel2 = new TopPanel();
TopPanel topPanel3 = new TopPanel();
JLabel appName = new JLabel("MyApplication");
JLabel verNum = new JLabel("version 1.0");
Font verFont = new Font("Tahoma", Font.BOLD, 11);
Font nameFont = new Font("Tahoma", Font.BOLD, 14);
GridBagConstraints gbc = new GridBagConstraints();
appName.setForeground(Color.WHITE);
appName.setFont(nameFont);
verNum.setForeground(Color.WHITE);
verNum.setFont(verFont);
//add program name and version number
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
midPanel.add(appName, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
midPanel.add(verNum, gbc);
//add 3 example top panels to midpanel
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(1,2,1,2);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
midPanel.add(topPanel1, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
gbc.insets = new Insets(1,2,1,2);
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
midPanel.add(topPanel2, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(1,2,1,2);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
midPanel.add(topPanel3, gbc);
//add panel to push other panels to top
gbc.gridx = 0;
gbc.gridy = 5;
gbc.fill = GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
JPanel invisPanel = new JPanel();
invisPanel.setOpaque(false);
midPanel.add(invisPanel, gbc);
frame.getContentPane().add(midPanel);
frame.pack();
frame.setVisible(true);
}
//test it out
public static void main(String[] args) {
new TestGui();
}
//class for the top 3 panels
private class TopPanel extends JPanel {
private int maxLength;
private boolean cyclic;
public TopPanel() {
initComponents();
setOpaque(false);
cyclic = true;
maxLength = 0;
}
#Override
public void paintComponent(Graphics g) {
if(isOpaque()) {
super.paintComponent(g);
return;
}
int width = getWidth();
int height = getHeight();
GradientPaint paint = null;
Color top = new Color(50, 50, 50);
Color btm = new Color(19, 19, 19);
paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);
if(paint == null) {
throw new RuntimeException("Invalid direction specified in GamerTagPanel");
}
Graphics2D g2d = (Graphics2D) g;
Paint oldPaint = g2d.getPaint();
g2d.setPaint(paint);
g2d.fillRect(0, 0, width, height);
g2d.setPaint(oldPaint);
super.paintComponent(g);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
private void initComponents() {
GridBagConstraints gbc;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
setBorder(BorderFactory.createLineBorder(new Color(204,204,204)));
setLayout(new GridBagLayout());
jLabel1.setFont(new Font("Tahoma", Font.BOLD, 11));
jLabel1.setForeground(new Color(255, 255, 255));
jLabel1.setText("Scanning...");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(5, 5, 5, 5);
add(jLabel1, gbc);
jLabel2.setFont(new java.awt.Font("Tahoma", Font.BOLD, 11));
jLabel2.setForeground(new java.awt.Color(255, 255, 255));
jLabel2.setText("C:\\Directory\\Folder\\SubFolder\\SpecificFolder\\File.file");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1.0;
gbc.insets = new Insets(5, 5, 5, 5);
add(jLabel2, gbc);
}
}
public class MidPanel extends JPanel {
private int maxLength;
private boolean cyclic;
public MidPanel() {
setLayout(new GridBagLayout());
setOpaque(false);
maxLength = 0;
cyclic = false;
}
#Override
public void paintComponent(Graphics g) {
if(isOpaque()) {
super.paintComponent(g);
return;
}
int width = getWidth();
int height = getHeight();
GradientPaint paint = null;
Color top = new Color(75, 75, 75);
Color btm = new Color(19, 19, 19);
paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);
if(paint == null) {
throw new RuntimeException("Invalid direction specified in GamerTagPanel");
}
Graphics2D g2d = (Graphics2D) g;
Paint oldPaint = g2d.getPaint();
g2d.setPaint(paint);
g2d.fillRect(0, 0, width, height);
g2d.setPaint(oldPaint);
super.paintComponent(g);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 400);
}
}
}
Thanks JoopEggen for pointing out my issue with colors on the GradientPaint. It helped out quite a bit. I'm still looking for someone to put together a better/closer looking example. This is my first go at overriding the paintComponent in such a way.
Let's do some reverse engineering first. Several simplifications can be maid during that process. Moreover, I would say it is also possible to enhance that application look, because first impression is far from being very positive.
Basically the following elements can be found behind that design:
gradients
properly selected colors
rounded corners
outlines
Please note, rounded corners, outlines are important. BTW, some gradients can be optimized to provide clean and simple design. Please check The Battle Between Flat Design And Skeuomorphism for additional motivation.
Your example was modified and looks like the following (it just a visual result):
I've used the following colors:
Code:
public class TestGui {
public TestGui() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MidPanel midPanel = new MidPanel();
TopPanel topPanel1 = new TopPanel();
TopPanel topPanel2 = new TopPanel();
TopPanel topPanel3 = new TopPanel();
JLabel appName = new JLabel("MyApplication");
JLabel verNum = new JLabel("version 1.0");
Font verFont = new Font("Tahoma", Font.BOLD, 11);
Font nameFont = new Font("Tahoma", Font.BOLD, 14);
GridBagConstraints gbc = new GridBagConstraints();
appName.setForeground(Color.WHITE);
appName.setFont(nameFont);
verNum.setForeground(new Color(0xFF9f9f9f));
verNum.setFont(verFont);
//add program name and version number
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
midPanel.add(appName, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.insets = new Insets(5, 5, 5, 5);
midPanel.add(verNum, gbc);
//add 3 example top panels to midpanel
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(1,2,1,2);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
midPanel.add(topPanel1, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
gbc.insets = new Insets(1,2,1,2);
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
midPanel.add(topPanel2, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(1,2,1,2);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
midPanel.add(topPanel3, gbc);
//add panel to push other panels to top
gbc.gridx = 0;
gbc.gridy = 5;
gbc.fill = GridBagConstraints.VERTICAL;
gbc.weighty = 1.0;
JPanel invisPanel = new JPanel();
invisPanel.setOpaque(false);
midPanel.add(invisPanel, gbc);
frame.getContentPane().add(midPanel);
frame.pack();
frame.setVisible(true);
}
//test it out
public static void main(String[] args) {
new TestGui();
}
//class for the top 3 panels
private class TopPanel extends JPanel {
private int maxLength;
private boolean cyclic;
public TopPanel() {
super(true);
initComponents();
setOpaque(false);
cyclic = true;
maxLength = 0;
}
#Override
public void paintComponent(Graphics g) {
if(isOpaque()) {
super.paintComponent(g);
return;
}
int width = getWidth();
int height = getHeight();
GradientPaint paint = null;
//Color top = new Color(50, 50, 50);
//Color btm = new Color(19, 19, 19);
Color top = new Color(0xFF222222);
Color btm = new Color(0xFF0c0c0c);
paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);
if(paint == null) {
throw new RuntimeException("Invalid direction specified in GamerTagPanel");
}
Graphics2D g2d = (Graphics2D) g;
Paint oldPaint = g2d.getPaint();
g2d.setPaint(paint);
g2d.fillRect(0, 0, width, height);
g2d.setPaint(oldPaint);
super.paintComponent(g);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
#Override
public void paintBorder(Graphics g) {
Dimension d = getSize();
g.setColor(new Color(0xFF484848));
g.drawRoundRect(1, 1, d.width-3, d.height-3, 10, 10);
g.setColor(Color.BLACK);
g.drawRoundRect(0, 0, d.width-1, d.height-1, 10, 10);
}
private void initComponents() {
GridBagConstraints gbc;
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
setBorder(BorderFactory.createLineBorder(new Color(204,204,204)));
setLayout(new GridBagLayout());
jLabel1.setFont(new Font("Tahoma", Font.BOLD, 11));
jLabel1.setForeground(new Color(255, 255, 255));
jLabel1.setText("Scanning...");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.insets = new Insets(5, 5, 5, 5);
add(jLabel1, gbc);
jLabel2.setFont(new java.awt.Font("Tahoma", Font.BOLD, 11));
jLabel2.setForeground(new Color(0xFF9f9f9f));
jLabel2.setText("C:\\Directory\\Folder\\SubFolder\\SpecificFolder\\File.file");
gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.anchor = GridBagConstraints.NORTHWEST;
gbc.weightx = 1.0;
gbc.insets = new Insets(5, 5, 5, 5);
add(jLabel2, gbc);
}
}
public class MidPanel extends JPanel {
private int maxLength;
private boolean cyclic;
public MidPanel() {
setLayout(new GridBagLayout());
setOpaque(false);
maxLength = 0;
cyclic = false;
}
// public void paintBorder(Graphics g) {
// g.setColor(Color.RED);
// Rectangle bounds = getBounds();
// g.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 10, 10);
// }
#Override
public void paintComponent(Graphics g) {
if(isOpaque()) {
super.paintComponent(g);
return;
}
int width = getWidth();
int height = getHeight();
GradientPaint paint = null;
Color top = new Color(0xFF282828);
Color btm = new Color(0xFF0e0e0e);
paint = new GradientPaint(width / 2, 0, top, width / 2, maxLength > 0 ? maxLength : height, btm, cyclic);
if(paint == null) {
throw new RuntimeException("Invalid direction specified in GamerTagPanel");
}
Graphics2D g2d = (Graphics2D) g;
Paint oldPaint = g2d.getPaint();
g2d.setPaint(paint);
g2d.fillRect(0, 0, width, height);
g2d.setPaint(oldPaint);
super.paintComponent(g);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 400);
}
}
}
Best way to implement this UI
I think the only correct approach is to implement new Look&Feel subset. Take a look on project seaglass:
What did I use
All these examples were prepared using Inkscape -- an Open Source vector graphics editor.
You can download my SVG source
At a pinch, this is the best I can come up with.
Notes:
As best I can tell, the line border color is 74,74,74. I have used a rounded border, but it has smaller radius than shown in the original example.
The top color is brightened by the offset defined in code (mostly so I could see a difference!) Reduce it to 0 for colors closer to what appear and to make the line more obvious.
The color of the text seems to be 249,249,249 (#F9F9F9) but I used #B9B9B9 for the top text and white for the rest.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
class GradientPanels {
/** An 'offset' to make gradients more obvious.
* Reduce to 0 for more subtle effect. */
static final int o = 50;
static final Color borderColor = new Color(74,74,74);
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
JPanel gui = new JPanel(new BorderLayout());
JPanel main = new GradientPanel(o + 40, 22);
main.setLayout(new BorderLayout(4, 4));
JLabel lTop = new JLabel("<html><body><h1 style='color: #B9B9B9'>Up<br>Here");
main.add(lTop, BorderLayout.PAGE_START);
main.setBorder(new EmptyBorder(4, 4, 4, 4));
JPanel center = new GradientPanel(o + 40, 17);
AbstractBorder b = new CompoundBorder(
new LineBorder(borderColor, 1, true),
new EmptyBorder(6, 6, 6, 6));
center.setBorder(b);
LayoutManager lm = new BoxLayout(center, BoxLayout.Y_AXIS);
center.setLayout(lm);
main.add(center, BorderLayout.CENTER);
addPanel(center, "Virus Shield", o);
center.add(Box.createRigidArea(new Dimension(10, 10)));
addPanel(center, "Auto Scan", o);
center.add(Box.createRigidArea(new Dimension(10, 10)));
addPanel(center, "My BitDefender", o);
center.add(Box.createRigidArea(new Dimension(10, 50)));
gui.add(main, BorderLayout.CENTER);
JOptionPane.showMessageDialog(null, gui);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
public static void addPanel(JPanel p, String text, int offset) {
JPanel t = new GradientPanel(offset + 28, 20);
AbstractBorder b = new CompoundBorder(
new LineBorder(borderColor, 1, true),
new EmptyBorder(6, 6, 6, 6));
t.setBorder(b);
t.add(new JLabel("<html><body><h2 style='color: #FFFFFF'>" + text));
p.add(t);
}
}
class GradientPanel extends JPanel {
Color top;
Color btm;
GradientPanel(int t, int b) {
top = new Color(t, t, t);
btm = new Color(b, b, b);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
GradientPaint gp = new GradientPaint(0f, 0f, top,
0f, (float) getHeight(), btm);
g2.setPaint(gp);
g2.fillRect(0, 0, getWidth(), getHeight());
}
}
Edit 1
The border in my fist example is still far from that seen in the desired screenshot. In this answer I create a custom border with more rounded corners (a 'speech bubble').
Unfortunately that example works better for entirely transparent components like JLabel. I've not had the time to look into adapting it for opaque components.
See Border with rounded corners & transparency for further discussion.

Categories

Resources