This class represents the button panel of a UI I have created, the second JButton named 'btnNext' doesn't display text however the first JButton does, why is this?
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
public class ButtonPanel extends JPanel {
private MainPanel mainPanel;
// Buttons
private JButton btnRunTheAlgorithm = new JButton("Run the Algorithm");
public static JButton btnNext = new JButton("Next Step");
public ButtonPanel(MainPanel mainPanel) {
this.mainPanel = mainPanel;
this.setLayout(new FlowLayout());
this.add(btnRunTheAlgorithm);
this.add(btnNext);
this.btnRunTheAlgorithm.addActionListener(e -> {
Algorithm main = new Algorithm(mainPanel);
main.Run();
});
this.btnNext.setAction(new AbstractAction() {
public void actionPerformed(ActionEvent ae) {
synchronized (btnNext) {
btnNext.notify();
}
}
});
}
}
The buttons displays to the panel as on the image below:
Buttons:
I'm also not sure the AbstractAction works, so I suppose that could be the cause of the text not displaying but I have no idea why if that is the case.
Related
I'm trying to learn Java (not a programmer by profession).
I'm currently working on a calendar app with Postgres backend.
My app consists of a JFrame with two JPanels. One of those Panels is a CalendarView(MonthView, WeekView, or DayView), and the other a ButtonPanel.
The ButtonPanel has a button to add a new Event to the Calendar. This button opens a JDialog for entering Event details (startDate, endDate, title, etc).
The owner of the dialog is the JFrame. The dialog is modular.
The issues I have is that when the dialog is open, if I click on the parent window, the dialog disappears. If I then move the cursor outside the main application window and back in, the dialog reappears. I was under the impression that this should not happen with a modal component.
All feedback appreciated. I made a slimmed down SSCCE:
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import java.awt.*;
public class Calendar extends JFrame {
public Calendar() {
super("Calendar");
initGUI();
}
public void initGUI() {
JPanel calendarView = new JPanel();
calendarView.setPreferredSize(new Dimension(400, 400));
calendarView.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.BLACK), "Calendar view", TitledBorder.CENTER, TitledBorder.CENTER));
JPanel buttonPanel = new ButtonPanel();
buttonPanel.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.RED), "Button panel", TitledBorder.CENTER, TitledBorder.CENTER));
buttonPanel.setPreferredSize(new Dimension(200, 400));
this.getContentPane().add(calendarView, BorderLayout.CENTER);
this.getContentPane().add(buttonPanel, BorderLayout.WEST);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Calendar();
}
});
}
}
mport java.awt.*;
import java.awt.event.ActionListener;
import javax.swing.*;
public class ButtonPanel extends JPanel {
public ButtonPanel() {
initGui();
}
private void initGui() {
GridBagLayout gbag = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
this.setLayout(gbag);
JButton button = new JButton("Open dialog");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
new MyDialog((JFrame) ButtonPanel.this.getTopLevelAncestor());
}
});
gbag.setConstraints(button, gbc);
this.add(button);
}
}
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import java.awt.*;
public class MyDialog extends JDialog {
public MyDialog(JFrame owner) {
super(owner, "My dialog", true);
initGUI(owner);
}
private void initGUI(JFrame owner){
JOptionPane optionPane = new JOptionPane(createPanel(), JOptionPane.PLAIN_MESSAGE, JOptionPane.DEFAULT_OPTION, null, createButtons(), createButtons()[0]);
this.add(optionPane, BorderLayout.CENTER);
this.pack();
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.setLocationRelativeTo(owner);
this.setVisible(true);
}
private JPanel createPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createTitledBorder(new LineBorder(Color.BLACK), "My dialog", TitledBorder.CENTER, TitledBorder.CENTER));
return panel;
}
private JButton[] createButtons() {
JButton[] buttons = new JButton[1];
JButton button = new JButton("Exit");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event){
MyDialog.this.dispose();
}
});
buttons[0] = button;
return buttons;
}
}
So, I'm trying to make a basic functional menu for a simple game. I tried to do this by creating 2 JPanels, one for the actual game, and another for my menu.
What I'm trying to do is have a button on my Menu panel that when pressed, switches the JPanel being displayed in the parent JFrame from that of the menu to that of the actual game.
Here is my code:
class Menu extends JPanel
{
public Menu()
{
JButton startButton = new JButton("Start!");
startButton.addActionListener(new Listener());
add(startButton);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
Container container = getParent();
Container previous = container;
System.out.println(getParent());
while (container != null)
{
previous = container;
container = container.getParent();
}
previous.setContentPane(new GamePanel());
}
}
}
As you can see, I created a Listener for my start button. Inside the listener, I used a while loop to get to the JFrame, via the getParent() method. The program is getting the JFrame object, however it's not letting me call the setContentPane method...
Does anyone know how to get this to work, or a better way to switch back and forth between a menu and game?
Like so :
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class CardLayoutDemo extends JFrame {
public final String YELLOW_PAGE = "yellow page";
public final String RED_PAGE = "red page";
private final CardLayout cLayout;
private final JPanel mainPane;
boolean isRedPaneVisible;
public CardLayoutDemo(){
setTitle("Card Layout Demo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
mainPane = new JPanel();
mainPane.setPreferredSize(new Dimension(250,150));
cLayout = new CardLayout();
mainPane.setLayout(cLayout);
JPanel yellowPane = new JPanel();
yellowPane.setBackground(Color.YELLOW);
JPanel redPane = new JPanel();
redPane.setBackground(Color.RED);
mainPane.add(YELLOW_PAGE, yellowPane);
mainPane.add(RED_PAGE, redPane);
showRedPane();
JButton button = new JButton("Switch Panes");
button.addActionListener(e -> switchPanes() );
setLayout(new BorderLayout());
add(mainPane,BorderLayout.CENTER);
add(button,BorderLayout.SOUTH);
pack();
setVisible(true);
}
void switchPanes() {
if (isRedPaneVisible) {showYelloPane();}
else { showRedPane();}
}
void showRedPane() {
cLayout.show(mainPane, RED_PAGE);
isRedPaneVisible = true;
}
void showYelloPane() {
cLayout.show(mainPane, YELLOW_PAGE);
isRedPaneVisible = false;
}
public static void main(String[] args) {
new CardLayoutDemo();
}
}
I'm trying to make a program that can add name and address.
I'm trying to use the GridLayout but there is no buttons that shows up.
What did I do wrong here?
Thanks
Hello. I'm trying to make a program that can add name and address.
I'm trying to use the GridLayout but there is no buttons that shows up.
What did I do wrong here?
Thanks
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class AddressBookProgram extends JFrame {
public AddressBookProgram() {
super("Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new GridPanel());
setSize(300, 300);
setVisible(true);
}
private final class GridPanel extends JPanel {
private JPanel bookPanel;
private JPanel buttonPanel;
private JButton add;
private JButton delete;
private JButton search;
private JButton displayAll;
private JButton exit;
private ActionListener buttons = new ButtonListener();
private GridPanel() {
setLayout(new GridLayout(2, 3));
setBackground(Color.green);
bookPanel = new JPanel();
bookPanel.setBackground(Color.white);
buttonPanel = new JPanel();
buttonPanel.setBackground(Color.white);
add = new JButton("Add");
delete = new JButton("Delete");
search = new JButton("Search");
displayAll = new JButton("Display All");
exit = new JButton("Exit");
add.addActionListener(buttons);
delete.addActionListener(buttons);
search.addActionListener(buttons);
displayAll.addActionListener(buttons);
exit.addActionListener(buttons);
buttonPanel.add(add);
buttonPanel.add(delete);
buttonPanel.add(search);
buttonPanel.add(displayAll);
buttonPanel.add(exit);
}
private class ButtonListener implements ActionListener {
/**
* <p>Updates the watchLabel label when button is pushed.</p>
* #param event a button is pushed
*/
public void actionPerformed(ActionEvent event) {
if (event.getSource() == add) {
}
if (event.getSource() == delete) {
}
if (event.getSource() == search) {
}
if (event.getSource() == displayAll) {
}
if (event.getSource() == exit) {
}
}
}
}
public static void main(String[] args) {
new AddressBookProgram();
}
}
This is because you create buttonPanel but you don't add it. Just write this line:
add(buttonPanel);
This would make your code:
buttonPanel.add(add);
buttonPanel.add(delete);
buttonPanel.add(search);
buttonPanel.add(displayAll);
buttonPanel.add(exit);
add(buttonPanel);
I want to keep my Controller panel as type JPanel as I will be incorporating into a tab later, I want to swap between Main and NextPage using buttons on those specific screens, I don't want to have consistent buttons on the bottom for both screens that switch between cards(i.e I don't want to have add & back to be appearing on both screens), I am trying to get the add button in Main to go to NextPage and back button in NextPage to go to Main. This is what I have so far:
For Controller:
import java.awt.CardLayout;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Controller extends JPanel {
private static Controller instance = new Controller();
JPanel cards;
Main mainPanel;
NextPage nextPage;
public Controller() {
setLayout(new BorderLayout());
setSize(810, 510);
cards = new JPanel(new CardLayout());
mainPanel = new Main();
nextPage = new NextPage();
cards.add(mainPanel, "Main");
cards.add(nextPage, "Next");
add(cards);
setVisible(true);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("MainPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Controller con = new Controller();
frame.getContentPane().add(con);
frame.setSize(800, 600);
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public void changeCard(String card) {
CardLayout cl = (CardLayout) (cards.getLayout());
cl.show(cards, card);
}
public static Controller getInstance() {
return instance;
}
}
For main:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class Main extends JPanel implements ActionListener {
private JButton search, add, delete;
private JTextField textField;
public Main() {
search = new JButton("Search");
add = new JButton("Add");
delete = new JButton("Delete");
textField = new JTextField(20);
add.addActionListener(this);
delete.addActionListener(this);
setLayout(new BorderLayout());
JPanel top = new JPanel();
top.add(search);
add(top, BorderLayout.NORTH);
JPanel bottom = new JPanel();
bottom.add(add);
bottom.add(delete);
add(bottom, BorderLayout.SOUTH);
setVisible(true);
setSize(400, 500);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == add) {
Controller.getInstance().changeCard("Next");
} else if (e.getSource() == delete) {
System.out.println("do something");
}
}
}
For NextPage:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
public class NextPage extends JPanel implements ActionListener {
private JButton back;
private JTextField textField;
public NextPage() {
back = new JButton("Back");
textField = new JTextField(20);
back.addActionListener(this);
setLayout(new BorderLayout());
add(back);
setVisible(true);
setSize(400, 500);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == back) {
Controller.getInstance().changeCard("Next");
}
}
}
Check out Card Layout Actions.
It is an extension of CardLayout that provides you with Previous/Next buttons that you can easily add to a panel separate from the CardLayout.
I'd like to create a simple table game by Swing. I have a JFrame and a JPanel variable.
I want to add JButtons to this JPanel, but I'd like to create an own class.
I made a class that extends JButton (inheritence):
public class GameField extends JButton {...}
So I could add GameFields to the JPanel.
But I'd like to create GameFields by composition:
public class GameField{
private JButton button;
}
But in this clase how I can add GameField to JPanel?
Can I solve this problem by compisition?
But in this clase how I can add GameField to JPanel? Can I solve this
problem by compisition?
You do this by adding a simple getter like this:
public class GameField{
private JButton button;
public GameField(String text) {
button = new JButton(text);
// do your stuff here
}
public JButton getButton() {
return button;
}
}
Then in your GUI:
public void createAndShowGUI() {
JPanel panel = new JPanel(new GridLayout(5,5));
panel.add(new GameField("Button # 1").getButton());
panel.add(new GameField("Button # 2").getButton());
...
JFrame frame = new JFrame("Game");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
Edit
You've stated in a comment:
Thanks, but in this case if I'd like to access this field (i.e.
panel.getComponent(i)), I can get only a JButton, and not a GameField.
You can keep a list with your GameField objects or you can use putClientProperty() method to keep a reference to the GameField object as shown in the example below:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Demo {
private void createAndShowGUI() {
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource();
GameField gameField = (GameField)button.getClientProperty("GameField");
if(gameField != null) {
System.out.println(gameField.getText());
}
}
};
GameField gameField1 = new GameField("Button # 1");
gameField1.getButton().addActionListener(actionListener);
GameField gameField2 = new GameField("Button # 2");
gameField2.getButton().addActionListener(actionListener);
JPanel content = new JPanel(new GridLayout());
content.add(gameField1.getButton());
content.add(gameField2.getButton());
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class GameField {
private String text;
private JButton button;
public GameField(String text) {
this.text = text;
button = new JButton(text);
button.putClientProperty("GameField", GameField.this);
}
public JButton getButton() {
return button;
}
public String getText() {
return text;
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Demo().createAndShowGUI();
}
});
}
}
If you wish your GameField objects to have JComponents and still be able to add them to other JComponents, have them extend JPanel instead of JButton.
You can then have your GameField objects as JPanels with other JComponents and add them to your JFrame.