Layered Java JPanels - java

I have overlayed JPanels, background has an image that prevents foreground from painting on applet's load.
setOpaque(false) works fine (repaints both panels twenty times thou[?]), but I need it opaque to have BG color, opaque background causes repainting itself 3 times, and that wipes out the top panel:
public class LayeredPanelsTest extends JApplet
{
private Image _image;
#Override
public void init()
{
_image = getImage( getDocumentBase(), "./images/flag.GIF" );
setSize( 450, 450 );
setLayout( new OverlayLayout( getContentPane() ) );
final BottomPanel background = new BottomPanel();
background.setBounds( 10, 10, 400, 400 );
final TopPanel foreGround = new TopPanel();
foreGround.setBounds( 10, 10, 400, 400 );
add( foreGround );
add( background );
}
public class BottomPanel extends JPanel
{
public BottomPanel()
{
setBackground(Color.CYAN);
setLayout( new FlowLayout() );
setOpaque( true );//with false foreground is painted just fine, but they get repainted like 20 times.
}
#Override
public void paintComponent( final Graphics g )
{
super.paintComponent( g );
g.drawImage( _image, 10, 10, this );
System.out.println( "Bottom" );
}
}
public class TopPanel extends JPanel
{
int _mouseX = 10;
public TopPanel()
{
setLayout( new FlowLayout() );
setOpaque( false );
addMouseListener( new MouseAdapter()
{
#Override
public void mousePressed( final MouseEvent evt ) {
_mouseX = evt.getX();
repaint();
}
});
}
#Override
public void paintComponent( final Graphics g )
{
super.paintComponent( g );
g.drawLine( _mouseX, 0, _mouseX, 80);
System.out.println( "Top" );
}
}
}

Related

Translucent internal frames - is that possible in java?

Is there any way I can make translucent JInternalFrame uing swing?
All I found is option for JFrame(not internal one) which is not what I need.
You should be able to use a JLayer. You could start with the layout painting a fully opaque layer the same color as the background of the desktop pane. Then you change the alpha value to approach cell until you have full transparency.
See the section from the Swing tutorial on How to Decorate Components With the JLayer Class for more information and an example of painting with transparency.
If you only care about the background you can use the Alpha Container when using components with transparency:
JPanel content = new JPanel( new BorderLayout() );
content.setBackground( new Color(0, 0, 0, 0) );
internalFrame.setContentPane(new AlphaContainer(content));
internalFrame.setOpaque(false);
You can then change the alpha value of the content panel to your desired transparency.
Edit:
Here is may attempt at animating the transparency of an internal frame and its components:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class TransparentInternalFrame extends JInternalFrame implements ActionListener
{
static int openFrameCount = 0;
static final int xOffset = 30, yOffset = 30;
private float alpha = 0.0f;
private Timer timer = new Timer(500, this);
public TransparentInternalFrame()
{
super("Document #" + (++openFrameCount), true, true, true, true);
setSize(300,300);
setLocation(xOffset * openFrameCount, yOffset * openFrameCount);
setVisible( true );
}
#Override
public void paint(Graphics g)
{
g.setColor( getDesktopPane().getBackground() );
g.fillRect(0, 0, getWidth(), getHeight());
Graphics2D g2 = (Graphics2D)g.create();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
super.paint(g2);
}
public void showFrame()
{
timer.start();
}
public void hideFrame()
{
alpha = 0.0f;
repaint();
}
#Override
public void actionPerformed(ActionEvent e)
{
alpha += .05f;
alpha = Math.min(1.0f, alpha);
System.out.println(alpha);
if (alpha >= 1.0f)
timer.stop();
repaint();
}
private static void createAndShowGUI()
{
JDesktopPane desktop = new JDesktopPane();
desktop.setBackground( Color.YELLOW );
TransparentInternalFrame tif = new TransparentInternalFrame();
desktop.add( tif );
tif.add(new JButton("Hello"), BorderLayout.PAGE_START);
JButton show = new JButton( "Show Internal Frame" );
show.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
tif.showFrame();
}
});
JButton hide = new JButton( "Hide Internal Frame" );
hide.addActionListener( new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
tif.hideFrame();
}
});
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(show, BorderLayout.PAGE_START);
frame.add(desktop);
frame.add(hide, BorderLayout.PAGE_END);
frame.setLocationByPlatform( true );
frame.setSize(500, 500);
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}

Clear previously drawn string over an image

I am wondering how I can clear a previously drawn string before drawing a new one over an image, if I do not clear the strings overlap. I have tried graphics#drawRect and overriding paintComponent(Graphics), still no eval.
Here is my code:
paintComponent(Graphics)
public class SplashScreen extends JLabel
{
private static final long serialVersionUID = 5515310205953670741L;
private static final String ROOT = "./assets/img/";
private static final SplashScreen INSTANCE = new SplashScreen( get( new File( ROOT, "splash.png" ) ), get( new File( ROOT, "splash-bar.png" ) ) );
private final BufferedImage background;
private final BufferedImage foreground;
private final JLabel label;
private SplashScreen( BufferedImage background, BufferedImage foreground )
{
this.background = background;
this.foreground = foreground;
label = new JLabel( new ImageIcon( background ) );
JWindow window = new JWindow();
window.setSize( background.getWidth(), background.getHeight() );
window.getContentPane().add( label );
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
window.setLocation( dimension.width / 2 - window.getSize().width / 2, dimension.height / 2 - window.getSize().height / 2 );
window.setVisible( true );
}
public void updateStatus( String status )
{
Graphics g = background.getGraphics();
g.drawString( status, 304, 301 );
g.dispose();
label.repaint();
}
public void updateBar( int width )
{
Graphics g = background.getGraphics();
g.drawImage( foreground, 73, 309, width, foreground.getHeight(), null );
g.dispose();
label.repaint();
}
private static BufferedImage get( File file )
{
try {
return ImageIO.read( file );
} catch( IOException e ) {
throw new RuntimeException( e.getMessage() );
}
}
public static SplashScreen getInstance()
{
return INSTANCE;
}
}
Any help is greatly appreciated. :-)
Thanks.
You don't need to do custom painting.
Here are a couple of different ways to paint text on a label with an Icon:
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class LabelImageText extends JPanel
{
public LabelImageText()
{
JLabel label1 = new JLabel( new ColorIcon(Color.ORANGE, 100, 100) );
label1.setText( "Easy Way" );
label1.setHorizontalTextPosition(JLabel.CENTER);
label1.setVerticalTextPosition(JLabel.CENTER);
add( label1 );
//
JLabel label2 = new JLabel( new ColorIcon(Color.YELLOW, 200, 150) );
label2.setLayout( new BoxLayout(label2, BoxLayout.Y_AXIS) );
add( label2 );
JLabel text = new JLabel( "More Control" );
text.setAlignmentX(JLabel.CENTER_ALIGNMENT);
label2.add( Box.createVerticalGlue() );
label2.add( text );
label2.add( Box.createVerticalStrut(10) );
//
JLabel label3 = new JLabel( new ColorIcon(Color.GREEN, 200, 150) );
add( label3 );
JLabel text3 = new JLabel();
text3.setText("<html><center>Text<br>over<br>Image<center></html>");
text3.setLocation(20, 20);
text3.setSize(text3.getPreferredSize());
label3.add( text3 );
//
JLabel label4 = new JLabel( new ColorIcon(Color.CYAN, 200, 150) );
add( label4 );
JTextPane textPane = new JTextPane();
textPane.setText("Add some text that will wrap at your preferred width");
textPane.setEditable( false );
textPane.setOpaque(false);
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
StyledDocument doc = textPane.getStyledDocument();
doc.setParagraphAttributes(0, doc.getLength(), center, false);
textPane.setBounds(20, 20, 75, 100);
label4.add( textPane );
}
public static class ColorIcon implements Icon
{
private Color color;
private int width;
private int height;
public ColorIcon(Color color, int width, int height)
{
this.color = color;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
g.setColor(color);
g.fillRect(x, y, width, height);
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("LabelImageText");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new LabelImageText() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Then to change the text you just change the text in the component you are using to display the text.
If none of these help then the way to do custom painting is to override the paintCompnent() method of the JLabel. You should not be painting the text directly on the BufferedImage.
Basically, you can't.
What you should try doing is keep a reference to the original background image and when you need to change the text, copy it to a temp image and draw the String there, replacing it (the temp copy) as the label's icon...
A better solution might be to paint the text directly as part of the labels paint process by overriding the paintComponent method

Adding elements to JPanel

Why does "drawing" not appear here? I am adding it to a different JPanel then adding everything to another JPanel and returning that. However, all i see is the TrackBall
public class Draw extends JFrame
{
private JSplitPane itemPane;
private Point position = null;
public Draw()
{
// Set the layout to a grid
setLayout ( new BorderLayout (5,5));
// Set the properties of the window
setTitle ("Emulator");
setSize ( 900, 700);
setDefaultCloseOperation (EXIT_ON_CLOSE);
setBackground ( new Color (15, 255, 10));
// Add the components
addComponents ();
}
public static void startWindowsGui()
{
// We are in the static main, set the form to invoke later
SwingUtilities.invokeLater ( new Runnable()
{
public void run()
{
// Create a new instance of server and set it to visible
Draw gui = new Draw();
gui.setVisible (true);
}
} );
}
private void addComponents()
{
// Create the main and an itemPane
JSplitPane mainPane = new JSplitPane ( JSplitPane.HORIZONTAL_SPLIT );
setItemPane(new JSplitPane ( JSplitPane.VERTICAL_SPLIT ));
mainPane.add ( createPane ( ), JSplitPane.LEFT );
mainPane.add ( getItemPane(), JSplitPane.RIGHT );
mainPane.setOneTouchExpandable ( true );
getItemPane().setOpaque(true);
getItemPane().setBackground(new Color(0xffffffc0));
JPanel p = new JPanel();
this.getItemPane().add(p);
add ( mainPane, BorderLayout.CENTER );
}
public static void main(final String[] args)
{
Runnable gui = new Runnable()
{
#Override
public void run()
{
new Draw().setVisible(true);
}
};
SwingUtilities.invokeLater(gui);
}
private class Drawing extends JPanel {
private static final long serialVersionUID = 1L;
private final Point position;
public Drawing(Point position) {
this.position = position;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.RED);
g2.fillOval(160 + position.x, 160 - position.y, 15, 15);
}
}
private JPanel createPane()
{
// Create the feedPanel
JPanel panel = new JPanel ( );
JPanel panel2 = new JPanel ( );
JPanel panel3 = new JPanel ( );
this.position = new Point();
TrackBall myJoystick = new TrackBall(150, position, 100);
panel.add(myJoystick, BorderLayout.PAGE_END);
Drawing drawing = new Drawing(position);
panel2.add(drawing, BorderLayout.PAGE_START);
panel3.add(panel2);
panel3.add(panel);
return panel3;
}
public JSplitPane getItemPane() {return itemPane;}
public void setItemPane(JSplitPane itemPane) {this.itemPane = itemPane;}
}
3 issues
panel2 requires BorderLayout rather than the default FlowLayout for the BorderLayout.PAGE_START constraint to be used
The class Drawing is required to override getPreferredSize
The Dimension specified by getPreferredSize should be large enough to accommodate the position specified in the constructor of Drawing
Read: Changing preferred size of a Swing component

Java graphics slow rendering of a draw methods. How to fix it?

Why the following code draws big space gap before circles equivalent to sum of consecutive executions of x=+10 statement?
class Panel extends JPanel {
private int x=10;
public void paintComponent( Graphics g ) {
super.paintComponent( g );
g.setColor( Color.MAGENTA );
for (int i=1; i<=8; i++) {
g.drawOval( x, 10, 50, 50 );
x+=10;
}
}
}
public class Circles156 {
public static void main(String[] args) {
JFrame frame = new JFrame( "Drawing lines, rectangles and ovals" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
Panel Panel = new Panel();
Panel.setBackground( Color.WHITE );
frame.add( Panel ); // add panel to frame
frame.setSize( 800, 300 ); // set frame size
frame.setVisible( true ); // display frame
}
}
Put x inside paintComponent() method.
Every time it is called, x is will increase the "initial value" by 80.

How to dynamically add a new customized button?

I am trying to have my interface dynamically generate a customized button when I click a button. I searched several answers like this, but somehow it does not work. Is there any mistake with my current code below?
public class MainWindow {
private JFrame frame;
private JPanel panel;
private JPanel panel_1;
private JPanel panel_2;
private JSplitPane splitPane;
private JButton btnSearch;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow window = new MainWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainWindow() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 645, 438);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.CENTER);
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
splitPane = new JSplitPane();
panel.add(splitPane);
panel_1 = new JPanel();
splitPane.setLeftComponent(panel_1);
btnSearch = new JButton("Search");
GridBagConstraints gbc_btnSearch = new GridBagConstraints();
gbc_btnSearch.gridx = 0;
gbc_btnSearch.gridy = 10;
panel_1.add(btnSearch, gbc_btnSearch);
panel_2 = new JPanel();
splitPane.setRightComponent(panel_2);
btnSearch.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
addButton();
}
});
}
protected void addButton() {
MyButton hahaButton = new MyButton("haha");
panel_2.add(hahaButton);
panel_2.add(new JButton());
panel_2.revalidate();
panel_2.repaint();
}
And this is the definition of the MyButton:
public class MyButton extends JButton {
private static final long serialVersionUID = 1L;
private Color circleColor = Color.BLACK;
public MyButton(String label) {
super(label);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension originalSize = super.getPreferredSize();
int gap = (int) (originalSize.height * 0.2);
int x = originalSize.width + gap;
int y = gap;
int diameter = originalSize.height - (gap * 2);
g.setColor(circleColor);
g.fillOval(x, y, diameter, diameter);
}
#Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
size.width += size.height;
return size;
}
}
I just tried your sourcecode and it works as expected: everytime I klick the search button on the left side of the split-pane, 2 buttons are added to the panel on the right side of the panel (one with the black filled circle and a button without a label).
What doesn't work for you? I'm using java 1.6 on Mac OSX, but this should work with earlier versions on other platforms as well......
As Dieter Rehbein pointed out, the code you have does compile and run.
However, it was rather sloppy and convoluted, as if you copied and pasted different sources together.
I took a few minutes and cleaned it up some, hope it helps.
public class MainWindow
{
public static void main( String[] args )
{
new MainWindow();
}
public MainWindow()
{
// Create the split pane
JSplitPane jSplitPane = new JSplitPane();
final JPanel leftPanel = new JPanel();
final JPanel rightPanel = new JPanel();
jSplitPane.setLeftComponent( leftPanel );
jSplitPane.setRightComponent( rightPanel );
// Create the button
JButton jButton = new JButton( "Generate" );
leftPanel.add( jButton );
jButton.addMouseListener( new MouseAdapter()
{
#Override
public void mouseClicked( MouseEvent e )
{
addButtons( rightPanel );
}
} );
// Create the panel
JPanel jPanel = new JPanel();
jPanel.setLayout( new BoxLayout( jPanel , BoxLayout.X_AXIS ) );
jPanel.add( jSplitPane );
// Create the frame
JFrame jFrame = new JFrame();
jFrame.setBounds( 100 , 100 , 645 , 438 );
jFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
jFrame.getContentPane().add( jPanel , BorderLayout.CENTER );
// Show the frame
jFrame.setVisible( true );
}
private void addButtons( JPanel jPanel )
{
addButton( jPanel , "Default" , null );
addButton( jPanel , "Red" , Color.RED );
addButton( jPanel , "Yellow" , Color.YELLOW );
addButton( jPanel , "Blue" , Color.BLUE );
addButton( jPanel , "Green" , Color.GREEN );
}
protected void addButton( JPanel jPanel , String label , Color color )
{
jPanel.add( new MyButton( label , color ) );
jPanel.revalidate();
jPanel.repaint();
}
public class MyButton extends JButton
{
private static final long serialVersionUID = 1L;
private Color color = null;
public MyButton( String label , Color color )
{
super( label );
this.color = color;
}
#Override
protected void paintComponent( Graphics graphics )
{
super.paintComponent( graphics );
if ( color != null )
{
Dimension dimension = super.getPreferredSize();
int gap = ( int ) ( dimension.height * 0.2 );
int diameter = dimension.height - ( gap * 2 );
graphics.setColor( color );
graphics.fillOval( dimension.width + gap , gap , diameter , diameter );
}
}
#Override
public Dimension getPreferredSize()
{
Dimension size = super.getPreferredSize();
size.width += size.height;
return size;
}
}
}

Categories

Resources