Adding buttons to JPanel after button click - java

Okay, so I am attempting to make a Flash cards program, and I want it to be that when the Add Set (or new deck of cards) is clicked, it will add a button to represent the set at the bottom of the frame.
What I have now will only show the button after the frame is resized. I don't really know what I'm doing with the panel, as I haven't figured out how to properly lay out all the parts yet.
I need the program to show the set icon in the bottom panel after the set it made.
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GraphicsUI extends JPanel {
private DeckList setsList;
CardActions action = new CardActions();
JButton addSetButton, addCardButton;
private JLabel label;
private JPanel bottomPanel;
public GraphicsUI(){
this.setPreferredSize(new Dimension(1000,825));
this.setBackground(Color.LIGHT_GRAY);
this.label = new JLabel();
label.setOpaque(true);
label.setBackground(Color.white);
label.setPreferredSize(new Dimension(600, 400));
ImageIcon img = new ImageIcon("setIcon.png");
//make that set image at bottom
this.addSetButton = new JButton("Add Set");
// this.addSetButton.setBackground(Color.white);
// this.addSetButton.setPreferredSize(new Dimension(240, 180));
this.add(addSetButton, BorderLayout.WEST);
this.addSetButton.addActionListener(new ButtonListener());
this.addCardButton = new JButton("Add Card");
// this.addCardButton
this.add(label);
JLabel blah = new JLabel();
blah.setPreferredSize(new Dimension(1000,30));
this.add(blah);
this.bottomPanel = new JPanel();
this.bottomPanel.setPreferredSize(new Dimension(1000, 400));
this.add(bottomPanel);
}
public class ButtonListener implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
action.setCommand(CardActions.Command.ADDSET);
action.setList(getSetInfo());
}
}
private CardList getSetInfo(){
CardList cl = new CardList();
String setName = JOptionPane.showInputDialog("Enter the name of your set.");
if(setName.isEmpty()){
JOptionPane.showMessageDialog(this, "Cannot have an empty set.");
}
cl.setSetName(setName);
ImageIcon img = new ImageIcon("setIcon.png");
bottomPanel.add(new JButton(img));
return cl;
}
}

Once you've added the button, try calling revalidate on the container to update the container hierarchy.
You may also find that the use of setPreferredSize may not be leaving enough room for the new button to appear

you should make a new jpanel that contains only buttons that will bring you to the specific set that the user has created. to update the jpanel just call repaint()

Related

How to close JDialog and save the setting ?

Hi I'm working on a program and I faced a problem when I choose some settings from JDialog then click "ok", which is that the setting didn't save but come back to the original settings.
PS : I'm not English speaker so maybe you observe some mistakes in my text above.
picture
enter image description here
class DrawingSettingWindow extends JDialog {
public DrawingSettingWindow() {
this.setTitle("Drawing Setting Window");
this.setSize(550, 550);
this.setLocationRelativeTo(null);
this.setModal(true);
this.setLayout(new GridLayout(4, 1));
JLabel selectColorText = new JLabel("Select Drawing Color");
colorsList = new JComboBox(colors);
JPanel panel1 = new JPanel();
panel1.add(selectColorText);
panel1.add(colorsList);
add(panel1);
JLabel selectStyleText = new JLabel("Select Drawing Style");
JPanel panel2 = new JPanel();
normal = new JRadioButton("Normal");
normal.setSelected(true);
filled = new JRadioButton("Filled");
ButtonGroup bg = new ButtonGroup();
bg.add(normal);
bg.add(filled);
panel2.add(selectStyleText);
panel2.add(normal);
panel2.add(filled);
add(panel2);
JButton ok = new JButton("OK");
add(ok);
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
this.pack();
this.setVisible(true);
}
The information is there, you just have to extract it from the dialog after the user is done using it. I would give the code above at least two new methods, one a public getColor() method that returns colorsList.getSelectedItem();, the color selection of the user (I'm not sure what type of object this is, so I can't show the method yet). Also another one that gets the user's filled setting, perhaps
public boolean getFilled() {
return filled.isSelected();
}
Since the dialog is modal, you'll know that the user has finished using it immediately after you set it visible in the calling code. And this is where you call the above methods to extract the data.
In the code below, I've shown this in this section: drawingSettings.setVisible(true);
// here you extract the data
Object color = drawingSettings.getColor();
boolean filled = drawingSettings.getFilled();
textArea.append("Color: " + color + "\n");
textArea.append("Filled: " + filled + "\n");
}
For example (see comments):
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
#SuppressWarnings("serial")
public class UseDrawingSettings extends JPanel {
private JTextArea textArea = new JTextArea(20, 40);
private DrawingSettingWindow drawingSettings;
public UseDrawingSettings() {
JPanel topPanel = new JPanel();
topPanel.add(new JButton(new ShowDrawSettings()));
setLayout(new BorderLayout());
add(new JScrollPane(textArea));
add(topPanel, BorderLayout.PAGE_START);
}
private class ShowDrawSettings extends AbstractAction {
public ShowDrawSettings() {
super("Get Drawing Settings");
}
#Override
public void actionPerformed(ActionEvent e) {
if (drawingSettings == null) {
Window win = SwingUtilities.getWindowAncestor(UseDrawingSettings.this);
drawingSettings = new DrawingSettingWindow(win);
}
drawingSettings.setVisible(true);
// here you extract the data
Object color = drawingSettings.getColor();
boolean filled = drawingSettings.getFilled();
textArea.append("Color: " + color + "\n");
textArea.append("Filled: " + filled + "\n");
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
UseDrawingSettings mainPanel = new UseDrawingSettings();
JFrame frame = new JFrame("UseDrawingSettings");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
#SuppressWarnings("serial")
class DrawingSettingWindow extends JDialog {
private static final String TITLE = "Drawing Setting Window";
private JComboBox<String> colorsList;
private JRadioButton normal;
private JRadioButton filled;
// not sure what colors is, but I'll make it a String array for testing
private String[] colors = {"Red", "Orange", "Yellow", "Green", "Blue"};
public DrawingSettingWindow(Window win) {
super(win, TITLE, ModalityType.APPLICATION_MODAL);
// this.setTitle("Drawing Setting Window");
this.setSize(550, 550); // !! this is not recommended
this.setLocationRelativeTo(null);
this.setModal(true);
this.setLayout(new GridLayout(4, 1));
JLabel selectColorText = new JLabel("Select Drawing Color");
colorsList = new JComboBox(colors);
JPanel panel1 = new JPanel();
panel1.add(selectColorText);
panel1.add(colorsList);
add(panel1);
JLabel selectStyleText = new JLabel("Select Drawing Style");
JPanel panel2 = new JPanel();
normal = new JRadioButton("Normal");
normal.setSelected(true);
filled = new JRadioButton("Filled");
ButtonGroup bg = new ButtonGroup();
bg.add(normal);
bg.add(filled);
panel2.add(selectStyleText);
panel2.add(normal);
panel2.add(filled);
add(panel2);
JButton ok = new JButton("OK");
add(ok);
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
});
this.pack();
// this.setVisible(true); // this should be the calling code's responsibility
}
public Object getColor() {
return colorsList.getSelectedItem();
}
public boolean getFilled() {
return filled.isSelected();
}
public static void main(String[] args) {
JFrame frame = new JFrame("Foo");
}
}
Side notes:
I've changed your class's constructor to accept a Window parameter, the base class for JFrame, JDialog, and such, and have added a call to the super's constructor. This way, the dialog is a true child window of the calling code (or you can pass in null if you want it not to be).
I recommend not making the dialog visible within its constructor. It is the calling code's responsibility for doing this, and there are instances where the calling code will wish to not make the dialog visible after creating it, for example if it wanted to attach a PropertyChangeListener to it before making it visible. This is most important for modal dialogs, but is just good programming practice.
I didn't know the type of objects held by your combo box, and so made an array of String for demonstration purposes.

add two JPanels to JFrame

I'm trying to add two JPanels to a Jframe, but it seems that they look like one. I'm trying tow stack them on top of each other like this image.
I thinking I may need to look at layout managers? I just need a little nudge in the right direction.
package projectTwo;
import javax.swing.*;
public class checkFrame
{
public static void main (String[] args)
{
JFrame frame = new JFrame("Compose Message");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
checkPanel bob = new checkPanel();
//frame.add(bob);
frame.getContentPane().add(bob);
frame.setResizable(false);
frame.setSize(750, 500);
frame.setVisible(true);
}
}
package projectTwo;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class checkPanel extends JPanel implements ActionListener
{
private JPanel entry, display;
private JLabel name, checkAmount, payOrderOf, numPrint, numWords;
private JTextField nameT, checkAmountT;
private JButton Submit;
public checkPanel()
{
entryComponents();
checkDisplay();
}
private void entryComponents(){
name = new JLabel("Name:");
checkAmount = new JLabel("Check Amount:");
nameT = new JTextField(20);
nameT.addActionListener(this);
checkAmountT = new JTextField(20);
checkAmountT.addActionListener(this);
Submit = new JButton("Submit");
Submit.addActionListener(this);
add(name);
add(nameT);
add(checkAmount);
add(checkAmountT);
add(Submit);
setPreferredSize(new Dimension(750, 75));
setBackground(new Color(200,200,200));
}
private void checkDisplay(){
payOrderOf = new JLabel("Pay to the Order of: ");
add(payOrderOf);
setBackground(new Color(220,255,225));
}
public void actionPerformed (ActionEvent event)
{
}
}
You should definitely take a look at layout managers. At the moment you are simply adding JPanels to each other without any specification on where they should be.
You have a few options in this case. You could use a GridLayout, but that leads to all the panels being the same size. If you just want two panels below each other, I would suggest using a BorderLayout. I've adjusted your code as follows:
public class checkPanel extends JPanel implements ActionListener
{
private JPanel entry, display;
private JLabel name, checkAmount, payOrderOf, numPrint, numWords;
private JTextField nameT, checkAmountT;
private JButton Submit;
public checkPanel()
{
this.setPreferredSize(new Dimension(750, 75));
entryComponents();
checkDisplay();
this.setLayout(new BorderLayout());
this.add(entry, BorderLayout.NORTH);
this.add(display, BorderLayout.CENTER);
}
private void entryComponents(){
entry = new JPanel();
// You should specify entry's layout as well FlowLayout are used by default
name = new JLabel("Name:");
checkAmount = new JLabel("Check Amount:");
nameT = new JTextField(20);
nameT.addActionListener(this);
checkAmountT = new JTextField(20);
checkAmountT.addActionListener(this);
Submit = new JButton("Submit");
Submit.addActionListener(this);
entry.add(name);
entry.add(nameT);
entry.add(checkAmount);
entry.add(checkAmountT);
entry.add(Submit);
entry.setBackground(new Color(200,200,200));
}
private void checkDisplay(){
display = new JPanel();
// You should specify display's layout as well FlowLayout are used by default
payOrderOf = new JLabel("Pay to the Order of: ");
display.add(payOrderOf);
display.setBackground(new Color(220,255,225));
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
It is in general a good idea to assign a layout to each JPanel you create. The choice of layout depends on how the panel should function.
using Gridbag Layout can help you a lot I would put a separator between panels as well

Want my JButton to return a previous area of text

I am trying to create a GUI that gives you hints when the program is opened. I am not sure how I am going to be able to add my text and then create buttons that allow me to go to the next text or return to the previous. I am not sure what type of actionListener I should use for that.
import java.awt.*;
import javax.swing.*;
public class HelpfulHints extends JFrame{
private JTextArea area; //This is my textarea to display hints
private JPanel panel;
private JButton close, previous, next; //Three buttons to operate program
public HelpfulHints(){
super("Tip of the Day");
setLayout(new BorderLayout());
panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.CENTER));
//Create first button
close= new JButton("Close");
add(close);
//Create second button
previous = new JButton("Previous");
add(previous);
//Create third button
next = new JButton("Next");
add(next);
//Add buttons to panel
panel.add(close);
panel.add(previous);
panel.add(next);
//Keep buttons to south of panel
add(panel, BorderLayout.SOUTH);
//Create ButtonHandler for button event handling
ButtonHandler handler = new ButtonHandler();
close.addActionListener(handler);
previous.addActionListener(handler);
next.addActionListener(handler);
//Create the helpful hint area on the screen
area = new JTextArea();
area.setEditable(true);
area.setLayout(new FlowLayout(FlowLayout.CENTER));
add(area, BorderLayout.CENTER);
setVisible(true);
}
//Inner class for button event handling
private class ButtonHandler implements ActionListener{
//handle Button event
#Override
public void actionPerformed(ActionEvent e){
}
}
}
I have updated the content of listener for your needs.
private JTextArea area; //This is my textarea to display hints
private JPanel panel;
private JButton close, previous, next; //Three buttons to operate program
private List<String> tips = new ArrayList<String>();
private int displayedTipIndex = 0;
public HelpfulHints(){
super("Tip of the Day");
// set up your tips
tips.add("First Tip");
tips.add("Second Tip");
tips.add("Third Tip");
// ... your other code stays the same...
//Create the helpful hint area on the screen
area = new JTextArea();
area.setEditable(true);
area.setLayout(new FlowLayout(FlowLayout.CENTER));
// set first tip
area.setText(tips.get(displayedTipIndex));
add(area, BorderLayout.CENTER);
// disable previous button when we start
previous.setEnabled(false);
//
setVisible(true);
}
//Inner class for button event handling
private class ButtonHandler implements ActionListener{
//handle Button event
#Override
public void actionPerformed(ActionEvent e){
if(e.getSource()==next){
displayedTipIndex++;
area.setText(tips.get(displayedTipIndex));
// disable the next button if no more tips
if(displayedTipIndex>=tips.size()-1){
next.setEnabled(false);
}
// re-enable previpous button
previous.setEnabled(true);
}
if(e.getSource()==previous){
displayedTipIndex--;
area.setText(tips.get(displayedTipIndex));
/// disable the previous button if no more tips
if(displayedTipIndex<0){
previous.setEnabled(false);
}
// re-enable next button
next.setEnabled(true);
}
if(e.getSource()==close){
System.exit(0);
}
}
}

Changing background color of a ContentPane

I'm working on a GUI and I'm not having some trouble with panes.
My GUI is divided into two parts (topPane and bottomPane).
I have buttons and labels on both panes, but one of the button functions I wanted to change the background color, but it's not doing the job.
What I did is that I used a Container (called thisContentPane) to change the background color of my entire GUI.
Here is my current code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class TempConverter extends JFrame
{
//Creating a contentPane down inside the inner class
Container thisContentPane;
//class scope variables : DO NOT CREATE THIS OBJECTS HERE.
JButton calculateButton, clearButton;
JTextField celsiusField, fahrenheitField, kelvinField;
//menu
JMenuBar menuBar = new JMenuBar();
JMenu backgroundColor = new JMenu("Background Color");
JMenu help = new JMenu("Help");
JMenuItem lightGray, white, black, blue, howToUse, about;
//constructor
TempConverter()
{
super("Temperature Converter App");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout());
this.setSize(400,200);;
this.setLocationRelativeTo(null);
//menuBar
this.setJMenuBar(menuBar);
menuBar.add(backgroundColor);
//adding JMenu to JMenuBar
menuBar.add(backgroundColor);
menuBar.add(help);
//adding JMenuItems
lightGray = backgroundColor.add("LIGHTGRAY");
white = backgroundColor.add("WHITE");
black = backgroundColor.add("BLACK");
blue = backgroundColor.add("BLUE");
howToUse = help.add("How To Use");
about = help.add("Help");
//babysitter
MaryPoppins babysitter = new MaryPoppins();
//adding action listener to the menu item
lightGray.addActionListener(babysitter);
white.addActionListener(babysitter);
black.addActionListener(babysitter);
blue.addActionListener(babysitter);
howToUse.addActionListener(babysitter);
about.addActionListener(babysitter);
//building JPanels
JPanel topPanel = new JPanel();
topPanel.setLayout(new GridLayout(3,2,0,20));
//add this to JFrame in centerzone
this.add(topPanel, BorderLayout.CENTER);
//bottom panel
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new FlowLayout());
//add this to JFrame in bottom
this.add(bottomPanel, BorderLayout.SOUTH);
//add components to the panels
//add the buttons
calculateButton = new JButton("Calculate");
clearButton = new JButton("Clear");
//add buttons
bottomPanel.add(calculateButton);
bottomPanel.add(clearButton);
//register listeners
calculateButton.addActionListener(babysitter);
clearButton.addActionListener(babysitter);
//add components to the top panel
JLabel labelOne = new JLabel("Celsius:");
JLabel secondOne = new JLabel("Fahrenheit:");
JLabel thirdOne = new JLabel("Kelvin:");
celsiusField = new JTextField("");
fahrenheitField = new JTextField("");
kelvinField = new JTextField("");
//add the label and text fields
topPanel.add(labelOne);
topPanel.add(celsiusField);
topPanel.add(secondOne);
topPanel.add(fahrenheitField);
topPanel.add(thirdOne);
topPanel.add(kelvinField);
this.setVisible(true);
} // end constructor
public static void main (String[] args) {
new TempConverter();
}
private class MaryPoppins implements ActionListener
{
//implement the abstract method from the interface
public void actionPerformed(ActionEvent ev)
{
thisContentPane = getContentPane();
if(ev.getActionCommand().equals("LIGHTGRAY"))
{
thisContentPane.setBackground(Color.lightGray);
}
else if (ev.getActionCommand().equals("BLUE"))
{
thisContentPane.setBackground(Color.BLUE);
}
else if(ev.getActionCommand().equals("WHITE") )
{
thisContentPane.setBackground(Color.WHITE);
}
else if (ev.getActionCommand().equals("BLACK"))
{
thisContentPane.setBackground(Color.BLACK);
}else if (ev.getActionCommand().equals("Clear"))
{
thisContentPane.setBackground(Color.BLACK);
}
else if (ev.getActionCommand().equals("BLACK"))
{
thisContentPane.setBackground(Color.BLACK);
}
}//end ActionPerformed()
}//end inner class
} // end class
When I click the buttons or menu items it doesn't do anything.
Your problem is that your contentPanel's background color is not "visible": your topPanel and your bottomPanel are on top of it :)
You should either do:
if (ev.getActionCommand().equals("LIGHTGRAY")) {
thisTopPanel.setBackground(Color.lightGray);
thisBottemPanel.setBackground(Color.lightGray);
}
... and do it for each of your if conditions (you know what I mean).
But that's not really the best way to go. An alternative that, in my opinion, makes perfect sense 'cause it reflects the exact behaviour you're looking for, would be:
topPanel.setOpaque(false);
bottomPanel.setOpaque(false);
I would obviously recommend the second option ;)
Also, since I'm at it, I prefer to use Color.LIGHTGRAY (and Color.BLACK, Color.WHITE, etc.) instead of Color.lightGrey, because these aliases respect the convention that states that constants must be upper-case.

Button Layout Issues with JFrame

Picture included I have another issue where my buttons go to the top-right after the user inputs their name. At this point, text shows up in the GUI on the LEFT side of the center which seems it would be "WEST" when I put "CENTER". Code:
public TheDungeon()
{
setTitle("InsertGameNameHere");
setSize(750, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
setLocationRelativeTo(null);
buildButtonPanel();
characterInfoPanel = new JLabel("<html>Character information will go here</html>");
gameScreen = new JLabel();
inventoryPanel = new JLabel("<html>This is for the inventory</html>");
add(gameScreen, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
setVisible(true);
//Program run
userName();
gameScreen.setText("<html>Welcome "+name+", to the game that has no name!</html>");
classWindow();
}
private void buildButtonPanel()
{
// Create a panel for the buttons.
buttonPanel = new JPanel();
// Create the buttons.
b1 = new JButton("Button 1");
b2 = new JButton("Button 2");
b3 = new JButton("Button 3");
b4 = new JButton("Button 4");
b5 = new JButton("Button 5");
// Add the buttons to the button panel.
buttonPanel.add(b1);
buttonPanel.add(b2);
buttonPanel.add(b3);
buttonPanel.add(b4);
buttonPanel.add(b5);
}
private void userName() {
name = JOptionPane.showInputDialog("What will your name be?");
}
I'm not sure why your program is behaving as it seems to be since when I ran it, it did not do this. You may wish to check your code to make sure that it's the code you're posting here. But regardless, I do have some suggestions:
Best to not set the sizes of anything, but rather to let the components and the layout managers do this for you.
Consider if you must overriding getPreferredSize() if you need to control the size of a component more fully.
Call pack() on your top level window after adding all components and before calling setVisible(true). This will tell the layout managers to do their things.
Avoid extending JFrame since you will rarely need to override one of its innate behaviors.
If you do add or remove components, or change their preferredSizes somehow after rendering your top-level window, you will want to call revalidate() and then repaint() on the component's container to have the container re-layout the components it holds and then redraw them.
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.*;
public class TheDungeon2 extends JPanel {
private static final int PREF_W = 750;
private static final int PREF_H = 600;
private static final String[] BUTTON_LABELS = {"Button 1", "Button 2",
"Button 3", "Button 4", "Button 5"};
private static final String WELCOME_TEXT = "Welcome %s to the game that has no name!";
private JLabel welcomeLabel = new JLabel("", SwingConstants.CENTER);
private String name;
public TheDungeon2() {
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
for (String buttonLabel : BUTTON_LABELS) {
JButton button = new JButton(buttonLabel);
buttonPanel.add(button);
}
setLayout(new BorderLayout());
add(welcomeLabel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void getAndSetName() {
name = JOptionPane.showInputDialog(this, "What will your name be?");
welcomeLabel.setText(String.format(WELCOME_TEXT, name));
}
private static void createAndShowGui() {
TheDungeon2 dungeon2 = new TheDungeon2();
JFrame frame = new JFrame("Nameless Game");
dungeon2.getAndSetName();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(dungeon2);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I tested your code with an empty classWindow() method and the buttons are correctly placed in south,
for the CENTER issue, you should place something in WEST to have your text centred (even an empty panel) otherwise CENTER will take all the place,
look at this , i added this line :
add(new JButton("a button for test"),BorderLayout.WEST);
and here is the result :

Categories

Resources