custom round skin gui - java

In looking for a starting place to how to create a round interface. I have tried looking into the docs and tried looking into other plugins for Eclipse. I'm just starting to build gui's with java and everything I find is either asking for me to be a part of a company to use their product or want a few hundred dollars.
I'm just a humble coder trying my hand at gui's and a personal project I'm working on wants a round gui skin.

There are, at least, two ways you might achieve this...
You could...
Use JFrame#setShape to alter the shape of the main window, for example...
JFrame frame = new JFrame("Testing");
frame.getContentPane().setBackground(Color.RED);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(new JLabel("Boo!"));
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setUndecorated(true);
frame.setShape(new Ellipse2D.Double(0, 0, 200, 200));
frame.setVisible(true);
This is simple, but frankly, looks crap. There's no way to implement soft clipping to smooth out the edges with this technique...
You could...
Create a transparent window and "fake" the shape...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CircleUI {
public static void main(String[] args) {
new CircleUI();
}
public CircleUI() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new CirclePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class CirclePane extends JPanel {
public CirclePane() {
setOpaque(false);
setLayout(new GridBagLayout());
add(new JLabel("Boo!"));
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setColor(Color.RED);
g2d.fill(new Ellipse2D.Double(0, 0, getWidth() - 1, getHeight() - 1));
g2d.dispose();
}
}
}
Which, arguably, produces a nicer looking result, but will allow you to display components beyond the shape (allow them to overflow), so you need to be able to manage the content to ensure that this doesn't happen...
You could...
Do both...
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// This is the secret here...
JPanel content = new JPanel(new BorderLayout());
content.setOpaque(false);
content.setBorder(new EmptyBorder(1, 1, 1, 1));
content.add(new CirclePane());
frame.setContentPane(content);
frame.pack();
int width = frame.getWidth();
int height = frame.getHeight();
frame.setShape(new Ellipse2D.Double(0, 0, width, height));
frame.setLocationRelativeTo(null);
frame.setVisible(true);
What this does is uses the setShape method from the first example, with the soft clipping from the second example and combines them. This is done by using another JPanel to act as the container for our "fake" shape panel and supplying a very small (1 pixel) empty border. This pushes the size of the frame out from the edge of our soft clipping panel, but means that any components that overflow it, will be clipped...

Call the setOpacity method on your JFrame. More details here:
http://java-demos.blogspot.com/2012/09/how-to-create-shaped-jframes-in-java.html
Other options for Java 6 and Java 7: click here for examples in another solution
JFrame frame = new JFrame();
frame.setUndecorated(true);
AWTUtilities.setWindowShape(frame, new Ellipse2D.Double(0, 0, 100, 100));
Not to be rude, but you really could have found this if you spent 5 minutes Googling or searching on Stack Overflow...
If you really want to learn Java GUI's, you should spend some time studying AWT, Swing, or JavaFX, the core Java libraries for doing GUI work, and basic objects like JFrame and JWindow, and creating menus, buttons, ActionListeners and layouts.

Related

Why my rectangle shape is so small in java graphics 2d

So I am new in java graphics and I am creating a program that will show a rectangle. But when I run my program it only show like a small box and not the rectangle. I don't really know why it is happening.
Here is my code:
import javax.swing.*;
public class GraphicsEditor{
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
Rectangle rectangle = new Rectangle();
frame.setSize(1280, 720);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.add(panel);
panel.add(rectangle);
}
}
This is my rectangle class:
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Rectangle extends JPanel implements Shape {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.fillRect(0, 0, 200, 130);
}
}
This is my shape interface:
import java.awt.*;
public interface Shape {
void paintComponent(Graphics g);
}
Here, try this
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
public class GraphicsEditor {
public static void main(String[] args) {
JFrame frame = new JFrame();
Rectangle rectangle = new Rectangle();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(rectangle);
frame.pack();
// center frame on screen
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class Rectangle extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.fillRect(0, 0, 200, 130);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 500);
}
}
A couple of things.
you don't need the interface.
unlike components, just painting a picture doesn't affect the layout manager, so the panel will be reduced to it's default size with out regard to any painting.
so you need to override getPreferredSize() in your JPanel.
As the comments said, you should set the preferred size of both your panel and rectangle to your desired size, and then pack the frame, like:
panel.setPreferredSize(new Dimension(500,500));
rectangle.setPreferredSize(new Dimension(500,500));
frame.pack();
Otherwise your LayoutManager (when not specified it defaults to FlowLayout) will handle your rectangle the way it wants. So another way would be learning about Layout Managers, and using your desired one.
As a side note, I would like to make some suggestions to your code. Remember, Swing is not thread safe, so place your code inside an invokeLater() call, such as:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
Rectangle rectangle = new Rectangle();
frame.setSize(1280, 720);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500,500));
rectangle.setPreferredSize(new Dimension(500,500));
frame.add(panel);
panel.add(rectangle);
frame.pack();
frame.setVisible(true);
}
});
Also, calling frame.setVisible(true) should be called after adding your components.

Centering game pieces which aren't maintaing size when resizing

I have a board game (think Monopoly) where multiple game pieces can be located on a single tile. I got 4 circles drawn on a green background, but the circles are not centered and when I resize them the circles move all over the place instead of staying with the tile.
CirclePanel:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class CirclePanel extends JPanel {
public static final Dimension SIZE = new Dimension(35, 35);
public CirclePanel() {
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.RED);
g.fillOval(0, 0, 35, 35);
System.out.println(getSize());
}
#Override
public Dimension getPreferredSize() {
return SIZE;
}
}
GraphicsTile:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
#SuppressWarnings("serial")
public class GraphicsTile extends JPanel {
public static final Dimension SIZE = new Dimension(140, 140);
public static final GridLayout MGR = new GridLayout(2, 2);
public GraphicsTile() {
super();
setLayout(MGR);
add(new CirclePanel());
add(new CirclePanel());
add(new CirclePanel());
add(new CirclePanel());
}
#Override
public Dimension getPreferredSize() {
return SIZE;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillRect(0, 0, 140, 140);
}
}
GraphicsRunner:
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
public class GraphicsRunner {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setLayout(new GridLayout(4, 0, 5, 5));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1280, 720);
frame.setPreferredSize(new Dimension(140, 140));
frame.add(new GraphicsTile());
frame.add(new GraphicsTile());
frame.setVisible(true);
}
}
Once again, don't play with the size. All Swing components should determine their own preferred size. This includes panels and frame.
The panel will determine its size based on the component added to the panel.
The frame will determine its size based on the panels added to the frame. After the panels are added you use the pack() method.
Then all the components will be displayed at their preferred size. You could then just make the frame a fixed size by using:
frame.setResizable( false );
However, if you don't do the above then you need to determine what happens if the frame is resized. You then need to be more careful about the layout managers you use.
For a GridLayout all the components are resized to fill all the space available. This is easily verified by changing the painting code in your GraphicsTile` to:
//g.fillRect(0, 0, 140, 140);
g.fillRect(0, 0, getWidth(), getHeight());
This is the better painting technique. You should NOT be hardcoding values. Use properties of the component to specify the parameters when appropriate.
If you do this you will see the tiles expand to fill the area and the CirclePanel is at the beginning of the GraphicsTile (again because you hardcoded the location).
To prevent the GraphicsTile from expanding in size you will need to wrap it in another panel that respects the preferred size of the components added to it.
An easy way to do this is to use a GridBagLayout with the default GridBagConstraints. Now any component added to it will be centered in the space available.
So the restructuring of you main() method would look like:
JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());
JPanel tilePanel = new JPanel( new GridLayout(0, 1, 5, 5) );
tilePanel.add(new GraphicsTile());
tilePanel.add(new GraphicsTile());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tilePanel, new GridBagConstraints());
frame.pack();
frame.setVisible(true);
It is because GridLayout automatically expand the content using the all the available space.
You could avoid this by wrapping your GraphicsTiles with another JPanel (which by default uses FlowLayout). This way the GridLayout would be forced to remain inside the wrapper.
For example in GraphicsRunner you could use panel as a wrapper:
JPanel panel = new JPanel();
panel.add(new GraphicsTile());
frame.add(panel);
panel = new JPanel();
panel.add(new GraphicsTile());
frame.add(panel);
But you might want to investigate if other layouts (or even not using layouts at all) suits your needs better.
Here a similar question that could help: How to set the component size with GridLayout? Is there a better way?

Paint not showing up

I am using a JFrame and a pane and trying to draw a simple square.
My painting is not showing up. I made I set the color to black so it should be visible.
Code:
package W2;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import javax.swing.*;
public class W2 {
JFrame frame = new JFrame("W2");
public W2(){
Container pane = new Container();
frame.setContentPane(pane);
frame.setSize(750,500);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setVisible(true);
}
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(50, 50, 50, 50);
}
public static void main(String args[]){
new W2();
}
}
The paint method won't be called because it's not part of a object that can be painted.
See Performing Custom Painting for details about how painting is done in Swing
For example...
frame.setContentPane(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(50, 50, 50, 50);
}
});

How to add gradient color to Jbuttons placed in jtoolbar

I am using netbeans platform module to develop this desktop application. I am using drag and drop facility in netbeans in the developement.
I needed to create a toolbar which is having few buttons..I need to create a gradient color for these buttons.
I dragged and dropped JToolBar, over it I dragged and placed JButton objects.
In the properties of the button I have selected a color for which I want a shaded color. In the custom code I have modified.
jbutton = new javax.swing.Jbutton();
as below
jbutton = new javax.swing.JButton(){
#Override
protected void paintComponent(Graphics grphcs) {
Graphics2D g2d = (Graphics2D) grphcs;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0,
getBackground().brighter().brighter().brighter(), 0, getHeight(),
getBackground().darker());
g2d.setPaint(gp);
g2d.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(grphcs);
}};
When I used the above code for a JPanel in my project it worked but it is not showing any effect when I used it for a button.
How to get a gradient color for a button placed in a toolbar?
The button has a contentAreaFilled attribute which determines if the look and feel should paint the content area of the button. When you call super.paintComponent, the look and feel delegate will paint over what you have done.
You can set this property to false and it should then work.
For example...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.RenderingHints;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GradientButtons {
public static void main(String[] args) {
new GradientButtons();
}
public GradientButtons() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(new RoundButton("Click me"));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class RoundButton extends JButton {
public RoundButton(String text) {
super(text);
setBorderPainted(false);
setContentAreaFilled(false);
setFocusPainted(false);
setOpaque(false);
}
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
int radius = Math.max(size.width, size.height);
size.width = radius;
size.height = radius;
return size;
}
#Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0,
Color.RED, 0, getHeight(),
Color.YELLOW);
g2d.setPaint(gp);
g2d.fillOval(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
}
}
You may want to check the ButtonModel's armed and/or pressed state so you can also change the way that the button is painted when clicked, as a suggestion...

Creating a JFrame you can click through

I'm trying to create a jframe that the user can click through. I'm not looking for opacity but transparency.
I need a solution that works on all OS and not just Windows because I can't use
WindowUtils.setWindowTransparent(frame, true);
WindowUtils.setWindowAlpha(frame, 0.6f);
or
AWTUtilities.setWindowOpaque(this, false);
AWTUtilities.setWindowOpacity(this, 0.8f);
Can I accomplish this with java alone? It's ok if there is a library that I must use.
EDIT: I have my jframe undecorated and here is the code for it.
frame = new JDialog();
frame.setUndecorated(true);
frame.setVisible(true);
frame.setOpacity(Shared.opacity);
frame.setLocation(0, 0);
frame.setSize(Shared.screenWidth, Shared.screenHeight);
When I say the user can click through what I mean is that if my frame is on top but they have a window under mine, clicking on mine would bring the one under on top.
A completely transparent window can be achieved in Java 7 by using a completely transparent background color, for example...
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
The problem you will have is, that anywhere there is any kind of solid pixel (even if it is transparent), it will stop the mouse events from going beyond the window...
This means that every child component you add to the frame (that you want to be able to click through) will need to be transparent as well.
I use a similar technique for some of my utility programs and include a MouseListener on the main opaque component to make the window more visible so I can drag it if I want to it, but that's stuff for another question ;)
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ClickThroughWindow {
public static void main(String[] args) {
new ClickThroughWindow();
}
public ClickThroughWindow() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setUndecorated(true);
frame.setBackground(new Color(0, 0, 0, 0));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.setAlwaysOnTop(true);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setOpaque(false);
setLayout(new GridBagLayout());
add(new JLabel("Hello"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(getBackground());
// g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
// g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.dispose();
}
}
}
You can find more details at How to Create Translucent and Shaped Windows, in particular How to Implement Per-Pixel Translucency

Categories