How to Dynamically Add JButton to JPanel? - java

In NetBeans, I have used the GUI editor to make a JFrame and I've put a JPanel in the frame.
At the moment, I'm trying to make a new button in the panel when the class constructs.
This is the code I have, but I can't seem to get it to work.
(The first line makes the button, the other lines try to show it.)
this.jPanel2.add(new JButton("Test"),BorderLayout.NORTH);
this.jPanel2.validate();
this.jPanel2.revalidate();
this.jPanel2.repaint();
this.jPanel2.setVisible(true);
this.revalidate();
this.setVisible(true);
this.repaint();
I've been googling all night, but can't seem to get it to work.

Some times when you don't see a button it is a layout manager issue (as in you aren't setting the right properties for the layout manager). You can test this by disabling it:
this.jPanel2.setLayoutManager(null);
And setting bounds for the button (JButton.setBounds()).
If the above fixes your problem, then you need to look into the requirements set by the LayoutManager you are using (see also the answer by Robin).
All the calls to validate(), revalidate() and repaint() are not needed to do this.

Normally the add call is sufficient.
Note: a BorderLayout can only contain one component in each location. So if you add another component in the NORTH location, your button will not be visible.
Second note: by default a JPanel does not have a BorderLayout but a FlowLayout. Have you set a BorderLayout on that specific panel ? Otherwise the BorderLayout#NORTH constraint is incorrect
All the validate,revalidate,repaint calls can be removed
Edit
It seems some sort of validation is needed after all. I was under the impression that Swing should be smart enough to listen for the event when something is added to a Container, and update whatever is necessary (a bit similar to updating a TableModel updates the JTable based on events, without the need to call repaint or the likes on the JTable).
However, when trying this in an SSCCE, I came to the following code (different versions, only post the most elaborate version)
without the scroll-pane, the validate calls seem to have no effect. I actually need to call pack again to make the new labels visible (not included in the SSCCE, but removing the scrollpane from the code is trivial)
with the scroll-pane, the validate call has an effect
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddLabelsAtRuntime {
private int fLabelCounter = 0;
private JPanel fLabelPanel;
private final JFrame fTestFrame;
public AddLabelsAtRuntime() {
fLabelPanel = new JPanel( );
BoxLayout boxLayout = new BoxLayout( fLabelPanel, BoxLayout.PAGE_AXIS );
fLabelPanel.setLayout( boxLayout );
fTestFrame = new JFrame( "Dynamically add labels" );
}
private JFrame createUI(){
Container contentPane = fTestFrame.getContentPane();
contentPane.setLayout( new BorderLayout() );
JScrollPane scrollPane = new JScrollPane( fLabelPanel );
scrollPane.setPreferredSize( new Dimension( 200, 200 ) );
contentPane.add( scrollPane, BorderLayout.CENTER );
contentPane.add( createButtonPanel(), BorderLayout.SOUTH );
fTestFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
fTestFrame.pack();
return fTestFrame;
}
private void addLabel(){
fLabelPanel.add( new JLabel( "Label " + ++fLabelCounter ) );
}
private JPanel createButtonPanel(){
JPanel buttonPanel = new JPanel( );
BoxLayout boxLayout = new BoxLayout( buttonPanel, BoxLayout.LINE_AXIS );
buttonPanel.setLayout( boxLayout );
JButton validateButton = new JButton( "Add + validate" );
validateButton.addActionListener( new ActionListener() {
#Override
public void actionPerformed( ActionEvent e ) {
addLabel();
fLabelPanel.validate();
fTestFrame.validate();
}
} );
buttonPanel.add( validateButton );
JButton noValidateButton = new JButton( "Add" );
noValidateButton.addActionListener( new ActionListener() {
#Override
public void actionPerformed( ActionEvent e ) {
addLabel();
}
} );
buttonPanel.add( noValidateButton );
JButton packButton = new JButton( "Add + pack" );
packButton.addActionListener( new ActionListener() {
#Override
public void actionPerformed( ActionEvent e ) {
addLabel();
fTestFrame.pack();
}
} );
buttonPanel.add( packButton );
return buttonPanel;
}
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
#Override
public void run() {
AddLabelsAtRuntime addLabelsAtRuntime = new AddLabelsAtRuntime();
addLabelsAtRuntime.createUI().setVisible( true );
}
} );
}
}

Create Dynamic JButton with Image and ActionListener - Java Swing
Create JButton dynamically with Image and the ActionListener . You will be able to change the button height , width horizontal gap and vertical gap in one place.
you can find more details from here

Related

JPanel gets paintComponent gets called when child is entered

Some previous entries here address paintComponent() being called repeatedly, but the answers hinged on paintComponent itself calling repaint().
Using Nimbus L&F, if I subclass JPanel and add a JButton or JTextField, then my JPanel's paintComponent() method gets called whenever I enter or leave a child. In addition, if the JTextField gets focus, my panel's paintComponent() method gets called for every flash of the text field's position cursor. My paintComponent() method does nothing other than print that it is being called. Here's an example:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Tester extends JPanel {
public Tester() {
JPanel p = new JPanel();
JTextField t1 = new JTextField( "text in nested panel" );
p.add( t1 );
this.add( p );
JTextField t2 = new JTextField( "text" );
this.add( t2 );
JButton b = new JButton( "button" );
this.add( b );
setPreferredSize( new Dimension( 400, 200 ) );
}
#Override
public void paintComponent( Graphics g ) {
super.paintComponent( g );
System.out.println( "paint" );
}
public static void main( final String[] args ) {
SwingUtilities.invokeLater( new Runnable() {
#Override
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ( "Nimbus".equals( info.getName() ) ) {
UIManager.setLookAndFeel( info.getClassName() );
break;
}
}
} catch (Exception ex) {
System.out.println( "No Nimbus" );
}
final String name = new String( "GuiViewer" );
final JFrame jf = new JFrame( name );
jf.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
final Tester comp = new Tester();
jf.add( comp );
jf.pack();
jf.setVisible( true );
}
} );
}
}
When you click in the first text field (nested inside another JPanel), you do not get continual calls to paintComponent(). But if you click in the second one, you continually get calls. If you comment out the setting of Nimbus L&F, the paintComponent() doesn't get repeated calls. The Nimbus implementation of JTextField and JButton act like their paintComponent method calls parent.repaint(). Is this a bug in Nimbus, or is it that way by design?
This seems to be a design choice of Nimbus.
If you inspect the result of JTextField#isOpaque, it returns false (making it transparent). This means that when ever the component is repainted, the parent container must first be repainted as well.
The JTextField is triggering a repaint each time the caret is updated (blinks on and off)
The reason why your first JTextField doesn't cause a repaint on the Tester is because it's sitting inside a opaque container, so only it's immediate parent container will be repainted.
Try making the JTextField opaque (t2.setOpaque(true);) and see what happens

JComboBox Dropdown Menu Not Obeying AlwaysOnTop

I have an always-on-top window that I want to remain above all other windows. Using setAlwaysOnTop(true) seems to work for most purposes, but fails when it comes to JComboBox dropdown menus. Is there any way to prevent this from happening? Attached below is a SSCCE and picture of the undesired functionality.
EDIT: Not sure if the behavior is OS-dependent, but I'm noticing the issue on Windows 7 using Java 7. On top is supported on this OS.
EDIT 2: Seems that JPopupMenu has an override on alwaysOnTop() to return true. This is the source of the problem, since on-top components do not have a defined order in how they appear on top of each other (OS-dependent). Worse still, the method is package private. Quite problematic...
Undesired Behavior:
SSCCE:
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JTextField;
public class OnTopTest
{
public static void main( String[] args )
{
new OnTopTest();
}
public OnTopTest()
{
JDialog onTop = new OnTopWindow();
JDialog other = new OtherWindow();
System.out.println("IS ON TOP SUPPORTED? " + onTop.isAlwaysOnTopSupported());
other.setVisible( true );
onTop.setVisible( true );
}
private class OnTopWindow extends JDialog
{
public OnTopWindow()
{
setLayout( new BorderLayout() );
JButton button = new JButton("Button");
add( button, BorderLayout.CENTER );
setSize( 100, 100 );
setAlwaysOnTop( true );
}
}
private class OtherWindow extends JDialog
{
public OtherWindow()
{
setLayout( new BorderLayout() );
JTextField textField = new JTextField("Text");
add( textField, BorderLayout.NORTH);
JButton button = new JButton("Button");
add( button, BorderLayout.CENTER );
JComboBox comboBox = new JComboBox( new Object[] {"Item1", "Item2", "Item3"} );
add( comboBox, BorderLayout.SOUTH );
setSize( 200, 200 );
}
}
}
I'm pretty sure this is handled by the Operating System and that Java cannot force the dropdown to not overlap the other window, as searching for this without specifying Java reported the same behaviour in many different languages.
You can test with a JMenu to confirm, but I'm sure it will also happen as menus and some other controls (like dropdowns) will (by necessity) show above any other window.

Using an Example from Deitel's Java Book Not Working

// Fig. 14.6: LabelFrame.java
// Demonstrating the JLabel class.
import java.awt.FlowLayout; // specifies how components are arranged
import javax.swing.JFrame; // provides basic window features
import javax.swing.JLabel; // displays text and images
import javax.swing.SwingConstants; // common constants used with Swing
import javax.swing.Icon; // interface used to manipulate images
import javax.swing.ImageIcon; // loads images
public class LabelFrame extends JFrame
{
private JLabel label1; // JLabel with just text
private JLabel label2; // JLabel constructed with text and icon
private JLabel label3; // JLabel with added text and icon
// LabelFrame constructor adds JLabels to JFrame
public LabelFrame(){
{super( "Testing JLabel" );
setLayout( new FlowLayout() );
// JLabel constructor with a string argument
label1 = new JLabel( "Label with text" );
label1.setToolTipText( "This is label1" );
add( label1 );
//JLabel constructor with string, Icon and alignment arguments
Icon bug = new ImageIcon( getClass().getResource( "bug1.png" ) );
label2 = new JLabel( "Label with text and icon", bug,
SwingConstants.LEFT );
label2.setToolTipText( "This is label2" );
add( label2 );
label3 = new JLabel(); // JLabel constructor no arguments
label3.setText( "Label with icon and text at bottom" );
label3.setIcon( bug ); // add icon to JLabel
label3.setHorizontalTextPosition( SwingConstants.CENTER );
label3.setVerticalTextPosition( SwingConstants.BOTTOM );
label3.setToolTipText( "This is label3" );
add( label3 );
}
}
That was class one.
import javax.swing.JFrame;
public class LabelTest
{
public static void main( String[] args )
{
LabelFrame labelFrame = new LabelFrame(); // create LabelFrame
labelFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
labelFrame.setSize( 260, 180 ); // set frame size
labelFrame.setVisible( true ); // display frame
} // end main
}
This is class two.
I noticed that with the one untyped (LabelFrame) class did not have a type, but I copied from Deitel's Java book. I assumed we was correct, but so far this is not running because of that little piece of code. I am wondering if it could be an issue with the Java version, since mine is the latest, and the book is from 2012. If you could enlighten me on why this code won't run in Eclipse, that would be greatly appreciated. In addition, the add did not work. Thanks.
OK.. it seems the problem is that the code would not even compile cleanly. This was largely due to the lack of logical indentation leading to incorrectly placed brackets.
This code compile, but fails (here) at run-time due to the missing image.
import java.awt.FlowLayout; // specifies how components are arranged
import javax.swing.JFrame; // provides basic window features
import javax.swing.JLabel; // displays text and images
import javax.swing.SwingConstants; // common constants used with Swing
import javax.swing.Icon; // interface used to manipulate images
import javax.swing.ImageIcon; // loads images
public class LabelFrame extends JFrame
{
private JLabel label1; // JLabel with just text
private JLabel label2; // JLabel constructed with text and icon
private JLabel label3; // JLabel with added text and icon
// LabelFrame constructor adds JLabels to JFrame
public LabelFrame() {
super( "Testing JLabel" );
setLayout( new FlowLayout() );
// JLabel constructor with a string argument
label1 = new JLabel( "Label with text" );
label1.setToolTipText( "This is label1" );
add( label1 );
//JLabel constructor with string, Icon and alignment arguments
Icon bug = new ImageIcon( getClass().getResource( "bug1.png" ) );
label2 = new JLabel( "Label with text and icon", bug,
SwingConstants.LEFT );
label2.setToolTipText( "This is label2" );
add( label2 );
label3 = new JLabel(); // JLabel constructor no arguments
label3.setText( "Label with icon and text at bottom" );
label3.setIcon( bug ); // add icon to JLabel
label3.setHorizontalTextPosition( SwingConstants.CENTER );
label3.setVerticalTextPosition( SwingConstants.BOTTOM );
label3.setToolTipText( "This is label3" );
add( label3 );
}
public static void main( String[] args )
{
LabelFrame labelFrame = new LabelFrame(); // create LabelFrame
labelFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
labelFrame.setSize( 260, 180 ); // set frame size
labelFrame.setVisible( true ); // display frame
} // end main
}
The reason add is showing error is because you didn't "extend JFrame in the LabelFrame class,
It should be coded like this:
public class LabelFrame extends JFrame{
}
that should solve that problem, On the rest of your question, I'm having the same problem because the image is not there, It's null, If anyone can tell me how to get the image and use it, that would be greatly appreciated, Thanks!..
Copy and paste the picture in the package of your project and run the code.I hope it will work.
Another process:
Use
ImageIcon bug = new ImageIcon("java.png");//In the double quotes write the full path of the image.
instead of Icon bug = new ImageIcon( getClass().getResource( "bug1.png" ) );
I hope it will also work.
I faced the same problem. Here is the solution... just make a png image (using photoshop) and name it as bug1.png. Now just copy & paste the image in your project's src folder. Thats all.

How to add a picture onto JTabbedPane - on a null panel layout?

I want to implement a 200 * 200 picture onto my JTabbed Pane layout from the src folder.
My issue is that nothing is showing- no error no exception and no picture.
I dont think I have to declare the directory and set as a private as its already included in the src folder.
import java.awt.*;
import javax.swing.*;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JFrame;
public class Example1
extends JFrame
{
private JTabbedPane tabbedPane;
private JPanel panel1;
public Example1()
{
// NOTE: to reduce the amount of code in this example, it uses
// panels with a NULL layout. This is NOT suitable for
// production code since it may not display correctly for
// a look-and-feel.
setTitle( "Program" );
setSize( 800, 400 );
setBackground( Color.gray );
JPanel topPanel = new JPanel();
topPanel.setLayout( new BorderLayout() );
getContentPane().add( topPanel );
// Create the tab pages
createPage1();
// Create a tabbed pane
tabbedPane = new JTabbedPane();
tabbedPane.addTab( "Tab Page", panel1 );
topPanel.add( tabbedPane, BorderLayout.CENTER );
}
public void createPage1()
{
panel1 = new JPanel();
panel1.setLayout( null );
ImageIcon pic = new ImageIcon("test.png");
JLabel label = new JLabel (pic);
panel1.add(label);
label.setVisible (true);
label.setBounds( 200, 200, 200, 400 );
}
// Main method to get things started
public static void main( String args[] )
{
// Create an instance of the test application
Example1 mainFrame = new Example1();
mainFrame.setVisible( true );
}
}
If you want me to provide more info please ask for it.
Don't use a null layout (and get ride of the setBounds()) on your panel.
The panel doesn't have a preferred size so Swing thinks there is nothing to paint.
ImageIcon doesn't display any error if an image cannot be found - make sure the image is located in the application directory of the application
Re using a null layout, from the docs
Although it is possible to do without a layout manager, you should use a layout manager if at all possible.

displaying images in JComboBox

i need to display a image in JComboBox
Just add an Icon to the model instead of a String:
import java.awt.*;
import javax.swing.*;
public class ComboBoxIcon extends JFrame
{
JComboBox comboBox;
public ComboBoxIcon()
{
Object[] items =
{
new ImageIcon("about16.gif"),
new ImageIcon("add16.gif"),
new ImageIcon("copy16.gif")
};
comboBox = new JComboBox( items );
getContentPane().add( comboBox, BorderLayout.NORTH );
}
public static void main(String[] args)
{
JFrame frame = new ComboBoxIcon();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
Take a look at this example that appears to do what you want.
http://www.java2s.com/Code/Java/Swing-JFC/CustomComboBoxwithImage.htm
What you are looking for is a custom renderer for the JComboBox. A renderer is simply a JComponent, so if you can create a component (JPanel with the necessary items contained), then you can create almost any result that you can think of). You can even override the paint method if using standard JComponents are not enough for you.

Categories