JLabel showing ellipses when is has space to show full label
my code:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.basic.BasicLookAndFeel;
import com.bulenkov.darcula.DarculaLaf;
public class GUI implements ActionListener {
private int count = 0;
private JLabel label;
private JFrame frame;
private JPanel panel;
public GUI() throws UnsupportedLookAndFeelException {
BasicLookAndFeel darcula = new DarculaLaf();
UIManager.setLookAndFeel(darcula);
frame = new JFrame();
JButton button = new JButton("Click Me");
button.addActionListener(this);
label = new JLabel("Number of clicks: 0");
panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(20, 100, -85, 100));
panel.setLayout(new GridLayout(5, 1));
panel.add(button);
panel.add(label);
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
///frame.setTitle("Cool GUI");
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) throws UnsupportedLookAndFeelException {
new GUI();
}
#Override
public void actionPerformed(ActionEvent e) {
count++;
label.setText("Number of clicks: " + count);
}
}
Oracle has a good tutorial that teaches the basics of Swing, Creating a GUI With JFC/Swing. Skip the Netbeans section.
I created the following GUI.
Here's what I did.
I started my Swing GUI with a call to the SwingUtilities invokeLater method. This method ensures that all of the Swing components are created and executed on the Event Dispatch Thread.
I separated the code to construct the JFrame from the code to construct the JPanel. The JFrame methods have to be called in a certain order. This is the order I use for most of my Swing applications.
I construct the JPanel in Swing component order. I keep all methods having to do with a particular Swing component together.
I put the "Number of clicks:" text in one place.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BasicGUI implements ActionListener, Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new BasicGUI());
}
private int count;
private JLabel label;
public BasicGUI() {
this.count = 0;
}
#Override
public void run() {
JFrame frame = new JFrame("Cool GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setResizable(false);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JButton button = new JButton("Click Me");
button.addActionListener(this);
panel.add(button);
label = new JLabel();
label.setHorizontalAlignment(JLabel.CENTER);
updateLabel(0);
panel.add(label);
return panel;
}
public void updateLabel(int count) {
label.setText("Number of clicks: " + count);
}
#Override
public void actionPerformed(ActionEvent event) {
updateLabel(++count);
}
}
BasicLookAndFeel darcula = new DarculaLaf();
UIManager.setLookAndFeel(darcula);
Don't use a 3rd party LAF when asking a basic question.
We don't know if the problem is related to the LAF or the standard classes of the JDK.
JLabel showing ellipses when is has space to show full label
Well actually it doesn't have space because you use the pack() method and all components are displayed at their preferred size based on the preferred size of the components and of the Borders applied to the components.
When I run your code (using the default LAF) the text displays correctly at startup.
This is because the width of the panel is controlled by the preferred width of the JButton since it is the larger component.
However, if I change the text of the button to be:
label.setText("Number of clicks made: " + count);
now the width of the panel is controlled by the preferred width of the label since it is greater than that of the button.
Again, at startup the text displays properly
However, if you click the button 10 times then the "count" changes from a one digit number to a two digit number which increases the preferred size of the label causing the "..." to appear.
A simple solution is to use:
count++;
label.setText("Number of clicks made: " + count);
frame.pack();
Now the frame will be resized to accommodate the newly calculated preferred size of the label.
panel.setLayout(new GridLayout(5, 1));
Also, don't hardcode the "rows" of the GridLayout. The above code reserves space for 5 components even though you only have 2.
Instead use:
panel.setLayout(new GridLayout(0, 1));
which indicates a single column with any number of components.
Then you can use the EmptyBorder properly to give it symmetry on all sides:
//panel.setBorder(BorderFactory.createEmptyBorder(20, 100, -85, 100));
panel.setBorder(BorderFactory.createEmptyBorder(20, 100, 20, 100));
I think GridBagLayout asks your JLabel about the required size when the UI is initialized. Then the JLabel is assigned the requested size.
During runtime the String that needs to be displayed by the JLabel changes, and actually it gets longer. But no re-layout is happening, therefore the JLabel is not allowed to use more space - even if on the screen it seems there is plenty of space.
The solution is to either tell GridBagLayout to reserve plenty of space for that component, or allow for dynamic scaling. Check the GridBagLayout tutorial for details.
Related
I can see the button and when I get rid of the button, I can see the JLabelI'm using the Eclipse IDE and I'm trying to have a JLabel display over a JButton.
I already tried creating my JLabel above my JButton, still doesn't work
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section. Pay particular attention to the Laying Out Components Within a Container section.
Since you posted an image of your code fragment, I created the following GUI.
I should post an image of the code, but I'm going to be nice and post the complete runnable code.
import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class JLabelOverJButtonGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JLabelOverJButtonGUI());
}
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1, 5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JLabel label = new JLabel("Label");
panel.add(label);
JButton button = new JButton("Button");
panel.add(button);
return panel;
}
}
I tried to make a JButton that would put a JLabel in the window, but when I click the button, it doesn't seem to put the JLabel in the window. The button seems to work when I use it for the console, but not for putting the JLabel in the window. Why is this, and what should I do?
Here's my code:
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class AnimaleseTranslator implements ActionListener {
private static JPanel panel;
private static JLabel label;
public AnimaleseTranslator() {
JFrame frame = new JFrame();
panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(220, 391, 220, 391));
panel.setLayout(new GridLayout(0, 1));
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null); // centers the JFrame
frame.setTitle("Animalese Translator");
frame.setVisible(true);
JButton button = new JButton("Click me!");
button.setBounds(100, 100, 98, 55);
button.addActionListener(this);
panel.add(button);
label = new JLabel("lkdsajflksdjlaskdjf");
label.setBounds(200, 200, 50, 50);
}
public static void main(String[] args) {
new AnimaleseTranslator();
}
#Override
public void actionPerformed(ActionEvent e) {
panel.add(label);
}
}
but when I click the button, it doesn't seem to put the JLabel in the window.
The setBounds(...) statement does nothing. Swing uses layout managers by default and the layout manager will set the size/location of each component. So get rid of the setBounds() statement because it is confusing.
Components need to be added to the frame BEFORE the frame is made visible. The pack() or setVisible() statement will then invoke the layout manager.
After you add a component to panel on a visible frame you need to invoke panel.revalidate() to invoke the layout manager. So you need to add the revalidate() in the ActionListener.
Get rid of the setBorder(...) statement until you better understand what it does. The problem with your current code is the border is too big, so there is no room for the button and label to display properly.
I'm trying to create something super basic but after getting super frustrated I figured it was time to ask here.
Desired result:
Right now here is my code:
GUI class
package bookingProject;
import java.awt.Color;
import javax.swing.JPanel;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class GUI extends javax.swing.JFrame {
JFrame frame = new JFrame();
JPanel silverPanel = new JPanel();
JPanel goldPanel = new JPanel();
Button buttons[] = new Button[30];
public static void main(String args[]) {
new GUI();
}
public GUI() {
setSize(500, 500);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel bronzePanel = new JPanel();
bronzePanel.setLayout(new GridLayout(3, 10));
bronzePanel.setBackground(Color.red);
for (int i = 0; i < 30; i++) {
buttons[i] = new Button();
bronzePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
bronzePanel.add(buttons[i]);
}
add(bronzePanel);
setVisible(true);
silverPanel.setLayout(new GridLayout(3, 10));
silverPanel.setBackground(Color.yellow);
for (int i = 0; i < 30; i++) {
buttons[i] = new Button();
silverPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
silverPanel.add(buttons[i]);
}
add(silverPanel);
setVisible(true);
goldPanel.setLayout(new GridLayout(3, 10));
goldPanel.setBackground(Color.green);
for (int i = 0; i < 30; i++) {
buttons[i] = new Button();
goldPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
goldPanel.add(buttons[i]);
}
add(goldPanel);
setVisible(true);
}
}
And a class for the Buttons I want to use
Button class
package bookingProject;
import java.awt.Color;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Button extends JButton implements ActionListener{
public Button (){
this.addActionListener(this);
}
public void actionPerformed(ActionEvent e){
Object source = e.getSource();
if (source instanceof GUI){
((GUI)source).setBackground(Color.YELLOW);
}
}
}
This is what I'm getting:
I'm brand new to this stuff so forgive my complete ignorance/ability... but what I would like is 3 panels going top to bottom (bronze/silver/gold) each with a GridLayout of buttons... But all I can get is the bronze panel sticking infront of everything else. I think I'm supposed to use BoxLayout to sort the 3 panels into an order but I played around with this for about 4 hours and felt like I was getting nowhere fast.
I also need a way of making the buttons turn yellow when I press them but currently that isn't working; although I barely looked at that.
This is what I'm getting:
By default the content pane of a JFrame uses a BorderLayout. When you add components to the frame the components get added to the BorderLayout.CENTER by default because you didn't specify a constraint. Only one component can be displayed in the CENTER so only the last one added is visible.
I think I'm supposed to use BoxLayout
That is one approach (but probably not the easiest) as you would manually need to specify the space between each row of components.
The section from the Swing tutorial on How to Use Box Layout has a working example to get you started.
Easiest is to use a GridLayout with 3 rows and 2 columns as the layout manager for the frame. Then each individual panel can also use a GridLayout with 3 rows and 5 columns.
If you want spaces between the components in each of your panels then you need to look at the GridLayout API. It allows you to specify a vertical and horizontal gap between components.
Another approach would be to use a GridBagLayout, although this is a little more complicated because you need to specify constraints for each component added.
The tutorial also has sections on How to Use GridBag Layout and How to Use GridLayout.
Note the examples from the tutorial will also show you how to better structure your code so that component are created on the Event Dispatch Thread(EDT).
You can try GridBagLayout instead:
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import java.awt.Insets;
import java.awt.Color;
class Demo{
public static void main(String[]args){
SwingUtilities.invokeLater(()->{
JFrame frame=new JFrame("Grid");
JPanel panel=(JPanel)frame.getContentPane();
GridBagConstraints gbc=new GridBagConstraints();
gbc.insets=new Insets(9,7,5,5);
panel.setLayout(new GridBagLayout());
panel.add(newGrid(Color.YELLOW,gbc, 0, 0),gbc);
panel.add(newGrid(Color.YELLOW,gbc, 1, 0),gbc);
panel.add(newGrid(Color.LIGHT_GRAY,gbc, 0, 1),gbc);
panel.add(newGrid(Color.LIGHT_GRAY,gbc, 1, 1),gbc);
panel.add(newGrid(Color.GREEN,gbc, 0, 2),gbc);
panel.add(newGrid(Color.GREEN,gbc, 1, 2),gbc);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
});
}
private static JPanel newGrid(Color color, GridBagConstraints pGbc, int pX, int pY){
JPanel panel=new JPanel(new GridBagLayout());
GridBagConstraints gbc=new GridBagConstraints();
gbc.insets=new Insets(5,5,5,5);
for(int x=0;5>x;x++){
for(int y=0;3>y;y++){
gbc.gridx=x;
gbc.gridy=y;
JButton btn=new JButton("<html> </html>");
btn.setBackground(color);
panel.add(btn,gbc);
}
}
pGbc.gridx=pX;
pGbc.gridy=pY;
return panel;
}
}
I have a problem using BorderLayout, but first of all, here is my GUI setup:
As you can see, I have 3 different components inside my JFrame. Adding the JMenu and JList works fine. But my JPanel should have a fixed size so I want to prevent my BorderLayout from stretching the panel. I tried everything, setPreferredSize() setMinimumSize() setMaximumSize() setSize() but again the layout stretches my panel to fit to the frame. (The panel is added to the frame using BorderLayout.CENTER).
Is there any way to prevent this or do you have other suggestions to manage the problem?
I'm pretty sure you mean BorderLayout, not BoxLayout, because there is no BoxLayout.CENTER and it looks like you use a BorderLayout to place the components.
I think the problem here is that you only set the preferred size of the panel that you add to BorderLayout.CENTER. This doesn't have any effect. Instead you need nested layouts.
In this example I added the JPanel called centerPanel, which is using a standard GridBagLayout (to center the added component), to BorderLayout.CENTER. Then I added the additional JPanel called panel, which has a custom preferrdSize, to centerPanel. This way panel won't get stretched.
Code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class Example {
public Example() {
JMenuBar menuBar = new JMenuBar();
menuBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.BLACK));
DefaultListModel<String> listModel = new DefaultListModel<String>();
JList<String> list = new JList<String>(listModel);
list.setBorder(BorderFactory.createMatteBorder(0, 0, 0, 1, Color.BLACK));
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Uncomment the following lines if you also want to prevent the
// 'wrapping' of the panel.
/*
* #Override public Dimension getMinimumSize() { return new
* Dimension(400, 400); }
*/
};
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
for (int i = 1; i <= 5; i++) {
menuBar.add(new JMenu("Menu " + i));
listModel.addElement("Element " + i);
panel.add(new JLabel("Label " + i));
}
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(panel);
JPanel contentPanel = new JPanel(new BorderLayout());
contentPanel.add(menuBar, BorderLayout.NORTH);
contentPanel.add(list, BorderLayout.WEST);
contentPanel.add(centerPanel);
JFrame frame = new JFrame();
frame.setContentPane(contentPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Example();
}
});
}
}
Add your existing JPanel to a JPanel having Flowlayout, the default, or having GridBagLayout with default constraints. Add this panel to the frame's center, BorderLayout.CENTER by default.
Panel centerPane = new Panel(new GridBagLayout())`;
centerPane.add(yourJPanel);
frame.add(centerPane, BorderLayout.CENTER);
Also consider using Box, rather than a JPanel having BoxLayout.
Also consider using the frame's setJMenuBar(), rather than add(BorderLayout.PAGE_START).
I was playing around with JFrame today and had trouble getting a JButton component to display text properly. The text displayed in JButton is cut off at the end. I tried resizing the JButton component in order to make sure that the text could fit, but the same problem occurred. The problem looks like this:
Here is the code:
import javax.swing.JFrame;
public class Launcher {
public static void main(String[] args) {
JFrame jFrame = new JFrame("Frame");
jFrame.setSize(400, 400);
jFrame.setDefaultCloseOperation(jFrame.EXIT_ON_CLOSE);
jFrame.setLocation(400, 400);
jFrame.add(new Drawable(jFrame));
jFrame.setVisible(true);
}
}
Here is the other class in another .java file.
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Drawable extends JPanel {
private JButton button;
private JFrame jFrame;
public Drawable(JFrame jFrame) {
this.jFrame = jFrame;
button = new JButton("This text does not show properly");
button.setPreferredSize(new Dimension(200, 25));
button.setLocation(jFrame.getWidth() / 2 - 50, jFrame.getHeight() / 2 - 12);
this.add(button);
}
}
I understand that this might be a problem with my project's setup, so if anyone needs me to post it I can do so.
Remove the statement
button.setPreferredSize(new Dimension(200, 25));
which is being used by the panel's layout manager to constrain the button width