I have a JPanel in a JFrame that contains 5 buttons. In another JPanel there is a button called "delete button", what I want to do is to click this button and than choose what button of the other 5 to delete by ckicking in one of them. Can anyone help me?
public class gui extends JFrame implements ActionListener
{
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p2 = new JPanel();
JButton b1 = new JButton("Delete");
JButton b2 = new JButton("A");
JButton b3 = new JButton("B");
JButton b4 = new JButton("C");
gui()
{
p1.setLayout(new GridLayout(1,2));
p1.add(p2);
p1.add(p3);
p2.setLayout(new GridLayout(3,1));
p2.add(b2);
p2.add(b3);
p2.add(b4);
p3.add(b1);
b1.addActionListener(this);
b2.addActionListener(this);
b3.addActionListener(this);
b4.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == b1)
// When I click this button I want to be able to delete a button of my choice (one of the other 3)
}
}
Use a chain of responsibility in the button listeners. One Button listener that listens for the "to be deleted" buttons and the "delete" button. Under normal operation this button listener just sends the "to be deleted" button events to the existing button events, but when it hears a "delete" button event, it then captures the "next" button event without sending it to the existing button listener, and acts to remove the button.
Ok you provided some code. Here is a solution that uses a chain of responsibility. Basically, if one ActionListener can't handle the event, it sends it to the next one, and so on.
import java.awt.GridLayou;
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.WindowConstants;
public class Gui extends JFrame {
public static final long serialVersionUID = 1L;
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
JButton b1 = new JButton("Delete");
JButton b2 = new JButton("A");
JButton b3 = new JButton("B");
JButton b4 = new JButton("C");
public Gui() {
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
p1.setLayout(new GridLayout(1, 2));
p1.add(p2);
p2.add(p3);
p2.setLayout(new GridLayout(3, 1));
p2.add(b2);
p2.add(b3);
p2.add(b4);
p3.add(b1);
DoItListener doIt = new DoItListener(null);
DeleteItListener deleteIt = new DeleteItListener(this, doIt);
b1.addActionListener(deleteIt);
b2.addActionListener(deleteIt);
b3.addActionListener(deleteIt);
b4.addActionListener(deleteIt);
add(p1);
pack();
}
public void deleteButton(String name) {
if (b2 != null && "A".equals(name)) {
p2.remove(b2);
b2 = null;
p2.invalidate();
p2.redraw();
}
if (b3 != null && "B".equals(name)) {
p2.remove(b3);
b3 = null;
p2.invalidate();
p2.redraw();
}
if (b4 != null && "A".equals(name)) {
p2.remove(b4);
b4 = null;
p2.invalidate();
p2.redraw();
}
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Gui().setVisible(true);
}
});
}
}
class DoItListener implements ActionListener {
private ActionListener delegate;
public DoItListener(ActionListener next) {
delegate = next;
}
public void actionPerformed(ActionEvent e) {
if (!("Delete".equals(e.getActionCommand()))) {
System.out.println("doing " + e.getActionCommand());
} else if (delegate != null) {
delegate.actionPerformed(e);
}
}
}
class DeleteItListener implements ActionListener {
private Gui gui;
private boolean deleteNext;
private ActionListener delegate;
public DeleteItListener(Gui container, ActionListener next) {
gui = container;
delegate = next;
deleteNext = false;
}
public void actionPerformed(ActionEvent e) {
if ("Delete".equals(e.getActionCommand())) {
deleteNext = true;
} else if (deleteNext) {
gui.deleteButton(e.getActionCommand());
deleteNext = false;
} else if (delegate != null) {
delegate.actionPerformed(e);
}
}
}
Here try this code out :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DeleteButtonExample extends JFrame
{
private boolean deleteNow = false;
private JButton deleteButton;
private JPanel leftPanel;
private JPanel rightPanel;
private JButton[] buttons = new JButton[5];
private ActionListener deleteAction = new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
JButton button = (JButton) ae.getSource();
if (deleteNow)
{
leftPanel.remove(button);
leftPanel.revalidate();
leftPanel.repaint();
deleteNow = false;
}
else
{
// Do your normal Event Handling here.
System.out.println("My COMMAND IS : " + button.getActionCommand());
}
}
};
private void createAndDisplayGUI()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationByPlatform(true);
setLayout(new GridLayout(0, 2));
leftPanel = new JPanel();
leftPanel.setLayout(new GridLayout(0, 2));
leftPanel.setBackground(Color.WHITE);
for (int i = 0; i < 5; i++)
{
buttons[i] = new JButton("" + i);
buttons[i].addActionListener(deleteAction);
buttons[i].setActionCommand("" + i);
leftPanel.add(buttons[i]);
}
rightPanel = new JPanel();
rightPanel.setBackground(Color.BLUE);
JButton deleteButton = new JButton("DELETE");
deleteButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
JOptionPane.showMessageDialog(null, "Delete any Button from the Left Panel by clicking it."
, "INFO : ", JOptionPane.INFORMATION_MESSAGE);
deleteNow = true;
}
});
rightPanel.add(deleteButton);
add(leftPanel);
add(rightPanel);
pack();
setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new DeleteButtonExample().createAndDisplayGUI();
}
});
}
}
OUTPUT :
, ,
Here's a snippet of code to kick you off in the right direction:
import java.awt.event.ActionEvent;
import javax.swing.*;
public class FrameTestBase extends JFrame {
public static void main(String args[]) {
FrameTestBase t = new FrameTestBase();
final JPanel p = new JPanel();
final JButton button = new JButton();
button.setAction(new AbstractAction("Remove me!") {
#Override
public void actionPerformed(ActionEvent e) {
p.remove(button);
p.revalidate();
p.repaint();
}
});
p.add(button);
t.setContentPane(p);
t.setDefaultCloseOperation(EXIT_ON_CLOSE);
t.setSize(400, 400);
t.setVisible(true);
}
}
Before click:
After click:
From the comments:
To generalize this, you could create an AbstractAction that takes the to-be-deleted button as argument. Use this AbstractAction, and update it as necessary whenever your delete-policy should change.
Have a look at the glass pane. This tutorial shows how it is used.
At a high level, clicking the 'Delete' button would put the glass pane listener into a state where it:
detects a click,
determines the target component,
determines whether the component is allowed to be deleted
and if so, delete the component.
As a design note, I would keep a Set of controls that are allowed to be deleted, and thereby separate the concerns. So when you add a button that is allowed to be deleted, it is your responsibility to also add it to the delete candidates set.
The easiest method:
Add an ActionListener to the button that will remove another one;
Repaint and revalidate the panel where is the button to remove.
Example (in this case the button that will delete another one is called by "deleteBtn" and the button in the another panel that will be removed is called by "btnToDlt" that exists in the "panel"):
deleteBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.remove(btnToDlt);
panel.revalidate();
panel.repaint();
}
});
Related
I'm trying to do a call simulator in Swing and for some reason the window won't budge.
My goal is to open a seperate window that returns true or false if a button is pressed or another has been pressed. The user should have 15 seconds to do something, otherwise it returns false and performs an action.
When it returns, it should finish it's execution. This function is called by another function part of main.
However, due to my lack of experience and idiocy, it doesn't work. Instead, it opens a window (blank) that never closes by itself when it should...
Here's the code:
public static boolean callWindow(Telephone src, Telephone dst) {
Timer t1 = new Timer(15000, e-> {
DateTime date = new DateTime();
Call c = new Call(date, src.getTelephone(), dst.getTelephone(), 0);
dst.addLostCall(c);
});
//Janela para atender
JFrame window = new JFrame();
window.setTitle("Incoming Call");
JLabel telephones = new JLabel();
telephones.setText("From: " + src.getTelephone() + " To: " + dst.getTelephone() );
JButton answerCall = new JButton("Answer");
JButton denyCall = new JButton("Decline");
JLabel status = new JLabel();
answerCall.addActionListener( e -> status.setText("answer") );
denyCall.addActionListener( e -> status.setText("no answer") );
answerCall.setBackground(Color.GREEN);
denyCall.setBackground(Color.RED);
JPanel callInfo = new JPanel();
callInfo.add(telephones);
JPanel callOptions = new JPanel();
callOptions.add(answerCall);
callOptions.add(denyCall);
Container container = window.getContentPane();
container.add(callInfo, BorderLayout.NORTH);
container.add(callOptions);
window.setSize(350,120);
window.setVisible(true);
t1.start();
while (t1.isRunning()) {
if (status.getText().equals("answer")) return true;
if (status.getText().equals("no answer")) return false;
}
return false;
}
I would appreciate to know how this could work and how to despaghettify this horrible code.
I used a JDialog to demonstrate how to close a window after 15 seconds.
Here's the GUI JFrame I created.
Here's the JDialog I created
The JDialog will dispose after 15 seconds. The isAnswered method will return true if the call was answered or false if the call was declined, the JDialog was closed by left-clicking on the X, or when the 15 seconds runs out.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class JDialogTimedGUI implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new JDialogTimedGUI());
}
private JFrame frame;
#Override
public void run() {
frame = new JFrame("JDialog Timed GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(
75, 100, 75, 100));
panel.setPreferredSize(new Dimension(400, 200));
JButton button = new JButton("Open JDialog");
button.addActionListener(new ButtonListener());
panel.add(button);
return panel;
}
public class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
IncomingCall ic = new IncomingCall(frame, "Incoming Call",
"555-1212", "555-2323");
System.out.println("Incoming call: " + ic.isAnswered());
}
}
public class IncomingCall extends JDialog {
private static final long serialVersionUID = 1L;
private boolean answered;
private Timer timer;
public IncomingCall(JFrame frame, String title,
String sourcePhone, String destinationPhone) {
super(frame, true);
this.answered = false;
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle(title);
add(createMainPanel(frame, sourcePhone, destinationPhone));
pack();
setLocationRelativeTo(frame);
timer = new Timer(15000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
setVisible(false);
dispose();
timer.stop();
}
});
timer.start();
setVisible(true);
}
private JPanel createMainPanel(JFrame frame,
String sourcePhone, String destinationPhone) {
JPanel panel = new JPanel(new BorderLayout(5, 5));
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
String s = "From: " + sourcePhone + " To: " + destinationPhone;
JLabel telephones = new JLabel(s);
panel.add(telephones, BorderLayout.BEFORE_FIRST_LINE);
JPanel callOptions = new JPanel();
CallButtonListener listener = new CallButtonListener(this);
JButton answerCall = new JButton("Answer");
answerCall.addActionListener(listener);
answerCall.setBackground(Color.GREEN);
callOptions.add(answerCall);
JButton denyCall = new JButton("Decline");
denyCall.addActionListener(listener);
denyCall.setBackground(Color.RED);
callOptions.add(denyCall);
panel.add(callOptions, BorderLayout.CENTER);
return panel;
}
public void setAnswered(boolean answered) {
this.answered = answered;
}
public boolean isAnswered() {
return answered;
}
}
public class CallButtonListener implements ActionListener {
private IncomingCall incomingCall;
public CallButtonListener(IncomingCall incomingCall) {
this.incomingCall = incomingCall;
}
#Override
public void actionPerformed(ActionEvent event) {
JButton button = (JButton) event.getSource();
if (button.getText().equals("Answer")) {
incomingCall.setAnswered(true);
} else {
incomingCall.setAnswered(false);
}
incomingCall.dispose();
}
}
}
I'm having trouble with the functionality of dispose for my checkerboard (called Checkers) . For each checkerboard that I have, i want to be able to remove it by using dispose before calling another instance of my interface. Here is my progress so far:
Checkers class:
import java.awt.*;
import javax.swing.*;
import java.awt.Color.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.Random;
public class Checkers extends JFrame
{
Random random = new Random();
private final int ROWS = 2;
private final int COLS = 5;
private final int GAP = 2;
private final int NUM = ROWS * COLS;
private int i;
public int score;
private JPanel pane = new JPanel(new GridLayout(ROWS,COLS, GAP,GAP));
private JPanel pane2 = new JPanel();
private JPanel pane3 = new JPanel();
private JButton btn1 = new JButton("Play A Game");
private JButton btn2 = new JButton("Exit");
private JButton btn3 = new JButton("Easy");
private JButton btn4 = new JButton("Intermediate");
private JButton btn5 = new JButton("Difficult");
private JLabel lbl1 = new JLabel ("score: " + score);
private JLabel gameLost = new JLabel("You lose! You got: " + score + " points");
private MyPanel [] panel = new MyPanel[NUM];
private Color col1 = Color.RED;
private Color col2 = Color.WHITE;
private Color col3 = Color.GREEN;
private Color tempColor;
public Checkers()
{
super("Checkers");
setSize(600,600);
setVisible(true);
setBackground(Color.BLACK);
setBoard();
}
public void setBoard()
// roates colors on the checkbaord
{
for (int i = 0; i < panel.length; i++) {
panel[i] = new MyPanel(this);
pane.add(panel[i]);
if (i % COLS == 0) {
tempColor = col1;
col1 = col2;
col2 = tempColor;}
if (i % 2 == 0) {
panel[i].setBackground(col1);}
else {
panel[i].setBackground(col2);}
}
//pane background colour and the size of this pane.
pane.setBackground(Color.BLACK);
pane.setPreferredSize(new Dimension(300,300));
//pane background colour and size of this pane.
pane2.setBackground(Color.white);
pane2.setPreferredSize(new Dimension(300,300));
//directions on the board where these panes appear.
add(pane, BorderLayout.WEST);
add(pane2, BorderLayout.EAST);
pane2.add(lbl1);
pane2.setLayout(new BoxLayout(pane2, BoxLayout.PAGE_AXIS));
}
public void incrementScore(){
score++;
lbl1.setText("Score: " + Integer.toString(score));
}
//This is the method for resetting via dispose - only works once.
public void restartBoard(){
this.dispose();
new Checkers();
}
}
And also the MyPanel class
public class MyPanel extends JPanel implements MouseListener {
private final Checkers checkers;
public MyPanel(Checkers checkers) {
this.checkers = checkers;
addMouseListener(this);
}
#Override
public void mouseClicked(MouseEvent e) {
setBackground(Color.BLACK);
checkers.incrementScore();
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
}
EXPECTED RESULT - What i'd like to do is be able to close the current version of interface by using the dispose method, and then opening a new instance of said interface.
ACTUAL RESULT - When opening an interface, then calling dispose method, it will work once. once you try to remove the 2nd interface when creating a 3rd interface, dispose will not function, and I cant see why this is.
Any help is welcome.
For what it's worth, this is an MCVE that shows your likely problem:
import java.awt.Dimension;
import javax.swing.*;
public class CheckersTest {
private static void createAndShowGui() {
Checkers checkers = new Checkers();
JButton restartButton = new JButton("Restart");
restartButton.addActionListener(event -> checkers.restartBoard());
JPanel restartPanel = new JPanel();
restartPanel.setPreferredSize(new Dimension(400, 400));
restartPanel.add(restartButton);
JFrame frame = new JFrame("Checkers Test");
frame.add(restartPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class Checkers extends JFrame {
public Checkers() {
setPreferredSize(new Dimension(200, 200));
pack();
setLocationByPlatform(true);
setVisible(true);
}
public void restartBoard(){
this.dispose();
new Checkers();
}
}
The restart button refers to the original Checkers instance and so will not close any new instances created. The solution would be to get the restart method out of Checkers, create a Checkers field, and make sure the restart method refers to the visible Checkers instance:
import java.awt.Dimension;
import javax.swing.*;
public class CheckersTest {
private static Checkers checkers = new Checkers(); // holds reference
private static void restartBoard() {
if (checkers != null) {
checkers.dispose();
checkers = new Checkers(); // assign to reference field
}
}
private static void createAndShowGui() {
// !! Checkers checkers = new Checkers();
JButton restartButton = new JButton("Restart");
// !! restartButton.addActionListener(event -> checkers.restartBoard());
restartButton.addActionListener(event -> restartBoard());
JPanel restartPanel = new JPanel();
restartPanel.setPreferredSize(new Dimension(400, 400));
restartPanel.add(restartButton);
JFrame frame = new JFrame("Checkers Test");
frame.add(restartPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class Checkers extends JFrame {
public Checkers() {
setPreferredSize(new Dimension(200, 200));
pack();
setLocationByPlatform(true);
setVisible(true);
}
}
Notes:
Again a much better design is not to swap JFrames but rather JPanel views
Note that the MCVE has code that reproduces the problem but avoids code not related to the problem. So it shows the restartBoard method, it compiles, but avoids game code since this is not relevant to the problem.
I am dynamically adding items to my JPanel through an ArrayList<Items>. Basically the items object looks like that:
public class Item {
private JComponent component;
private String functionality;
public Item(JComponent component, String functionality) {
super();
this.component = component;
this.functionality = functionality;
}
public JComponent getComponent() {
return component;
}
public void setComponent(JComponent component) {
this.component = component;
}
public String getFunctionality() {
return functionality;
}
public void setFunctionality(String functionality) {
this.functionality = functionality;
}
}
Here I am adding my buttons dynamically: (try the example out if you want)
public class minimumExample extends JFrame {
private JButton addItem;
private JComboBox itemBox;
private String[] itemSelect = { "test1", "test2" };
private JPanel addUpperPane;
private JPanel addLowerPane;
private ArrayList<Item> displayedItems = new ArrayList<Item>();
private JButton upButton;
private JButton downButton;
private JButton deleteButton;
public void createControlPane() {
addUpperPane = new JPanel();
addLowerPane = new JPanel(new GridLayout(0, 1));
addItem = new JButton("Add item");
upButton = new JButton("Up");
downButton = new JButton("Down");
deleteButton = new JButton("Delete");
itemBox = new JComboBox(itemSelect);
addItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(itemBox.getSelectedItem().toString().equals("test1")) {
displayedItems.add(new Item( new ButtonComp().butt(), "test1"));
validate();
repaint();
}
if(itemBox.getSelectedItem().toString().equals("test2")) {
displayedItems.add(new Item( new LabelComp().label(), "test2"));
validate();
repaint();
}
for (int i = 0; i < displayedItems.size(); i++) {
addLowerPane.add(displayedItems.get(i).getComponent());
validate();
repaint();
}
}
});
addUpperPane.add(itemBox, BorderLayout.EAST);
addUpperPane.add(addItem, BorderLayout.WEST);
addUpperPane.add(new JLabel(" | "), BorderLayout.WEST);
addUpperPane.add(upButton, BorderLayout.WEST);
addUpperPane.add(downButton, BorderLayout.WEST);
addUpperPane.add(deleteButton, BorderLayout.WEST);
addUpperPane.add(new JSeparator(JSeparator.HORIZONTAL));
//put everything together
add(addUpperPane, BorderLayout.NORTH);
add(addLowerPane, BorderLayout.SOUTH);
repaint();
}
private void makeLayout() {
setTitle("Test App");
setLayout(new BorderLayout());
setPreferredSize(new Dimension(1000, 500));
createControlPane();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
/**
* starts the GUI
*/
public void start() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
makeLayout();
}
});
}
public static void main(String[] args) throws IOException {
minimumExample ex = new minimumExample();
ex.start();
}
public class ButtonComp extends Component {
public JPanel butt() {
JPanel panel = new JPanel();
JButton button = new JButton("Test1");
JCheckBox check = new JCheckBox();
panel.add(button);
panel.add(check);
return panel;
}
}
public class LabelComp extends Component {
public JPanel label() {
JPanel panel = new JPanel();
JLabel label = new JLabel("Test2");
JCheckBox check = new JCheckBox();
panel.add(label);
panel.add(check);
return panel;
}
}
}
The program basically looks like that:
My problem is that the buttons Up, Down and Delete do not work, because I do not know how to get the selected element from the pane to delete it from the list where all components are in. Any recommendations on how to make this work?
I really appreciate your answer!
UPDATE
I changed my code your specifications #cghislai but it does not work. Try it out yourself:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
public class minimumExample extends JFrame {
private JButton addItem;
private JComboBox itemBox;
private String[] itemSelect = { "test1", "test2" };
private JPanel addUpperPane;
private JPanel addLowerPane;
private List<CheckableItem> displayedItems = new ArrayList<CheckableItem>();
private JButton upButton;
private JButton downButton;
private JButton deleteButton;
public void createControlPane() {
addUpperPane = new JPanel();
addLowerPane = new JPanel(new GridLayout(0, 1));
addItem = new JButton("Add item");
upButton = new JButton("Up");
downButton = new JButton("Down");
deleteButton = new JButton("Delete");
itemBox = new JComboBox(itemSelect);
addItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(itemBox.getSelectedItem().toString().equals("test1")) {
ButtonComp butt = new ButtonComp();
butt.init();
displayedItems.add(butt);
validate();
repaint();
}
if(itemBox.getSelectedItem().toString().equals("test2")) {
// displayedItems.add(new CopyOfItem( new LabelComp(), "test2"));
validate();
repaint();
}
for (int i = 0; i < displayedItems.size(); i++) {
addLowerPane.add(displayedItems.get(i).getComponent());
validate();
repaint();
}
}
});
deleteButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
Iterator<CheckableItem> it = displayedItems.iterator();
while (it.hasNext()) {
CheckableItem next = it.next();
if (next.isSelected()) {
addLowerPane.remove(next.getComponent());
it.remove();
continue;
}
}
}
});
addUpperPane.add(itemBox, BorderLayout.EAST);
addUpperPane.add(addItem, BorderLayout.WEST);
addUpperPane.add(new JLabel(" | "), BorderLayout.WEST);
addUpperPane.add(upButton, BorderLayout.WEST);
addUpperPane.add(downButton, BorderLayout.WEST);
addUpperPane.add(deleteButton, BorderLayout.WEST);
addUpperPane.add(new JSeparator(JSeparator.HORIZONTAL));
//put everything together
add(addUpperPane, BorderLayout.NORTH);
add(addLowerPane, BorderLayout.SOUTH);
repaint();
}
private void makeLayout() {
setTitle("Test App");
setLayout(new BorderLayout());
setPreferredSize(new Dimension(1000, 500));
createControlPane();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
/**
* starts the GUI
*/
public void start() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
makeLayout();
}
});
}
public static void main(String[] args) throws IOException {
minimumExample ex = new minimumExample();
ex.start();
}
public abstract class CheckableItem {
protected JCheckBox check;
public boolean isSelected() {
return check.isSelected();
}
public abstract Component getComponent();
}
public class ButtonComp extends CheckableItem {
JPanel panel = new JPanel();
public void init() {
JButton button = new JButton("Test1");
check = new JCheckBox();
panel.add(button);
panel.add(check);
}
#Override
public Component getComponent() {
return panel;
}
}
public class LabelComp extends JPanel {
public void label() {
// JPanel panel = new JPanel();
JLabel label = new JLabel("Test2");
JCheckBox check = new JCheckBox();
add(label);
add(check);
}
}
}
You need to traverse all your items, check if the item checkbox is selected, if this is the case, remove your item from the panel. I would make an abstract CheckableItem class with a getter to the JCheckbox and the Component. Then, for each of you item, if the checkbox is selected, remove the component from the parent.
public abstract class CheckableItem {
protected JCheckbox checkbox;
public boolean isSelected() {
return checkbox.isSelected();
}
public abstract Component getComponent();
}
public class ButtonComp extends CheckableItem {
private Panel panel;
public void init() {
checkbox = new JCheckbox;
panel = new JPanel();
panel.add(new JButton());
panel.add(checkbox);
}
public Component getComponent() {
return panel;
}
}
Then to keep track of your items:
private List<CheckableItem> items = new ArrayList<>();
// ...
ButtonComp comp = new ButtonComp();
comp.init();
items.add(comp);
Then to remove all checked:
Iterator<CheckbleItem> it = items.iterator();
while (it.hasNext()) {
CheckableItem next = it.next();
if (next.isSelected()) {
mainPanel.remove(next.getComponent());
it.remove();
continue;
}
}
Why don't you just have your ButtomComp and LabelComp extend from JPanel? This would solve a lot of your problems I think. For example :
public class ButtonComp extends JPanel {
JButton button;
JCheckBox check = new JCheckBox();
public ButtonComp() {
button = new JButton("Test1");
this.add(button);
this.add(check);
}
}
Then all you would need to do is iterate over your items and look at the checkbox in the components :
for (int i = 0; i < displayedItems.size(); i++) {
if (displayedItems.get(i).check.isSelected()) {
displayedItems.remove(i);
}
}
Note: haven't tested this code. But you should get the idea.
I'm trying to write a Tic Tac Toe program using swing, but I seem to having some trouble. In my anonymous inner classes I attempt to set up the actionListener for each of my buttons, but I'm having trouble finding the type or the variable which will allow me to reference the buttons and set them to either X or Y. I tried e.getSource().setText() in my anonymous classes, but that came back with errors. Any thoughts?
Thanks!
Alex
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TicTacToe {
public JFrame frame;
public JLabel label;
public JPanel panel;
public static int counter;
public void go()
{
frame = new JFrame("TicTacToe");
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setLayout(new GridLayout(3,3,10,10));
frame.add(BorderLayout.CENTER, panel);
label= new JLabel("TIC TAC TOE");
frame.add(BorderLayout.NORTH, label);
;
JButton button1 = new JButton("Button 1");
JButton button2 = new JButton("Button 1");
JButton button3 = new JButton("Button 1");
JButton button4 = new JButton("Button 1");
JButton button5 = new JButton("Button 1");
JButton button6 = new JButton("Button 1");
JButton button7 = new JButton("Button 1");
JButton button8 = new JButton("Button 1");
JButton button9 = new JButton("Button 1");
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
}
});
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button7.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button8.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
button9.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
}
});
panel.add(button1);
panel.add(button2);
panel.add(button3);
panel.add(button4);
panel.add(button5);
panel.add(button6);
panel.add(button7);
panel.add(button8);
panel.add(button9);
frame.setVisible(true);
panel.setVisible(true);
}
public static void main(String[] args)
{
TicTacToe gui = new TicTacToe();
gui.go();
}
}
Remember, ActionListener can be used on a number of different types of components, so the source reference is generalized. You need to cast to back to the expected value
button9.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
if (source instanceof JButton) {
JButton btn = (JButton)source;
// Go ahead and do what you like
}
}
});
While I know your ActionListener as it stands can pretty much guarantee that the source type of the Object will be a JButton, I never like blindly casting objects, but that's me
If you are receiving errors then you should post them but I am assuming it is because you aren't asserting that the source object is in fact a button. There are two straightforward solutions to what you are doing.
First is that since you are only adding one action listener to each button, you can assume that it is the object that the action event is referring to. Just note that the button either needs to be an instance variable or declared final:
button1.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
button1.setText("X/Y");
}
});
Second, which would fix the cause of your error, is by asserting that the ActionEvent source object is in fact a button. This is done by checking that the source is an instance of JButton:
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JButton) {
((JButton) e.getSource()).setText("X/Y");
}
}
});
I went through and cleaned up your code a little bit. I'm not quite sure why your code had errors, but I didn't get any. I suggest, since you have common code, to reuse it like I did in an array. I also added a boolean to switch between players on each button click.
Lastly, I suggest setting up the JFrame in the constructor, or in a private method called by the constructor (more complex user interfaces might have a lot of code, and breaking it up is a good habit for maintainability of your code) like I showed below.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TicTacToe {
public static final boolean PLAYER_X = false;
public static final boolean PLAYER_O = true;
public static int counter;
private JFrame frame;
private JLabel label;
private JPanel panel;
private JButton[] buttons;
private boolean player;
public TicTacToe() {
frame = new JFrame("TicTacToe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
panel.setPreferredSize(new Dimension(500, 500));
panel.setLayout(new GridLayout(3, 3, 10, 10));
frame.add(BorderLayout.CENTER, panel);
label = new JLabel("TIC TAC TOE");
frame.add(BorderLayout.NORTH, label);
/* Set the initial player turn to player X */
player = PLAYER_X;
/* Create the JButtons */
buttons = new JButton[9];
/* Loop through and set all of them up */
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JButton();
buttons[i].addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JButton) {
((JButton)e.getSource()).setText(player ? "O" : "X"); /* Set button text */
player = !player; /* Switch turns */
}
}
});
/* Add all of the buttons to the panel. */
panel.add(buttons[i]);
}
/* Pack the frame to the contents. Basically a "fit to contents". */
frame.pack();
}
public void go() {
frame.setVisible(true);
panel.setVisible(true);
}
public static void main(String[] args) {
TicTacToe gui = new TicTacToe();
gui.go();
}
}
I am writing a program for a black jack game. It is an assignment we are not to use gui's but I am doing it for extra credit I have created two frames ant they are working. On the second frame I want to be able to switch back to the first when a button is pressed. How do I do this?
first window.............
import javax.swing.* ;
import java.awt.event.* ;
import java.awt.* ;
import java.util.* ;
public class BlackJackWindow1 extends JFrame implements ActionListener
{
private JButton play = new JButton("Play");
private JButton exit = new JButton("Exit");
private JPanel pane=new JPanel();
private JLabel lbl ;
public BlackJackWindow1()
{
super();
JPanel pane=new JPanel();
setTitle ("Black Jack!!!!!") ;
JFrame frame = new JFrame("");
setVisible(true);
setSize (380, 260) ;
setLocation (450, 200) ;
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE) ;
setLayout(new FlowLayout());
play = new JButton("Start");
exit = new JButton("exit");
lbl = new JLabel ("Welcome to Theodores Black Jack!!!!!");
add (lbl) ;
add(play, BorderLayout.CENTER);
play.addActionListener (this);
add(exit,BorderLayout.CENTER);
exit.addActionListener (this);
}
#Override
public void actionPerformed(ActionEvent event)
{
// TODO Auto-generated method stub
BlackJackWindow2 bl = new BlackJackWindow2();
if (event.getSource() == play)
{
bl.BlackJackWindow2();
}
else if(event.getSource() == exit){
System.exit(0);
}
}
second window....
import javax.swing.* ;
import java.awt.event.* ;
import java.awt.* ;
import java.util.* ;
public class BlackJackWindow2 extends JFrame implements ActionListener
{
private JButton hit ;
private JButton stay ;
private JButton back;
//private JLabel lbl;
public void BlackJackWindow2()
{
// TODO Auto-generated method stub
JPanel pane=new JPanel();
setTitle ("Black Jack!!!!!") ;
JFrame frame = new JFrame("");
setVisible(true);
setSize (380, 260) ;
setLocation (450, 200) ;
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE) ;
setLayout(new FlowLayout());
hit = new JButton("Hit");
stay = new JButton("stay");
back = new JButton("return to main menu");
// add (lbl) ;
add(hit, BorderLayout.CENTER);
hit.addActionListener (this) ;
add(stay,BorderLayout.CENTER);
stay.addActionListener (this) ;
add(back,BorderLayout.CENTER);
back.addActionListener (this) ;
}
#Override
public void actionPerformed(ActionEvent event)
{
// TODO Auto-generated method stub
BlackJackWindow1 bl = new BlackJackWindow1();
if (event.getSource() == hit)
{
//code for the game goes here i will complete later
}
else if(event.getSource() == stay){
//code for game goes here i will comeplete later.
}
else
{
//this is where i want the frame to close and go back to the original.
}
}
}
The second frame needs a reference to the first frame so that it can set the focus back to the first frame.
Also your classes extend JFrame but they are also creating other frames in their constructors.
A couple of suggestions:
You're adding components to a JPanel that uses FlowLayout but are using BorderLayout constants when doing this which you shouldn't do as it doesn't make sense:
add(play, BorderLayout.CENTER);
Rather, if using FlowLayout, just add the components without those constants.
Also, rather than swap JFrames, you might want to consider using a CardLayout and swapping veiws in a single JFrame. For instance:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooBarBazDriver {
private static final String INTRO = "intro";
private static final String GAME = "game";
private CardLayout cardlayout = new CardLayout();
private JPanel mainPanel = new JPanel(cardlayout);
private IntroPanel introPanel = new IntroPanel();
private GamePanel gamePanel = new GamePanel();
public FooBarBazDriver() {
mainPanel.add(introPanel.getMainComponent(), INTRO);
mainPanel.add(gamePanel.getMainComponent(), GAME);
introPanel.addBazBtnActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardlayout.show(mainPanel, GAME);
}
});
gamePanel.addBackBtnActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
cardlayout.show(mainPanel, INTRO);
}
});
}
private JComponent getMainComponent() {
return mainPanel;
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Foo Bar Baz");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new FooBarBazDriver().getMainComponent());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
class IntroPanel {
private JPanel mainPanel = new JPanel();
private JButton baz = new JButton("Baz");
private JButton exit = new JButton("Exit");
public IntroPanel() {
mainPanel.setLayout(new FlowLayout());
baz = new JButton("Start");
exit = new JButton("exit");
mainPanel.add(new JLabel("Hello World"));
mainPanel.add(baz);
mainPanel.add(exit);
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window win = SwingUtilities.getWindowAncestor(mainPanel);
win.dispose();
}
});
}
public void addBazBtnActionListener(ActionListener listener) {
baz.addActionListener(listener);
}
public JComponent getMainComponent() {
return mainPanel;
}
}
class GamePanel {
private static final Dimension MAIN_SIZE = new Dimension(400, 200);
private JPanel mainPanel = new JPanel();
private JButton foo;
private JButton bar;
private JButton back;
public GamePanel() {
foo = new JButton("Foo");
bar = new JButton("Bar");
back = new JButton("return to main menu");
mainPanel.add(foo);
mainPanel.add(bar);
mainPanel.add(back);
mainPanel.setPreferredSize(MAIN_SIZE);
}
public JComponent getMainComponent() {
return mainPanel;
}
public void addBackBtnActionListener(ActionListener listener) {
back.addActionListener(listener);
}
}
Since I had to test it myself if it is in fact so easy to implement, I built this simple example. It demonstrates a solution to your problem. Slightly inspired by #jzd's answer (+1 for that).
import java.awt.Color;
import java.awt.HeadlessException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class FocusChangeTwoFrames
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createGUI();
}
});
}
private static void createGUI() throws HeadlessException
{
final JFrame f2 = new JFrame();
f2.getContentPane().setBackground(Color.GREEN);
final JFrame f1 = new JFrame();
f1.getContentPane().setBackground(Color.RED);
f1.setSize(400, 300);
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f1.setVisible(true);
MouseListener ml = new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e)
{
if(f1.hasFocus())
f2.requestFocus();
else
f1.requestFocus();
}
};
f1.addMouseListener(ml);
f2.setSize(400, 300);
f2.setLocation(200, 150);
f2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f2.setVisible(true);
f2.addMouseListener(ml);
}
}
Enjoy, Boro.