I am a beginner at java so am attempting to create a minesweeper game. I have a grid full of JButtons that when clicked reveal numbers or mines.
I want to add "flags" so when I right click on any button it changes colour - showing it has been flagged and is 'locked' so it cannot be clicked on unless right clicked.
Here are my buttons
public void buttons()
{
// Creating the grid with buttons
grid.setLayout(new GridLayout(20,20));
// Button grid
for (int x = 0; x < buttons.length; x++)
{
for (int y = 0; y < buttons.length; y++)
{
buttons[x][y] = new JButton();
buttons[x][y].addActionListener(this);
grid.add(buttons[x][y]);
}
}
I attempted to create this right click functionality but I am currently stuck and would like some help.
public void flag()
{
buttons.addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
JButton rightClick = new JButton("Right Click");
rightClick.addActionListener(this);
}
});
}
Typically, you would process user events on a button via the button's ActionListener, what you want to try and do is stop the user from trigger the buttons ActionListener, the easiest way that you can do this is disable the button...
Normally, I don't like using MouseListeners on buttons as this is not normally the best way to ascertain user interaction, but in this case, it's the requirement
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JButton btn;
public TestPane() {
setBorder(new EmptyBorder(8, 8, 8, 8));
setLayout(new GridBagLayout());
btn = new JButton("O");
btn.setMargin(new Insets(8, 8, 8, 8));
add(btn);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("You clicked me");
}
});
btn.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
btn.setEnabled(!btn.isEnabled());
if (btn.isEnabled()) {
btn.setText("O");
} else {
btn.setText("X");
}
}
}
});
}
}
}
Related
I want to set my JToggleButton in a disabled state, i.e. so that the user can't toggle it by clicking. I tried btn.setEnabled(false); but it grays out my icon and I don't want that. Is there any other method which doesn't gray out the icon, but doesn't let the user toggle the button?
but my own custom icon to be displayed.
You can also specify a "disabled icon" to be used by the toggle button. It could be the same Icon you use by default, or a slightly different icon.
When you specify your own Icon you don't get the greyed out effect.
You could disassociate the icon from the button and use appropriate layout constraints to provide a visual clue to the relationship instead, using a JLabel to display the icon instead, for example...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
public class TestPane extends JPanel {
public TestPane() throws IOException {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
BufferedImage img = ImageIO.read(new File("/Volumes/Disk02/Dropbox/MegaTokyo/thumnails/2.jpg"));
JLabel label = new JLabel(new ImageIcon(img));
add(label, gbc);
JToggleButton btn = new JToggleButton("Click");
btn.setEnabled(false);
add(btn, gbc);
}
}
}
Personally, I'm thinking a JCheckBox might be more appropriate for this style
To allow the JToggleButton to be clicked only once.
If there are N JToggleButtons, declare N number of int class variables equal to 0.
(int jtbIntValue1=0, jtbIntValue1=0 ,...jtbIntValueN = 0)
Before allowing the user to press the JToggle button check if(jtbIntValueN != 0)
when a JToggle button is clicked update the corresponding JToggleButton int value equal to 1. (From jtbIntValueN = 0 to jtbIntValueN = 1).
public class Development1
{
int b1 = 0 ; // For one Button
public Development1()
{
...........
...........
JToggleButton jtb1 = new JToggleButton();
jtb1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e1)
{
if(b1!=1)
{
if(SwingUtilities.isRightMouseButton(e1) && e1.getClickCount() == 1)
{
jtb1.setIcon(icRight); // Or do whatever you want to
}
else if(SwingUtilities.isLeftMouseButton(e1) && e1.getClickCount() == 1)
{
jtb1.setIcon(icLeft);
}
}
b1 = 1;
}
});
To abstract this problem, I put 2 buttons. One is called "Add & toTop", another is called "toTop"
And there is no text in the textArea at the very beginning.
And I add the actionListener for "Add & toTop" button like this:
btn1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
textArea1.setText("jhggjhg\nhugffsrdtfg\ngfdrtdf\nhgftrsdf\nytfresrdcfvg\nuytyrdtesrdfgg\ntdrfygvhct\njh"
+ "gfda\njftyuyiugcf\nhfuygihvftyughbuy\nhgyuftydfhgfyc\ndstryrfdts");
//A long enough String
JScrollBar jb = scrollPane1.getVerticalScrollBar();
jb.setValue(jb.getMinimum());
scrollPane1.repaint();
}
});
So the function of the first button is :"Add some text and Scroll to Top"
But it will only add text but will not scroll to top
However for the second button, I add a actionListener like this:
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JScrollBar VerticalScrollBar = scrollPane1.getVerticalScrollBar();
VerticalScrollBar.setValue(VerticalScrollBar.getMinimum());
scrollPane1.repaint();
}
});
So, I press the second button after pressing the first button, the second button will perform well.
And I really feel confused that why the first button will not scroll to top :<
A simple solution might be to use JTextArea#setCaretPosition, for example
import java.awt.BorderLayout;
import java.awt.EventQueue;
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.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea ta;
public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(5, 20);
add(new JScrollPane(ta));
JButton btn = new JButton("Add and to top");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ta.setText("jhggjhg\nhugffsrdtfg\ngfdrtdf\nhgftrsdf\nytfresrdcfvg\nuytyrdtesrdfgg\ntdrfygvhct\njh"
+ "gfda\njftyuyiugcf\nhfuygihvftyughbuy\nhgyuftydfhgfyc\ndstryrfdts");
ta.setCaretPosition(0);
}
});
add(btn, BorderLayout.SOUTH);
}
}
}
I had a play around with scrollRectToVisible, but ended up having to use SwingUtilites.invokeLater to make it work, for example...
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ta.scrollRectToVisible(new Rectangle(0, 0, 10, 10));
}
});
so I'd say setCaretPosition in this case is the simpler solution
I have the following JButton on the GUI interface I'm building.
I want to make the border around the button more thicker so it will stand out from the background. Is it possible to do this in Java?
You could simply use a LineBorder
JButton btn = ...;
btn.setBorder(BorderFactory.createLineBorder(Color.BLACK, 4));
Take a look at How to Use Borders for more details and ideas
Updating the border state based on the model state
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
protected static final Border NORMAL_BORDER = BorderFactory.createLineBorder(Color.BLACK, 4);
protected static final Border ROLLOVER_BORDER = BorderFactory.createLineBorder(Color.RED, 4);
public TestPane() {
JButton btn = new JButton("Click me!");
btn.setContentAreaFilled(false);
btn.setBorder(NORMAL_BORDER);
btn.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
if (btn.getModel().isRollover()) {
btn.setBorder(ROLLOVER_BORDER);
} else {
btn.setBorder(NORMAL_BORDER);
}
}
});
setLayout(new GridBagLayout());
add(btn);
}
}
}
Create a Border first -
Border border = new LineBorder(Color.WHITE, 13);
Then create a JButton and set the Border -
JButton button = new JButton("Button Name");
button.setBorder(border);
Hope it will Help.
Thanks a lot.
I'm making a piano interface and am trying to make it so that when the user clicks the white key it turns light gray, then when they release it. When I press the key, it beings the white key to the foreground and hides the black key.
Before clicking anything:
After clicking a few keys:
The keys are JPanels inside a JLayeredPanel and I'm setting the background colors to change the color. I'd like for the black keys to stay on top when I click the bottom keys. Is there any way I can do this? I'm using Netbeans GUI Builder
Start by having a closer look at How to Use Layered Panes. You need to specify the layer you want each component to reside, otherwise they will overlap each other
Just in case you miss it, they key factor here is the use of JLayeredPane#setLayer
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class TestLayer {
public static void main(String[] args) {
new TestLayer();
}
public TestLayer() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JLayeredPane {
public TestPane() {
setLayout(new GridBagLayout());
ColorPane background = new ColorPane(Color.WHITE) {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
ColorPane foreground = new ColorPane(Color.BLACK) {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
add(background, gbc);
setLayer(background, 0);
add(foreground, gbc);
setLayer(foreground, 1);
}
#Override
public void doLayout() {
super.doLayout();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
public class ColorPane extends JPanel {
public ColorPane(Color backGround) {
setBackground(backGround);
setBorder(new LineBorder(Color.RED));
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
setBackground(Color.RED);
}
#Override
public void mouseReleased(MouseEvent e) {
setBackground(backGround);
}
});
}
}
}
}
I want enter key to behave like tab key in my swing application.And this class is working fine for JTextFields.How can i do the same for JComboBox and Jspinner or for the other controls on the frame?kindly help.
class MyTextField extends JTextField {
MyTextField(int len) {
super(len);
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent evt) {
int key = evt.getKeyCode();
if (key == KeyEvent.VK_ENTER)
transferFocus();
}
});
}
}
Enter has special meaning for most components in Swing, for example JTextField will trigger actionPerformed on registered ActionListeners when Enter is pressed. Modifying this behaviour may have unexpected results for your application and may confuse many users...
Having said that, the best way to change the focus traversal keys is to provide a Set of KeyStrokes to the KeyboardFocusManager. This will (mostly) make the key's global.
Some component's supply there own focus traversal keys however, like JTextArea and JTable
Take a look at How to use Focus Subsystem for more details
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestFocusTraversal {
public static void main(String[] args) {
new TestFocusTraversal();
}
public TestFocusTraversal() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new GridBagLayout());
for (int index = 0; index < 10; index++) {
JTextField tf = new JTextField(5);
tf.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("...");
}
});
add(tf);
}
add(new JScrollPane(new JTextArea(10, 10)));
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
KeyStroke tab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
KeyStroke ctrlTab = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_DOWN_MASK);
Set<KeyStroke> keys = new HashSet<>();
keys.add(enter);
keys.add(tab);
keys.add(ctrlTab);
KeyboardFocusManager.getCurrentKeyboardFocusManager().setDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
}
}
}