How to dynamically add a new customized button? - java

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;
}
}
}

Related

Moving left right in a JPanel

I want to add a number of buttons to a JPanel dynamically, When I add it only shows a fixed number of buttons,
So I would like to add a left right moving for viewing all buttons
How we can do this, Is there any java component to do this?
public class TestJPanel extends JFrame {
JPanel statusBar;
public TestJPanel() {
setLayout(new BorderLayout());
statusBar = new JPanel();
statusBar.setLayout(new BoxLayout(statusBar, BoxLayout.LINE_AXIS));
add("South", statusBar);
for (int i = 1; i < 20; i++) {
statusBar.add(new Button("Button" + i));
}
} }
Here is some old code I had lying around that will automatically add/remove left/right buttons as required:
import java.awt.*;
import java.util.List;
import java.util.ArrayList;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.*;
public class ScrollContainer extends JPanel
implements ActionListener, ComponentListener
{
private Container container;
private List<Component> removedComponents = new ArrayList<Component>();
private JButton forwardButton;
private JButton backwardButton;
public ScrollContainer(Container container)
{
this.container = container;
setLayout( new BorderLayout(5, 0) );
addComponentListener( this );
// Create buttons to control scrolling
backwardButton = new BasicArrowButton( BasicArrowButton.WEST );
configureButton( backwardButton );
forwardButton = new BasicArrowButton( BasicArrowButton.EAST);
configureButton( forwardButton );
// Layout the panel
add( backwardButton, BorderLayout.WEST );
add( container );
add( forwardButton, BorderLayout.EAST );
}
// Implement the ComponentListener
public void componentResized(ComponentEvent e)
{
// When all components cannot be shown, add the forward button
int freeSpace = getSize().width - container.getPreferredSize().width;
if (backwardButton.isVisible())
freeSpace -= backwardButton.getPreferredSize().width;
forwardButton.setVisible( freeSpace < 0 );
// We have free space, redisplay removed components
while (freeSpace > 0 && ! removedComponents.isEmpty())
{
if (removedComponents.size() == 1)
freeSpace += backwardButton.getPreferredSize().width;
Object o = removedComponents.get(removedComponents.size() - 1);
Component c = (Component)o;
freeSpace -= c.getSize().width;
if (freeSpace >= 0)
{
container.add(c, 0);
removedComponents.remove(removedComponents.size() - 1);
}
}
// Some components still not shown, add the backward button
backwardButton.setVisible( !removedComponents.isEmpty() );
// repaint();
}
public void componentMoved(ComponentEvent e) {}
public void componentShown(ComponentEvent e) {}
public void componentHidden(ComponentEvent e) {}
// Implement the ActionListener
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
// Scroll the components in the container
if (source == forwardButton)
scrollForward();
else
scrollBackward();
}
/*
* Simulate scrolling forward
* by remove the first component from the container
*/
private void scrollForward()
{
if (container.getComponentCount() == 1)
return;
// Remove and save the first component
Component c = container.getComponent(0);
container.remove( c );
removedComponents.add( c );
// Allow for backwards scrolling
backwardButton.setVisible( true );
// All components are showing, hide the forward button
int backwardButtonWidth = backwardButton.getPreferredSize().width;
int containerWidth = container.getPreferredSize().width;
int panelWidth = getSize().width;
if (backwardButtonWidth + containerWidth <= panelWidth)
forwardButton.setVisible( false );
// Force a repaint of the panel
revalidate();
repaint();
}
/*
* Simulate scrolling backward
* by adding a removed component back to the container
*/
private void scrollBackward()
{
if (removedComponents.isEmpty())
return;
// Add a removed component back to the container
Object o = removedComponents.remove(removedComponents.size() - 1);
Component c = (Component)o;
container.add(c, 0);
// Display scroll buttons when necessary
if (removedComponents.isEmpty())
backwardButton.setVisible( false );
forwardButton.setVisible( true );
revalidate();
repaint();
}
private void configureButton(JButton button)
{
button.setVisible( false );
button.addActionListener( this );
}
private static void createAndShowGUI()
{
JToolBar toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.add( new JButton("one") );
toolBar.add( new JButton("two222222") );
toolBar.add( new JButton("three") );
toolBar.add( new JButton("four") );
toolBar.add( new JButton("five") );
toolBar.add( new JButton("six666666666") );
toolBar.add( new JButton("seven") );
toolBar.add( new JButton("eight") );
toolBar.add( new JButton("nine9999999") );
toolBar.add( new JButton("ten") );
ScrollContainer container = new ScrollContainer(toolBar);
JFrame frame = new JFrame("Scroll Container");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(container, BorderLayout.NORTH);
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
public TestJPanel()
{
setLayout(new BorderLayout());
statusBar = new JPanel();
statusBar.setLayout(new BoxLayout(statusBar, BoxLayout.LINE_AXIS));
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportView(statusBar)
add(scrollPane, BorderLayout.SOUTH);
for (int i = 1; i < 20; i++) {
statusBar.add(new Button("Button" + i));
}
}
If the look does not satisfy you, see for example Custom design JScollPane Java Swing and read about custom Look and Feels
I got one solution , we can implement left right navigation by using JViewport
public class StatusBar extends JFrame {
private final JPanel statusBar;
private final JPanel leftrightPanel;
private final JPanel myPane;
private final JButton rightButton;
private final JButton leftButton;
private final JViewport viewport;
private final JPanel iconsPanel;
private JButton button;
public StatusBar() {
setLayout(new BorderLayout());
statusBar = new JPanel();
statusBar.setLayout(new BorderLayout());
iconsPanel = new JPanel();
iconsPanel.setLayout(new BoxLayout(iconsPanel, BoxLayout.LINE_AXIS));
iconsPanel.setBackground(Color.LIGHT_GRAY);
viewport = new JViewport();
viewport.setView(iconsPanel);
leftrightPanel = new JPanel();
leftrightPanel.setBackground(Color.WHITE);
rightButton = new BasicArrowButton(BasicArrowButton.WEST);
rightButton.addActionListener((ActionEvent e) -> {
int iconsPanelStartX = iconsPanel.getX();
if (iconsPanelStartX < 0) {
Point origin = viewport.getViewPosition();
if (Math.abs(iconsPanelStartX) < 20) {
origin.x -= Math.abs(iconsPanelStartX);
} else {
origin.x -= 20;
}
viewport.setViewPosition(origin);
}
});
leftButton = new BasicArrowButton(BasicArrowButton.EAST);
leftButton.addActionListener((ActionEvent e) -> {
Point origin = viewport.getViewPosition();
origin.x += 20;
viewport.setViewPosition(origin);
});
leftrightPanel.add(rightButton);
leftrightPanel.add(leftButton);
statusBar.add(viewport);
statusBar.add(leftrightPanel, BorderLayout.LINE_END);
add(statusBar,BorderLayout.SOUTH);
myPane = new JPanel();
add(myPane, BorderLayout.CENTER);
for (int i = 1; i < 20; i++) {
button =new JButton("Button " + i);
iconsPanel.add(button);
}
}}

JButton settext specific position

I have a JButton with an image icon and I need to position the text.
Is there a way to position the text of a JButton in a specific position instead of using CENTER,LEADING, TOP and so on?
I've never tried it on a JButton before, but maybe you can add a JLabel as a component on the button. Then you can use layout managers or Borders to position the label more appropriately.
Here are some example of adding a component to a JLabel 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) );
label3.setLayout( new GridBagLayout() );
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();
}
});
}
}
I doubt the JTExtPane example will work with a button because the text pane will intercept the mouse events and so you will not be able to click the button when you click on the text. So I would stick with the examples that add a label to the button.
Spanish:
Puedes sobreescribir el método setText(String str).
Google Traductor English: You can overwrite the method setText (String str).
private static final String HTML_1 = "<html><body style='margin:0px 0px 0px 0px'>";
private static final String HTML_2 = "</html>";
#Override
public void setText(String txt) {
if (txt.isEmpty()) {
txt = "Dispositivo";
}
String txt2 = HTML_1 + txt + HTML_2;
super.setText(txt2);
}
you can use set bounds method to set the postion of the text on the button
JLabel positiongLabel = new JLabel();
positiongLabel.setBounds(100,50,300,30);
for more detail click here

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

JLabel misplaced after adding JPanel

I'm almost blind after reading lots of java swing articles, and still can not get panel to work.
When i add 2 JLabels, they are nicely aligned to left, with 5px padding defined by EmptyBorder, just as i want them to be.
I found that after adding ProgressBar with extra border for padding, does not work as expected, added 1 more panel, where i add ProgressBar. Progress looks good, but all my labels are displaced.
And finally it look like this (RED background is for debug, to see how JPanel draws):
Question1: How to fix this?
Question2: Is it standard approach for swing to place panel inside of other panel with other panels just to get formating i want?
Source:
public class AppInitProgressDialog {
private static final int VIEW_PADDING_VAL = 5;
private static final Border viewPaddingBorder = new EmptyBorder( VIEW_PADDING_VAL, VIEW_PADDING_VAL, VIEW_PADDING_VAL, VIEW_PADDING_VAL );
private JPanel view; // Dialog view
private JPanel panel;
private JPanel progressPanel;
private JLabel title;
private JLabel progressDesc;
private JProgressBar progressBar;
private void initPanel( int w, int h ) {
view = new JPanel();
view.setBorder( BorderFactory.createRaisedSoftBevelBorder() );
view.setBackground( Color.LIGHT_GRAY );
view.setSize( w, h );
view.setLayout( new BorderLayout() );
panel = new JPanel();
panel.setBorder( viewPaddingBorder );
panel.setLayout( new BoxLayout(panel, BoxLayout.PAGE_AXIS) );
//panel.setLayout( new SpringLayout() );
panel.setOpaque( false );
JFrame parent = AppContext.getMe().getAppWindow().getFrame();
int posx = (parent.getWidth() - w)/2;
int posy = (parent.getHeight() - h)/2;
view.add( panel, BorderLayout.CENTER );
view.setLocation( posx, posy );
}
private void initTitle() {
title = new JLabel( "Progress title" );
title.setAlignmentX( JComponent.LEFT_ALIGNMENT );
panel.add(title);
}
private void initProgress() {
progressPanel = new JPanel( new BorderLayout() );
progressPanel.setBackground( Color.LIGHT_GRAY );
progressPanel.setBorder( new EmptyBorder( 15, 30, 15, 30) );
progressPanel.setBackground( Color.RED );
progressBar = new JProgressBar(0, 10000);
progressBar.setStringPainted(true);
progressBar.setAlignmentX( JComponent.LEFT_ALIGNMENT );
progressPanel.add(progressBar);
panel.add( progressPanel );
progressDesc = new JLabel( "Progress description" );
panel.add(progressDesc);
}
public AppInitProgressDialog() {
initPanel( 400, 100 );
initTitle();
initProgress();
}
public JComponent getView() {
return view;
}
}
Alternatively, you can use BorderLayout for panel:
panel = new JPanel(new BorderLayout());
...
panel.add(title, BorderLayout.NORTH);
...
panel.add(progressPanel); // default CENTER
...
panel.add(progressDesc, BorderLayout.SOUTH);
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.border.EmptyBorder;
/**
* #see http://stackoverflow.com/a/16837816/230513
*/
public class Test {
private JFrame f = new JFrame("Test");
private void display() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new AppInitProgressDialog().getView());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
class AppInitProgressDialog {
private static final int VIEW_PADDING_VAL = 5;
private JPanel view; // Dialog view
private JPanel panel;
private JPanel progressPanel;
private JLabel title;
private JLabel progressDesc;
private JProgressBar progressBar;
private void initPanel(int w, int h) {
view = new JPanel();
view.setBorder(BorderFactory.createRaisedBevelBorder());
view.setBackground(Color.LIGHT_GRAY);
view.setSize(w, h);
view.setLayout(new BorderLayout());
panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.blue));
panel.setOpaque(false);
view.add(panel, BorderLayout.CENTER);
}
private void initTitle() {
title = new JLabel("Progress title");
title.setAlignmentX(JComponent.LEFT_ALIGNMENT);
panel.add(title, BorderLayout.NORTH);
}
private void initProgress() {
progressPanel = new JPanel(new BorderLayout());
progressPanel.setBackground(Color.LIGHT_GRAY);
progressPanel.setBorder(new EmptyBorder(15, 30, 15, 30));
progressPanel.setBackground(Color.RED);
progressBar = new JProgressBar(0, 10000);
progressBar.setStringPainted(true);
progressBar.setAlignmentX(JComponent.LEFT_ALIGNMENT);
progressPanel.add(progressBar);
panel.add(progressPanel);
progressDesc = new JLabel("Progress description");
panel.add(progressDesc, BorderLayout.SOUTH);
}
public AppInitProgressDialog() {
initPanel(400, 100);
initTitle();
initProgress();
}
public JComponent getView() {
return view;
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}
Use Layout Managers rather than just adding panels to each other. Specifically in your case I think you can use GridLayout.
panel.setLayout(new GridLayout(1,1,0,0));
Fore more details on layout refer to this tutorial.

Categories

Resources