How do I make a JLabel text vertically and horizontally aligned to the center?
I have to make use of setHorizontalTextPosition and setVerticalTextPosition. Can this be achieved by using these 2?
I have tried but the text remains at the top itself.
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
public class label extends JFrame
{
private JLabel label;
public label() //constructor
{
super("Simple GUI");
setLayout(new FlowLayout());
label=new JLabel("Centered JLabel");
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);
add(label);
}
}
I have tried but the text remains at the top itself.
You have two problems:
Andrew addressed the first problem. You are using the wrong method.
Next you are using the wrong layout. The FlowLayout only display components on a single line so the component will always be at the top. Don't change the layout manager. The default layout manager for a JFrame is the BorderLayout. When you add a component to the CENTER (which is the default when you don't specify a constraint), the component will be sized to fill the entire frame. Then the "alignment" properties will control the position of the text within the size allocated to the label.
Or a different option is to use a GridBagLayout. Then you don't need to play with alignment options of the component:
setLayout( new GridBagLayout() );
add(label, new GridBagConstraints());
Try both options as both may be effective in different situations.
Read the Swing tutorial on Layout Managers to better understand how each layout manager works.
I'm very sorry to don't know why the setHorizontalTextPosition method and the setVerticalTextPosition method doesn't work.
But, I'll let you know that there're several ways to sort the text in the label by inserting parameters an alignment with String when we create the label.
First of all, camickr's answer is the best answer, Because Swing was designed to be used with layout managers!!
Please remember that the most recommended method is to apply GridBagLayout() to the Layout of JFrame by camickr.
This answer is intended to inform you that
This method is also possible, but not recommended in the normal case
Using this method is not recommended because changing the size of the frame
keeps the components in place, but it could give you a little help
when it is indicated that the size and location of components in the
container are used in a way that can be used in special cases, such as
when they need to be fixed without external impact.
To get a better idea of the problem, I'll simply change the code that you uploaded to me so that it can be executed.
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;
public class StackOver extends JFrame
{
private JLabel label;
public StackOver() //constructor
{
super("Simple GUI");
setLayout(null);
setSize(500,300);
label=new JLabel("Centered JLabel", JLabel.CENTER);
/*
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);*/
add(label);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StackOver();
}
}
Hmm, let's put some color in JLabel's background to find out more.
label.setOpaque(true); //Transparency Settings
label.setBackground(Color.pink); //Specify background color
//to use 'Color' class, We must import java.awt.Color;
the JFrame setting was set to FlowLayout()which makes the location and size of components were fixed, so we couldn't see it working!
So now we're going to go through the next two processes.
1) Changing JFrame's layout to null to use Absolute Layout ("not recommended, just a case")
2) Changing the size and location of the JLabel
after the progress we can see that the text alignment works!
1) Changing JFrame's Layout
the following link: Layout Manager shows that there are so many Layouts outside of FlowLayout.
Swing is designed to use the layout manager, so of course you should use one of the Layout above link.
But, to use an interesting way that fix the location and size of components absolutely We will switch to setLayout(null);!
2) Changing the size and location of the JLabel
We can directly change the size and position of JLabel with setBounds(int startX, int startY, int Width, int Height) method!
import java.awt.FlowLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.Color;
public class StackOver extends JFrame
{
private JLabel label;
public StackOver() //constructor
{
super("Simple GUI");
setLayout(null);
setSize(500,300);
label=new JLabel("Centered JLabel", JLabel.CENTER);
// Since it also sets the size of the JLabel,
//let's use the constructor to set the alignment of the text inside the JLabel.
label.setOpaque(true); //Transparency Settings
label.setBackground(Color.pink); //Specify background color
//to use 'Color' class, We must import java.awt.Color;
Rectangle r = this.getBounds(); //to get Frame Size
label.setBounds(r.x+100, r.y+100, r.width-200, r.height-200);
/*
label.setHorizontalTextPosition(SwingConstants.CENTER);
label.setVerticalTextPosition(SwingConstants.CENTER);*/
add(label);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new StackOver();
}
}
Now we can see the text of JLabel in the middle as intended!
This method can directly fix the size and location of all components (ex buttons), but the location and size of the components are fixed even if the window size of the JFrame changes after the program runs.
so If you really want set components Absolutely by this way, you rather to set JFrame Resizable false by adding below code on JFrame's code
this.setResizable(false);
I hope the answer was helpful to you and have a peaceful day!
Related
I'm new to Java programming and I'd like to know how to mess around with buttons, I have created a "Home Screen" and some buttons as well as text, however it's not as advanced as I'd like it to be, I want to know how to create things like image effects, so let's say I hover over a button, I want it to display a glowing animation behind it, or since I don't have that animation, if there's no easy way to create it, just displaying an image behind it is alright, also I don't have anything happening when pressing the button bcs IDK how to do that yet so if you could help with that it'd be awesome!
Here's the code I currently have:
package Menu;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class BackgroundPanel extends JFrame {
private BufferedImage image;
public BackgroundPanel() {
ImageIcon icon = new ImageIcon("image_path.png");
JButton btn = new JButton(icon);
btn.setOpaque(false);
btn.setContentAreaFilled(false);
btn.setBorderPainted(false);
btn.setFocusPainted(false);
try {
image = ImageIO.read(new File("image_path.jpg"));
// Set your Image Here.
this.setContentPane(new JLabel(new ImageIcon(image)));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JPanel panel = new JPanel();
panel.add(new JLabel("Username:"));
panel.add(new JTextField("",20));
panel.add(new JLabel("Password:"));
panel.add(new JTextField("",20));
panel.add(btn);
//Adding components to Panel and JFrame
this.add(panel);
// JFrame Properties
this.setSize(1280,720);
this.setLayout(new FlowLayout());
this.setResizable(true);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("Panel");
this.setVisible(true);
}
public static void main(String[] args) {
new BackgroundPanel();
}
}
[...] also I don't have anything happening when pressing the button bcs IDK how to do that yet so if you could help with that it'd be awesome [...]
You need to add an ActionListener to your button. There are various other ways to detect if the button was pressed, but this one is the (in my opinion) easiest. This is how you do it:
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
// code you write in here will be executed if the button was pressed
}
});
[...] let's say I hover over a button, I want it to display a glowing animation behind it, or since I don't have that animation, if there's no easy way to create it, just displaying an image behind it is alright [...]
For this, you'll have to deal with JLayeredPanes and MouseListeners. Here is an example that I created "on the run"; the layouting is very dirty and has to be improved. Anyhow, you'll notice that once you hover over the button, a black-bordered box containing LA- -LL! will appear behind the button. That's a JLabel and you can use it to display images and such by using the JLabel.setIcon method.
let's say I hover over a button, I want it to display a glowing animation behind it, or since I don't have that animation, if there's no easy way to create it, just displaying an image behind it is alright
This is not that easy, it requires jumping through a whole bunch of hoops, especially when the button isn't rectangle.
A while I ago a did a prototype of a "validation highlighter" which highlighted invalid fields, it makes use of JXLayer library, but which should be convertible to use the included JLayer library on the core libraries
See How can I change the highlight color of a focused JComboBox for more details
The other possibility we'd be to create a custom JPanel and override its paintComponent method and paint your effect there. You would place your button it and with a combination of a a layout manager and borders you should be able to get the button positioned where you need it.
The problem with this, is it will effect the over layout of your form, as the effect will be considered while the primary form is laid out
I really don't have anything happening when pressing the button bcs IDK how to do that yet so if you could help with that it'd be awesome
I suggest you have a look at How to use buttons and How to write ActionListeners
in this code when the new button is clicked, the Jinternalframe goes behind the button, even if i add anything else like, jlabel, jtextfield, etc, the internalframe opens behind everything. i tried the tofront() and movetofront() functions, but it doesnt seem to work. plz help, thanks.
code:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Messages2 extends JFrame {
JFrame frame;
JButton button1;
public static void main(String[] args) {
Messages2 window = new Messages2();
window.frame.setVisible(true);
}
public Messages2() {
frame = new JFrame();
frame.getContentPane().setBackground(Color.WHITE);
frame.setBounds(100, 100, 220, 220);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//frame.getContentPane().setLayout(new FlowLayout());
JButton btnNew = new JButton("New Message");
btnNew.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JDesktopPane desktopPane = new JDesktopPane();
JInternalFrame intFrame = new JInternalFrame(
"JInternalFrame demo");
intFrame.setMaximizable(true);
intFrame.setIconifiable(true);
intFrame.setResizable(true);
intFrame.setClosable(true);
intFrame.setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
intFrame.setSize(320, 240);
// intFrame.pack();
intFrame.setVisible(true);
desktopPane.add(intFrame);
frame.add(desktopPane, BorderLayout.CENTER);
}
});
btnNew.setBounds(1, 35, 145, 31);
frame.getContentPane().add(btnNew);
}
}
when the new button is clicked, the Jinternalframe goes behind the button, even if i add anything else like, jlabel, jtextfield, etc,
Based on the code you posted in you last question (before you deleted it), you are attempting to add all your components directly to the frame. Swing paints components in the reverse order that a component is added. So since the internal frame is added last it is painted first and then all the other components are painted over top of it.
This is not the way you should be working with a JInternalFrame. You need to separate the JDesktopPane/JInternalFrames from your other components and work with each separately.
Read the section from the Swing tutorial on How to Use Internal Frames for basic information and examples.
the internal frame is added to a JDesktopPane which is added to the frame.
Don't use a null layout for your other components. Swing was designed to be used with layout managers. These components should be added to a panel and then the panel added to the frame.
The panel and the desktop pane must be added to different areas of the frame. For example:
frame.add(panel, BorderLayout.NORTH);
frame.add(desktopPane, BorderLayout.CENTER);
You're not using JInternalFrame correctly. It should only be placed within a JDesktopPane, something you're not doing and that I suggest that you start doing. Please check the appropriate tutorial on this.
Your button and your JInternalFrame now fill the field since you're using the JFrame's default BorderLayout. Suggestion:
First and foremost, explain fully just what exact effect/user experience you're trying to achieve. Are you sure that a JInternalFrame is your best choice here?
Learn about and use the layout managers to their best advantage.
If you're going to use a JInternalFrame, then while it's OK to add the JInternalFrame in your ActionListener, you're usually going to want to add the JDesktopPane to the GUI on GUI creation, not in the ActionListener.
Right now i can only have one of my two components show up on the screen the second one always just overlaps the first so the second is only showing.
How can I get both of them to show up at the same time.
package Game;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Amazing {
private final int width = 300;
private final int height = width / 16 * 9;
private int scale = 3;
private static Graphics g;
private static JFrame frame = new JFrame();
public Amazing(){
Dimension size = new Dimension(width*scale, height*scale);
frame.setPreferredSize(size);
frame.setResizable(false);
frame.setTitle("Amazing!");
Character character = new Character(50,50,scale,width,height);
Map map = new Map(scale, width, height);
frame.add(map);
frame.add(character);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
character.requestFocus();
}
public static void main(String[] args){
Amazing amazing = new Amazing();
}
}
I figured you don't need to see the other two classes(if you want i can also post them) but I think all you need to know about them are that the map class creates and paints with paintComponent(Graphics g) 2 randomly generated rectangles while the Character class creates and uses the paintComponent(Graphics g) method to show and Image on the screen.
Since you didn't specify a layout, you were using BorderLayout which only displays 1 component in each section. Unless you specify a different location as an additional arg when using the default BorderLayout, the add(component) method will "overwrite" whatever was there previously. Therefore, when you add your second component to your frame it overwrites the first.
I noticed that you imported GridLayout, but i don't see it used in your code. If you add a statement in the constructor like:
this.setLayout(new GridLayout(4, 2));
it will change the layout from the default BorderLayout to the GridLayout, and you will have 4 rows of 2 compartments each in which to place components. Calling the add(component) method will add a component in the next available section, starting with row 1 spot 1.
If you only want to add those two items, try putting in the statement
this.setLayout(new GridLayout(1, 2));
before you add your components. This will place them side by side.
When adding components to a panel in Swing you should choose a LayoutManager for the panel (FlowLayout is simple, GridBoxLayout flexible, but there are many more). Depending on the layout chosen you also associate data with the component to tell the LayoutManager where to place the component.
The "main" problem you're having is the fact that by default JFrame uses a BorderLayout. BorderLayout will only only a single component to occupy each of its five available positions. By default, BorderLayout will place components at the CENTER position.
You should explore a different layout manager which meets your requirements.
Take a look at Laying Out Components Within a Container
Can someone please explain to me, why every time I use the FlowLayout Layout manager
my textfields are displayed as slits.
I have bumped my head against this problem for some time now, and I can't seem to figure
out why it goes wrong.
I get a feeling it is a simple thing that I am overlooking time and time again, so if
someone would please explain this phenomenon to me, I would be forever grateful.
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class Console
{
public Console()
{
makeConsole();
}
private void makeConsole()
{
JFrame console = new JFrame("ArchiveConsole");
Container base = console.getContentPane();
base.setSize(400, 250);
console.setSize(base.getSize());
base.setLayout(new FlowLayout(FlowLayout.CENTER, 5,5));
JTextField tf = new JTextField();
tf.setSize(base.getWidth(), 25);
base.add(tf);
console.setVisible(true);
}
}
From the Swing layout manager tutorial
The FlowLayout class puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, the FlowLayout class uses multiple rows. If the container is wider than necessary for a row of components, the row is, by default, centered horizontally within the container
So you need to adjust the preferred size of your textfield, preferably by using the setColumns method.
Note that if you want your text field to span the whole width you might want to use another layout then the FlowLayout for the reason quoted above
For example, the following code gives a nice looking JTextField, but I have hardcoded the number of columns
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.FlowLayout;
public class TextFieldWithFlowLayout {
public static void main( String[] args ) {
EventQueue.invokeLater( new Runnable() {
#Override
public void run() {
JFrame console = new JFrame("ArchiveConsole");
Container base = console.getContentPane();
base.setLayout(new FlowLayout( FlowLayout.CENTER, 5,5));
JTextField tf = new JTextField();
tf.setColumns( 20 );
base.add(tf);
console.pack();
console.setVisible(true);
}
} );
}
}
Use:
JTextField tf = new JTextField(25);
Instead of:
JTextField tf = new JTextField();
tf.setSize(base.getWidth(), 25);
When you use LayoutManagers, don't try to set size and position manually. You are conflicting with what the LayoutManager does. Layoutmanagers size and position components based on constraints and preferred/minimum/maximum size. Most Swing components handle that automatically, so you should usually not force their preferred size.
As for your JTextField, since it does not contain any text, its preferred size is close to nothing. Use setColumns to indicate a preferredSize or invoke setPreferredSize
Thanks!
The parameter that using in the JTextField function is very important!
JPanel panel_buttons = new JPanel(new FlowLayout(FlowLayout.LEFT));
panel_buttons.add(...);
...
panel_buttons.add(...);
JTextField txt_search = new JTextField(20);
panel_buttons.add(txt_search);
If change 20 to 30 or large, may be u couldn't find it.May be the txt_search is in the next line.
I'm going to enhance an application with a Swing UI, to allow the user to pick colors so they're not stuck with the default color choices.
It is common for other applications to have shaded rectangles drawn on each button that activates a color selector, with the rectangle's color changing accordingly when a new color is selected. I am trying to achieve the same effect by placing a small JPanel with the selected color on the button, but that results in a tiny square in the middle of the button, instead of filling most of the surface of the button.
I figure another way would be to dynamically generate rectangular icons with the colors and then add the appropriate icon to each button, but surely there must be a simpler way?
put there JButton.setIcon with expected Rectangle, for example
EDIT
I am trying to achieve the same effect by placing a small JPanel with the selected color on the button, but that results in a tiny square in the middle of the button, instead of filling most of the surface of the button.
only JFrame (BorderLayout) and JPanel (FlowLayout) have got pre-implemented LayoutManager, for rest of JComponents (add one JComponent to the another JComponent) you have to define LayoutManager, please read this thread
Here is an example using setBackground that works for me:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String... args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
final JButton button = new JButton("Hello");
button.setOpaque(true);
panel.add(button);
button.setBackground(Color.RED);
button.setOpaque(true);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Color c = JColorChooser.showDialog(button, "Choose a color", button.getBackground());
if (c != null) {
button.setBackground(c);
}
}
});
frame.setContentPane(panel);
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
}
}
Every swing component is drawn using the JComponent.drawComponent(...) method, you can override the default behavior if you want. For example, to make a panel like you suggest. It is worth noting though, that you can change a jpanels background color to achieve the exact same thing.
JColorChooser chooser = new JColorChooser(Color.BLACK);
chooser.setVisible(true);
Color color = chooser.getColor();
if (color!=null) {
colorPanel.setBackground(color);
}
Where colorPanel would be your JPanel indicating your color.