To create my first 2D game in Java, I thought of using the JFrame's getContentPane(), updating it with the new view every 50ms.
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// ...
frame.setVisible(true);
// ...
Container area = frame.getContentPane();
Graphics pen = area.getGraphics();
pen.clearRect(0, 0, area.getWidth(), area.getHeight()); // Remove previous drawing
pen.drawString("Text", 50, 50);
// ...
area.repaint();
But it doesn't work; the window doesn't change.
As kiheru already said, use paintComponent(Graphics g) for custom painting. Here is an example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class Example {
int i = 0;
public Example() {
JFrame frame = new JFrame();
frame.getContentPane().add(new DrawingPanel());
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.getContentPane().repaint();
}
};
Timer timer = new Timer(500, actionListener); //500 = Every 500 milliseconds
timer.start();
}
class DrawingPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g); // Removes previous graphics
Random r = new Random(); //Randomizer
//Random x- and y-coordinates
int x = r.nextInt(400);
int y = r.nextInt(400);
//Random rgb-values
int red = r.nextInt(255);
int green = r.nextInt(255);
int blue = r.nextInt(255);
//Random width and height
int width = r.nextInt(100);
int height = r.nextInt(100);
g.setColor(new Color(red, green, blue)); //Setting color of the graphics
g.fillRect(x, y, width, height); //Filling a rectangle
}
}
public static void main(String[] args) {
new Example();
}
}
research for double buffering or for fast image drawing using VolatileImage type for directly rending into graphics card. In your case if you use double buffering the code will be:
private static BufferedImage bufferedImage = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
private static Graphics2D gBuff = bufferedImage.createGraphics();
public static void main(String[] args)
{
JFrame frame = new JFrame()
{
#Override
public void paint(Graphics g)
{
g.drawImage(bufferedImage,0,0,this);
}
};
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
gBuff.setColor(Color.WHITE);
gBuff.fillRect(0, 0, frame.getWidth(), frame.getHeight()); // Remove previous drawing
gBuff.setColor(Color.BLACK);
gBuff.drawString("Text", 50, 50);
// ...
frame.setVisible(true);
// ...
}
Related
Here is a minimal code to see the bug:
import javax.swing.*;
import java.awt.*;
public class Main1 extends JFrame {
static Main1 main;
public Main1() {
super("app");
}
public static void main(String[] args) {
main = new Main1();
main.setBounds(300, 300, 800, 500);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Graphics g = main.getGraphics();
for(int i = 0; i < 100; i++){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, 800, 500);
}
}
}
If i use 100 in the "for" cycle, the frame appears not to be colored, but 200 loops is enough to color it.
I want to make an application where frames change rarely, but this feature ruins the quality of code because I have to make a number of dummy frames.
public static void main(String[] args) {
main = new Main1();
main.setBounds(300, 300, 800, 500);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
main.setVisible(true);
Graphics g = main.getGraphics();
for(int i = 0; i < 100; i++){
g.setColor(new Color(255, 0, 0));
g.fillRect(0, 0, 800, 500);
}
}
This is not how you do Swing graphics. Getting a Graphics object by calling .getGraphics() on a component gives you a short-lived unstable and sometimes null object. For instance, it takes some time for the created JFrame to render, and if you call getGraphics() and try to use it prior to rendering, the object may be null, and certainly won't wokr.
Instead paint within a JPanel's paintComponent method using the Graphics object given by the JVM as per the tutorials:
public class MainPanel extends JPanel {
public MainPanel {
setPreferredSize(new Dimension(800, 500)));
setBackground(new Color(255, 0, 0)); // if you just want to set background
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use g here do do your drawing
}
}
and then use it like so:
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
Tutorial: Lesson: Performing Custom Painting
And yes, if you want to drive a simple animation, use a Swing Timer to help drive it like so:
public class MainPanel extends JPanel {
private int x = 0;
private int y = 0;
public MainPanel {
setPreferredSize(new Dimension(800, 500)));
setBackground(new Color(255, 0, 0)); // if you just want to set background
// timer code:
int timerDelay = 15;
new Timer(timerDelay, ()-> {
x += 4;
y += 4;
repaint();
}).start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// use g here do do your drawing
g.setColor(Color.BLUE);
g.drawRect(x, y, 20, 20);
}
}
New to Java and very new to Java's GUI classes. I'm making a GUI to showcase a few games, but am having difficulties switching panels. I read about CardLayout but I'm having an issue implementing it because I can't get the JPanels that hold the different games' GUIs to send their events back to the class that uses the CardLayout. (This is probably where I'm going wrong -- I can't get my head around how to structure this properly.)
This is my main menu (called mainContainer):
This is the overall structure of the GUI driver:
public class CasinoDriverGUI {
//CardLayout is here in the main method Container contentPane.add(cardLayout)
public static void main(String[] args) throws IOException
//MainContainer is MenuScreen: GridBagLayout for nice button placement
static class MainContainer extends JPanel implements ActionListener{...}
static class CrapsContainer extends JPanel implements ActionListener{...}
static class PokerContainer extends JPanel implements ActionListener{...}
//Button with custom look
class CButton extends JButton
}//end CasinoDriverGUI
Here is the main method: It grabs an image from a website and then adds the menu screen (mainContainer) to the contentPane. The menu screen uses GridBagLayout, but it's where the button components are added. Because of this, I can't figure out how to get the CardLayout of the contentPane to listen to the menu screen's buttons. I tried using ContainerListener but that seemed to be a dead end.
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
As I have it so far, I have just tried using the "menu screen" (mainContainer) to instantiate all the games' panels and use an ActionListener on some buttons to simply call thisGame.setVisible(true). but this is forcing the window to be minimized and re-opened for any change to be detectable.Edit: fixed this.
Any advice on how I can restructure this code to be able to switch the panels from the menu screen to the different game's panels? (Code is below, but the craps and poker GUIs are incomplete.. just using the code as placeholders.
public class CasinoDriverGUI {
public static void main(String[] args) throws IOException {
// load the texture resource image
System.out.println("Please wait, Loading Texture : http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png");
MainContainer.textureImg = ImageIO.read(new URL("http://www.pngall.com/wp-content/uploads/2016/04/Casino-PNG-Pic.png"));
System.out.println("Loading finished. Starting the Casino!");
MainContainer.textureImg = MainContainer.textureImg.getSubimage(0, 0, 580, 309);
// Starting the Swing GUI in the EDT
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final CardLayout cardLayout = new CardLayout();
JFrame frame = new JFrame("Midnight Casino");
// frame about the size of background src image
frame.setPreferredSize(new Dimension(580, 329));
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardLayout);
MainContainer mainContainer = new MainContainer();
mainContainer.setPreferredSize( frame.getPreferredSize() );
contentPane.add(mainContainer, "mainContainer");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
static class MainContainer extends JPanel implements ActionListener
{
public BufferedImage gradientImage = null;
public static BufferedImage textureImg; // static for ease
public static boolean loadingFinished = false;
protected JButton pokerJBtn;
protected JButton crapsJBtn;
CrapsContainer crapsContainer;
PokerContainer pokerContainer;
public MainContainer() {
setBorder(new EmptyBorder(50, 50, 50, 50)); // setting the insets
setLayout(new GridBagLayout());
// working with GridBagConstraints
GridBagConstraints labCnst = new GridBagConstraints();
GridBagConstraints txtCnst = new GridBagConstraints();
labCnst.ipady = txtCnst.ipady = 10;
labCnst.fill = GridBagConstraints.HORIZONTAL;
labCnst.gridwidth = 1;
labCnst.weightx = 0.3;
labCnst.gridx = 2;
labCnst.gridy = 2;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
pokerJBtn = new CButton("5-Card Poker");
add(pokerJBtn, labCnst);
labCnst.gridx = 2;
labCnst.gridy = 20;
labCnst.ipady = 13;
labCnst.insets = new Insets(0, 0, 0, 150);
crapsJBtn = new CButton("Craps");
add(crapsJBtn, labCnst);
crapsContainer = new CrapsContainer();
pokerContainer = new PokerContainer();
add(crapsContainer);
add(pokerContainer);
crapsContainer.setVisible(false);
pokerContainer.setVisible(false);
//Add Action Listeners
crapsJBtn.addActionListener(this);
pokerJBtn.addActionListener(this);
}
public void changeCompFont(JComponent comp)
{
comp.setForeground(Color.WHITE);
comp.setFont(getFont().deriveFont(Font.BOLD, 13));
}
// To PAINT THE TEXTURE ABOVE THE COMPONENTS
#Override
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D)g.create(); // cloning
Rectangle2D txRect = new Rectangle2D.Double(0, 0, textureImg.getWidth(), textureImg.getHeight());
TexturePaint txPaint = new TexturePaint(textureImg, txRect);
g2d.setPaint(txPaint);
//make the texture transparent
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.233f));
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();// disposing the graphics object
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if(gradientImage==null || gradientImage.getHeight() != getHeight() )
{
gradientImage = createGradientImg();
}
g2d.drawImage(gradientImage, 0, 0, getWidth(), getHeight(), this);
g2d.dispose();
}
public BufferedImage createGradientImg()
{
BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
// background gradient paint, linear gradient paint for the background
// Gradient paint rendering could be made more optimized
LinearGradientPaint lgrPaint = new LinearGradientPaint(0.0f, 0.0f, getWidth(), getHeight(),
new float[] { 0.0f, 0.5f, 0.6f, 1.0f },
new Color[] { new Color(0x0530E),// new Color[] { new Color(0x002AFF),
new Color(0x0A31B),
new Color(0x0A31B),
new Color(0x0530E ) });
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setPaint(lgrPaint);
//g2d.shear(0.2, 0);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.dispose();
g2d.drawImage(textureImg, 0, 0, getWidth(), getHeight(), null);
return image;
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == pokerJBtn)
{
pokerContainer.setVisible(true);
}
else if (e.getSource() == crapsJBtn){
this.setVisible(false);
invalidate();
crapsContainer.setVisible(true);
revalidate();
repaint();
}
}
}
//Either Flow, Border, or GridBag Layout
static class CrapsContainer extends JPanel implements ActionListener
{...}
//Either Flow, Border, or GridBag Layout
static class PokerContainer extends JPanel implements ActionListener
{...}
//Custom Button to change aesthetic look
class CButton extends JButton
{...}
}
This is my problem :
I have one JPanel and i paint in this panel one rectangle ex. 100x100.
In another JPanel I wouldlike show/paint fragments on first JPanel ex. 50x50, but if I change first JPanel, another JPanel change too (dont copy graphics or Panel)
What I can do this?
First Panel Second Panel
Public class Okienko extends JFrame {
Panel p = new Panel();
public Okienko(){
//setLayout(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(p);
pack();
setVisible(true);
}
private class Panel extends JPanel{
public Panel(){
setPreferredSize(new Dimension(300,400));
setBackground(Color.red);
setVisible(true);
}
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
super.paint(g2);
g2.setColor(Color.blue);
g2.fill(new Rectangle2D.Float(100,100,100,100));
g2.setColor(Color.green);
g2.fill(new Rectangle2D.Float(50,50,50,50));
}
}
private class Panel2 extends Panel{
#Override
public void paint(Graphics g) {
//I would like to show/paint only fragment painted Panel, ex. 50x50 (only show one rectangle)
}
}
public static void main(String[] args) {
Okienko o = new Okienko();
}
}
So this is what you need to do.
You need to save the first JPanel's Graphics context to a BufferedImage. Here is a helper method, I used in the example program below
BufferedImage bi;
....
private void setImage(JPanel panel) {
Dimension d = panel.getPreferredSize();
int w = (int)d.getWidth();
int h =(int)d.getHeight();
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
panel.paint(g);
g.dispose();
}
This saves the entire JPanel to a BufferedImage.
Use that BufferedImage to paint on the second JPanel. Use whatever coordinates you want. Use this method from Graphics class
public abstract boolean drawImage(Image img,
int dx1,
int dy1,
int dx2,
int dy2,
int sx1,
int sy1,
int sx2,
int sy2,
ImageObserver observer)
img - the specified image to be drawn. This method does nothing if img is null.
dx1 - the x coordinate of the first corner of the destination rectangle.
dy1 - the y coordinate of the first corner of the destination rectangle.
dx2 - the x coordinate of the second corner of the destination rectangle.
dy2 - the y coordinate of the second corner of the destination rectangle.
sx1 - the x coordinate of the first corner of the source rectangle.
sy1 - the y coordinate of the first corner of the source rectangle.
sx2 - the x coordinate of the second corner of the source rectangle.
sy2 - the y coordinate of the second corner of the source rectangle.
observer - object to be notified as more of the image is scaled and converted.
g.drawImage(bi, 0, 0, 200, 200, 0, 0, 50, 50, this);
Here's the result
Here's the full code
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
public class TestTwoPanels {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JPanel panel = new JPanel();
PanelTwo panelTwo = new PanelTwo();
PanelOne panelOne = new PanelOne(panelTwo);
JSplitPane split = new JSplitPane(
JSplitPane.HORIZONTAL_SPLIT, panelOne, panelTwo);
panel.add(split);
JFrame frame = new JFrame("Test Graphics");
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
private static class PanelOne extends JPanel {
Dimension size;
BufferedImage image;
PanelTwo panelTwo;
public PanelOne(PanelTwo panelTwo) {
this.panelTwo = panelTwo;
try {
URL url = new URL("http://swoo.co.uk/content/images/icons/stackoverflow.png");
image = ImageIO.read(url);
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
panelTwo.setImage(PanelOne.this);
panelTwo.repaint();
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawImage(image, 0, 0, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(250, 250);
}
}
private static class PanelTwo extends JPanel {
BufferedImage bi;
public PanelTwo() {
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
}
public void setImage(BufferedImage image) {
this.bi = image;
}
private void setImage(JPanel panel) {
Dimension d = panel.getPreferredSize();
int w = (int)d.getWidth();
int h =(int)d.getHeight();
System.out.println(d);
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D g = bi.createGraphics();
panel.paint(g);
g.dispose();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bi, 25, 25, 225, 225, 50, 50, 175, 175, this);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(250, 250);
}
}
}
private void setImage(JPanel panel) {
Dimension d = panel.getPreferredSize();
int w = (int)d.getWidth();
int h =(int)d.getHeight();
System.out.println(d);
bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
This code is clearify for me.
Graphics2D g = bi.createGraphics();
You create blank BufferedImage and init to Graphics2D?
panel.paint(g);
You paint graphics context on panel and copy to bi?
g.dispose();
You release g.
}
I'm testing a program that uses a JSlider to adjust the width of a circle, and the value of the slider is working, but its not actually changing the 'width' variable. Please help!!! Here is what I have so far:
public class SliderTest extends JFrame{
private static DrawShape circle = new DrawShape();
JSlider slider;
JLabel label;
public SliderTest() {
setLayout(new FlowLayout());
slider = new JSlider(JSlider.HORIZONTAL, 150, 450, 300);//orientation, min val, max value, starting val
slider.setMajorTickSpacing(50);//every 5 integers will be a new tick position
slider.setPaintTicks(true);
add(slider);
label = new JLabel("Current value 300");
add(label);
event e = new event();
slider.addChangeListener(e);;
}//end cons
public class event implements ChangeListener{
public void stateChanged(ChangeEvent e) {
JSlider slider = (JSlider)e.getSource();
int value = slider.getValue();
label.setText("Current Value " + value);
circle.setWidth(value);
repaint();
}//end stateChanged
}//end class event
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setTitle("Circle");
frame.add(circle);
frame.setSize(500,400);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
JFrame frame1 = new SliderTest ();
frame1.setTitle("Toolbar");
frame1.setSize(300,200);
frame1.setLocation(200,100);
frame1.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame1.setVisible(true);
}
}
The other class:
public class DrawShape extends JPanel{
private float width = 300;
private Ellipse2D circle = new Ellipse2D.Float(100, 20, 300, 300);
public DrawShape() {
}
public DrawShape(float width) {
circle.setFrame(100, 20, width, 300);
}
public void setWidth(int w) {
this.width = w;
circle.setFrame(100, 20, w, 300);
revalidate();
}
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
size.width = circle.getBounds().width;
return size;
}
public void paintComponent (Graphics g) {
super.paintComponents(g);
Graphics2D graphics = (Graphics2D)g;
graphics.setColor(Color.black);
graphics.fill(circle);
}//end paintComponent
}//end class
Two (major) issues popup.
Firstly, in your event handler, you're repainting the slider frame, which isn't going to help, so it your setWidth you should add a repaint request, for example.
public void setWidth(int w) {
System.out.println("setWidth " + w);
this.width = w;
circle.setFrame(100, 20, w, 300);
revalidate();
repaint();
}
Secondly, you all calling super.paintComponents (note the s at the end) instead of super.paintComponent, for example...
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.black);
g2d.fill(circle);
}//end paintComponent
This will cause you a significant amount of grieve with strange paint artifacts...
Right now I am making my jinternal frames transparent using this code:
double rgbConversionBackpack = Double.parseDouble(MyClient.configFile.getProperty("BACKPACK_FRAME_ALPHA"));
double tmp = (rgbConversionBackpack / 100.0) * 255.0;
this.getContentPane().setBackground(new Color(140, 0, 0, (int)tmp));
this.setOpaque(false);
I have code on the sliders to set the alpha which all works perfectly and saves it to a properties file, yada, yada, yada. The question is how do I make the entire JInternal Frame transparent.
Right now I have only be able to set the content pane, and any other panels (etc) that are in the jinternal frames transparent, but I want to make the entire JinternalFrame(borders and all) transparent.
Screenshot below shows how on the backpack the red tinted are is partially transparent and looks decent, but still want the border to be transparent also.
Is there a way to override the draw super method for each of my classes the extend JInternalFrame to have it draw semi transparent(depending on value obviously)?
You could do this by changing the AlphaComposite that the JInternalFrame's paint method uses. You have to be careful though to repaint the containing top level window at the location of the transparent component lest you have funny side effects. For example:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class TransparentInternalFrame extends JDesktopPane {
private static final Color COLOR_1 = Color.red;
private static final Color COLOR_2 = Color.blue;
private static final float PT_2 = 30f;
private static final int PREF_W = 800;
private static final int PREF_H = 500;
public TransparentInternalFrame() {
add(new MyInternalFrame("Foo", 50, 50, 300, 300, 0.2f));
add(new MyInternalFrame("Foo", 400, 100, 300, 300, 0.4f));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setPaint(new GradientPaint(0, 0, COLOR_1, PT_2, PT_2, COLOR_2, true));
g2.fillRect(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
TransparentInternalFrame mainPanel = new TransparentInternalFrame();
JFrame frame = new JFrame("TransparentInternalFrame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class MyInternalFrame extends JInternalFrame {
private AlphaComposite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
public MyInternalFrame(String title, int x, int y, int w, int h, final float alpha) {
super(title);
setClosable(true);
setBounds(x, y, w, h);
setVisible(true);
int sliderValue = (int) (alpha * 100);
comp = comp.derive(alpha);
final JSlider slider = new JSlider(0, 100, sliderValue);
slider.setMajorTickSpacing(20);
slider.setMinorTickSpacing(5);
slider.setPaintLabels(true);
slider.setPaintTicks(true);
slider.setBorder(BorderFactory.createTitledBorder("Alpha Value"));
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent cEvt) {
float alpha = (float) slider.getValue() / 100f;
setAlpha(alpha);
MyInternalFrame.this.repaint();
Window win = SwingUtilities.getWindowAncestor(MyInternalFrame.this);
win.repaint();
}
});
add(new JLabel("My Label", SwingConstants.CENTER));
add(slider, BorderLayout.SOUTH);
}
#Override
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(comp);
super.paint(g);
}
public void setAlpha(float alpha) {
comp = comp.derive(alpha);
}
}
But note that this program is not fully fixed. You'll still see pixel errors if you drag one JInternalFrame over another. I still need to work the bugs out...