I'm trying to add a JPanel to my JFrame within an actionListener method, but it appears only after the second click on the button. This is a portion of my code where panCours is a JPanel and ConstituerData the targeted JFrame :
addCours.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
panCours.setBounds(215, 2, 480, 400);
panCours.setBorder(BorderFactory.createTitledBorder("Saisir les données concernant le cours"));
ConstituerData.this.getContentPane().add(panCours);
}
});
I don't understand why it doesn't appear as soon as I click on the button. Any explanation and help about how to fix this ?
You'll need to add a call to repaint(); (as well as probably revalidate();) to get the JPanel to show immediately. A basic example demonstrating your problem (and the solution) below;
public class Test {
public static void main(String[] args) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
JButton button = new JButton("Test");
button.setBounds(20, 30, 100, 40);
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
JPanel panel = new JPanel();
panel.setBackground(Color.red);
panel.setBounds(215, 2, 480, 480);
frame.add(panel);
frame.revalidate(); // Repaint here!! Removing these calls
frame.repaint(); // demonstrates the problem you are having.
}
});
frame.add(button);
frame.setSize(695, 482);
frame.setVisible(true);
}
}
The above said, (as suggested by others) it's only right that I recommend against the use of a null layout in future. The swing layouts are a little awkward to begin with, but they will help you a great deal in the long run.
the answer can be found in the following snippet:
you need to revalidate() the contentPane, not repaint the frame. you can add any panel you want to the contentpane like this. if you declare contentPane as a private field you dont need your getContentPane() call. contentPane is global so it can be reffered to directly from anywhere within the class.
be careful about NullPointerExeptions which can be thrown if you refer to it before initialising.
public class testframe extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testframe frame = new testframe();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public testframe() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
contentPane = new JPanel();
setContentPane(contentPane);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JPanel a = new JPanel();
contentPane.add(a);
contentPane.revalidate();
}
});
contentPane.add(btnNewButton);
}
}
Related
I want my buttons to print to the console when I click them. Here's my code. Im looking to make a basic app using this code, and I was wondering how to make the buttons have actions. For the first time, I just want to start with the console for the first time, but later possibly display images?
public static void main(String[] args) {
JFrame frame = new JFrame("GUI");
frame.setSize(320, 300);
frame.setBackground(Color.WHITE);
frame.setVisible(true);
JPanel panel = new JPanel();
panel.setSize(50,50);
JLabel label = new JLabel();
frame.add(panel);
panel.add(label);
label.setText("Welcome to Team 1389!");
Container contentPane = getContentPane();
contentPane.setBackground(Color.blue);
contentPane.setLayout(new FlowLayout());
JButton button = new JButton("MATCHES");
button.setSize(100, 30);
button.setLocation(95, 45);
button.addActionListener(null);
button.setVisible(true);
frame.add(button);
JButton button2 = new JButton("PIT TEAM");
button2.setSize(100, 30);
button2.setLocation(95, 100);
button2.setVisible(true);
frame.add(button2);
JButton button3 = new JButton("SCOUTING");
button3.setSize(100, 30);
button3.setLocation(95, 150);
button3.setVisible(true);
frame.add(button3);
}
private static Container getContentPane() {
// TODO Auto-generated method stub
return null;
}
}
You can look at this tutorial on Oracle's website, it explains things well:
Use an ActionListener. They are interfaces so you will need to add unimplemented methods where the event is handled:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
//do stuff..
}
});
You can also create the listener separately before adding it if you desire to do so:
ActionListener listener = new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
//do stuff..
}
};
button.addActionListener(listener);
Hey everyone, I want to combine my classes and get it in
only one frame. Now I have 2 classes and I don't know how to group them.
The JSlider.
public class JSliderExample extends JFrame {
JSlider jsHorizontal;
JTextField jtf1;
public JSliderExample() {
jsHorizontal = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
jtf1 = new JTextField(15);
jtf1.setEditable(false);
jtf1.setText("Horizontal value is " + jsHorizontal.getValue());
JPanel panel = new JPanel();
panel.setBackground(Color.WHITE);
panel.add(jsHorizontal);
panel.setBackground(Color.WHITE);
panel.add(jtf1);
panel.setBackground(Color.WHITE);
getContentPane().add(panel, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(300, 400, 400, 300);
setVisible(true);
setBackground(Color.WHITE);
}
class JSliderHandler implements ChangeListener {
public void stateChanged(ChangeEvent ce) {
jtf1.setText("value is " + jsHorizontal.getValue());
}
}
And there are my buttons
.
public void createGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
JButton button2 = new JButton("PLAY");
button2.setActionCommand("Button PLAY was pressed!");
panel.add(button2);
textField = new JTextField();
textField.setColumns(23);
panel.add(textField);
ActionListener actionListener = new TestActionListener();
button1.addActionListener(actionListener);
button2.addActionListener(actionListener);
button3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textField.setText(e.getActionCommand());
}
});
getContentPane().add(panel);
setPreferredSize(new Dimension(320, 100));
}
public class TestActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
textField.setText(e.getActionCommand());
}
}
In the end of programm I see 2 frames that consist of 2 classes.
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestFrame frame = new TestFrame();
frame.pack();
JSliderExample frame1 = new JSliderExample();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
If you don't want to see 2 JFrames, then don't create 2 JFrames. Why not make JPanels with all your classes above and not JFrames, and then in your main method, add your JPanels to the JFrame created within main. Simple.
So for example, instead of having JSliderExample extend JFrame, change it's name to SliderPanel and have it extend JPanel, and likewise with your JButton program. Then your main method could look something like:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// your JSlider example class **that extends JPanel**
SliderPanel sliderPanel = new SliderPanel();
// your JButton example class **that extends JPanel**
ButtonPanel buttonPanel = new ButtonPanel():
JFrame frame = new JFrame("My GUI");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(sliderPanel, BorderLayout.PAGE_START);
frame.add(buttonPanel, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null); // center GUI if you want
frame.setVisible(true);
}
});
}
For some reason the last added button does not get displayed. I tried reordering them but still the same result. I checked the coordinates and they are correct.
The last 3 is where I get the problem. The last "add" button doesn't get displayed.
public class MainScreen extends Frame implements MouseListener{
HowToPlay otherFrame;
Button start, howto, settings, about ;
Image MainMenu;
MainScreen(){
Toolkit tkMM = Toolkit.getDefaultToolkit();
MainMenu = tkMM.getImage(this.getClass().getResource("MainMenu.jpg"));
otherFrame = new HowToPlay();
Button start = new Button ("Start Game");
start.setBounds(98, 333, 326, 51);
Button howto = new Button ("How to Play");
howto.setBounds(98, 389, 326, 29);
howto.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
otherFrame.setVisible(true);
}
});
Button settings = new Button ("Settings");
settings.setBounds(98, 424, 326, 29);
Button about = new Button ("About");
about.setBounds(98, 462, 326, 29);
about.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
otherFrame.setVisible(true);
}
});
add(start);
add(howto);
add(settings);
add(about);
setVisible(true);
setSize(500, 500);
setResizable(false);
setLayout(null);
setLocationRelativeTo(null); // Center the frame
setSize(500,500);//size of the canvass
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e){
super.windowClosed(e);
System.exit(0);
}
});
}
Wow nice it worked. Still puzzled by the disappearing button problem though.
The default layout manager is a BorderLayout.
When you add components to a BorderLayout without specifying a constraint the component will be added to the CENTER. However, only one component can be added to the center, so the last one added (the "about" button) will be handled by the layout manager.
When you invoke the setVisible(true) method, the layout manager is invoked and the "about" button is given a size/location. All the other buttons are ignored because the BorderLayout doesn't care about them.
However, the size of the frame is (0, 0) so there is no space to allocate to the "about" button so it is given a height of 0, which effectively means there is nothing to paint.
So when the frame is painted the other 3 buttons a painted properly but not the "about" button.
Change the code to:
setSize(500, 500);
setVisible(true);
and see what happens.
Your problem is that you're calling setLayout(null); at the end after adding all components. To fix this, call it at the beginning:
MainScreen() {
setLayout(null);
Toolkit tkMM = Toolkit.getDefaultToolkit();
//.....
Having said that I strongly urge you to avoid use of null layouts and setBounds
e.g.
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.SwingUtilities;
public class MainScreen2 extends Panel {
private static final int PREF_W = 500;
private static final int PREF_H = 500;
public MainScreen2() {
Panel bottomPanel = new Panel(new GridLayout(0, 1));
bottomPanel.add(new Button("Start Game"));
bottomPanel.add(new Button("How To Play"));
bottomPanel.add(new Button("Settings"));
bottomPanel.add(new Button("About"));
setLayout(new BorderLayout());
add(bottomPanel, BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
Frame frame = new Frame("MainScreen2");
frame.add(new MainScreen2());
frame.pack();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
super.windowClosed(e);
System.exit(0);
}
});
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
The default layout manager for Frame is BorderLayout. When you use add(item) that item is placed in center, replacing anything that was there.
You need to use a different layout manager
I'm wanting the panel to expand and display buttons and stuff when the mouse is hovered over, then apon mouse exiting the panel must return top original size.
So far I can only print a message:
public JPanel GUI()
{
final JPanel totalGUI = new JPanel();
totalGUI.setBackground(Color.blue);
totalGUI.setLayout(null);
//+++++++++++++++
// - - - - - - PANEL 1!
//+++++++++++++++
JPanel SearchPanel = new JPanel(); //Create new grid bag layout
SearchPanel.setLocation(5, 5);
SearchPanel.setSize(420, 120);
totalGUI.add(SearchPanel);
SearchPanel.addMouseListener(this);
return totalGUI;
}
public void mouseEntered(MouseEvent e) {
System.out.print("Mouse entered");
}
public void mouseExited(MouseEvent e) {
System.out.print("Mouse exited");
}
private static void createAndShowGUI()
{
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("RWB");
gay3 demo = new gay3();
frame.setContentPane(demo.GUI());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setSize(650, 500);
frame.setVisible(true);
}
public static void main(String[] args)
{
createAndShowGUI();
}
You could do this inside the mouseEntered and mouseExited methods:
JPanel source = (JPanel)e.getSource();
//Edit the searchPanel here
If searchPanel isn't the only component that uses this MouseListener, you may first have to check if the source really is an instance of JPanel:
Object o = e.getSource();
if(o instanceof JPanel) {
JPanel source = (JPanel)o;
//Edit the searchPanel here
}
This isn't necessary if you know the source is a JPanel.
I'm having a problem with this. I have a JPanel and normally I would create a JLabel like this:
JLabel lblNewLabel = new JLabel("New label");
lblNewLabel.setBounds(0, 0, 135, 14);
panel.add(lblNewLabel);
but I want each time I click a button, in that panel to be created a new JLabel with the same size, but with a different height possition. I tried:
panel.add(new JLabel(stringName));
but this way I don't get to set it's bounds. stringName I get from a JTextField.
First off, use a layout. Done correctly the layout will place the components like you want. Secondly, when dynamically adding a component to a layout you need to tell the layout to update. Here is an example, it adds a label each time a button is pressed:
public static void main(String[] args) {
final JFrame frame = new JFrame("Test");
frame.setLayout(new GridLayout(0, 1));
frame.add(new JButton(new AbstractAction("Click to add") {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.add(new JLabel("Bla"));
frame.validate();
frame.repaint();
}
});
}
}));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
SwingUtilities.invokeLater(new Runnable() {
#Override public void run() {
frame.setVisible(true);
}
});
}
As said by #AndrewThompson use a correct LayoutManager, you should not be messing with setBounds etc.
Here is an example I made (Simply adds a JLabel to the JPanel each time the JButton is clicked):
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Test {
public Test() {
createAndShowUI();
}
private void createAndShowUI() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
initComponents(frame);
frame.setResizable(false);
frame.pack();
frame.setVisible(true);
}
private void initComponents(final JFrame frame) {
final JPanel panel = new JPanel();
JButton button = new JButton("Add label");
button.addActionListener(new ActionListener() {
int count = 1;
#Override
public void actionPerformed(ActionEvent e) {
JLabel _lbl = new JLabel("Label " + count);//make label and assign text in 1 line
panel.add(_lbl);//add label we made
panel.revalidate();
panel.repaint();
frame.pack();//so our frame resizes to compensate for new components
count++;
}
});
frame.add(panel, BorderLayout.CENTER);
frame.add(button, BorderLayout.SOUTH);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
Try swapping the order of of your commands, add the panel first then set the location.