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
Related
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!
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.
If I set up a JFrame with some components and a layout manager, which initially looks perfectly fine, and then later due to some condition (say, clicking a button) I hide one of those components - the layout manager shuffles all the components around again.
See example code - initially 3 buttons appear. When you click the Hide button, the Hide button is hidden - but the two outer buttons then squash together. When you click the show button, they move apart again to make space. How can I stop that from happening, so that after I call pack (), components stay where they are no matter if they later become hidden?
In my real code I'm doing this with GridBagLayout, but used FlowLayout in the example below because its simpler and less code, and shows exactly the same behaviour.
I can only think of nasty ways of doing this, like using .setEnabled (false) instead of .setVisible (false), and then overriding the component's paintComponent () method to not draw the component when it is disabled.
It seems the exact opposite problem to here - Hide a button from Layout in Java Swing - where is complaining that hidden buttons do still take up space :) But there's no sample code there to show it working in that way.
Many thanks for any suggestions :)
Example:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RevalidateWhenSetChildInvisibleExample
{
private JButton button1;
private JButton button2;
private JButton button3;
public void run ()
{
// Set up action
Action hideButtonAction = new AbstractAction ()
{
#Override
public void actionPerformed (ActionEvent e)
{
button2.setVisible (false);
}
};
hideButtonAction.putValue (Action.NAME, "Hide");
Action showButtonAction = new AbstractAction ()
{
#Override
public void actionPerformed (ActionEvent e)
{
button2.setVisible (true);
}
};
showButtonAction.putValue (Action.NAME, "Show");
// Set up buttons
button1 = new JButton ("Dummy");
button2 = new JButton (hideButtonAction);
button3 = new JButton (showButtonAction);
// Set up content pane
JPanel contentPane = new JPanel ();
contentPane.setLayout (new FlowLayout ());
contentPane.add (button1);
contentPane.add (button2);
contentPane.add (button3);
// Set up frame
JFrame frame = new JFrame ();
frame.setContentPane (contentPane);
frame.pack ();
frame.setVisible (true);
}
public static void main (String args [])
{
SwingUtilities.invokeLater (new Runnable ()
{
public void run ()
{
new RevalidateWhenSetChildInvisibleExample ().run ();
}
});
}
}
You could use a CardLayout and then swap the button with an empty JPanel.
Read the section from the Swing tutorial on How to Use CardLayout for more information and examples.
The problem is the layout manager, which is not really a problem here because it is just doing its job. You could set the layout to null and then set the bounds for every button; this way they will NEVER move unless you change their position.
panel.setLayout(null);
button1.setBounds(10,10,50,20);
button2.setBounds(70,10,50,20);
button3.setBounds(xPos,yPos,width,height);
Another way is to use the GridLayout:
contentPane.setLayout(new GridLayout());
I tested it, and it worked fine, since the component did not get removed it stays the same.
Also, you should add the following to your code:
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
This makes the program exits when the JFrame is closed; without it the program still runs at the background.
Sorry if this is a really stupid question but I can't figure out how to set the size of a JButton. I'm trying to create a custom JButton class which can be called from anywhere with custom text to make things easier. I am also trying to set a background image which doesn't appear to be working either.
I have tried using this.setSize(1000, 1000) (surely this should work) but this does nothing at all.
Here is my code:
package menu;
import javax.swing.*;
#SuppressWarnings("serial")
public class Button extends JButton
{
public Button(String name)
{
ImageIcon background = new ImageIcon("/assets/buttons/menu.png"); //Is this how you set a background image for a button?
this.setText(name);
this.setIcon(background);
this.setLayout(null); //This hasn't made a difference
this.setSize(300, 80); //This does nothing
}
}
try
import javax.swing.JButton;
public class replaceButton **extends JButton**
{
public replaceButton(String name)
{
this.setText(name);
ImageIcon background = new ImageIcon("/assets/buttons/menu.png");
this.setIcon(background);
this.setSize(1000,1000);
}
}
by extending JButton you give it the properties of a button.
make sure you dont have any layout by adding this to the JFrame
this.setLayout(null);
else the button will be adjusted to the layout
see http://docs.oracle.com/javase/tutorial/uiswing/layout/border.html
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.