I thought I implemented MouseListener correctly, but when I click on the canvas it doesn't reach the line System.out.println("Click registered");
All the tutorials I've looked at implement a mouse listener the way I did.
The program compiles and everything works except for the mouse listener.
package ttt;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Frame extends JFrame implements MouseListener
{
public static Field field = new Field();
public static Game game = new Game();
public static TTTCanvas tttcanvas = new TTTCanvas();
static final long serialVersionUID = 1l;
private static final int width = 700;
private static final int height = 700;
public Frame()
{
setLayout(new BorderLayout());
setResizable(false);
setBounds(400, 400, width, height);
setTitle("Tic Tac Toe");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
add(tttcanvas);
addMouseListener(this);
}
public void mouseClicked(MouseEvent e)
{
System.out.println("Click registered");
int x = field.getFieldfromPixel(e.getX());
int y = field.getFieldfromPixel(e.getY());
game.updateField(x, y);
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
Add the mouselistener to your ttt canvas
package ttt;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Frame extends JFrame implements MouseListener
{
public static Field field = new Field();
public static Game game = new Game();
public static TTTCanvas tttcanvas = new TTTCanvas();
static final long serialVersionUID = 1l;
private static final int width = 700;
private static final int height = 700;
public Frame()
{
setLayout(new BorderLayout());
setResizable(false);
setBounds(400, 400, width, height);
setTitle("Tic Tac Toe");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
add(tttcanvas);
tttcanvas.addMouseListener(this); //changed here
}
public void mouseClicked(MouseEvent e)
{
System.out.println("Click registered");
int x = field.getFieldfromPixel(e.getX());
int y = field.getFieldfromPixel(e.getY());
game.updateField(x, y);
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
}
Works fine for me when I remove:
//add(tttcanvas);
A MouseEvent is only dispatched to a single component.
Your TTTCanvas class must also have a MouseListner, so it is receiving the event.
Not sure what your exact requirement is so I would guess you could either:
add a second MouseListener to the TTTCanvas class or combine the logic of both listeners into one listener, or
remove the listener from the TTTCanvas class
Some code to demonstrate my answer:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Frame extends JFrame implements MouseListener
{
// public static Field field = new Field();
// public static Game game = new Game();
// public static TTTCanvas tttcanvas = new TTTCanvas();
// static final long serialVersionUID = 1l;
private static final int width = 700;
private static final int height = 700;
public Frame()
{
setLayout(new BorderLayout());
setResizable(false);
setBounds(400, 400, width, height);
setTitle("Tic Tac Toe");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
//add(tttcanvas);
JPanel panel = new JPanel();
panel.setPreferredSize( new Dimension(700, 400) );
panel.setBackground(Color.RED);
panel.addMouseListener( new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
System.out.println("panel listener");
}
});
add(panel, BorderLayout.PAGE_START);
addMouseListener(this);
}
public void mouseClicked(MouseEvent e)
{
System.out.println("frame listener");
}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public static void main(String[] args) throws Exception
{
java.awt.EventQueue.invokeLater( () -> new Frame() );
}
}
if you click on the red panel you see "panel listener" because the panel receives the event not the frame.
if you click on the grey you see "frame listener" because no other component has been added to the CENTER of the frames BorderLayout, so the frame receives the MouseEvent.
Related
I'm trying to move around jframe on the window through an event triggered from an external jpanel class, my code is below, but the doesn't achieve this. Instead the panel is the one that's moving around.
What am I doing wrong here? I am new programming in general.
package casuls_app;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Titlebar extends JPanel {
public Titlebar() {
btnClose =new JButton("X");
btnClose.setFocusable(false);
btnClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
closeButtonPressed(e);
}
}
);
controlBox =new JPanel(new GridLayout(1,1));
controlBox.setPreferredSize(new Dimension(150,40));
controlBox.add(btnClose);
controlBox.setBackground(new Color(255,255,255));
setLayout(new BorderLayout());
add(controlBox,BorderLayout.EAST);
setPreferredSize(new Dimension(0,40));
setBackground(new Color(60, 173, 205));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
mousePressedOnTitlebar(e);
}
}
);
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
mouseDraggedOnTitlebar(e);
}
}
);
}
private void mousePressedOnTitlebar(MouseEvent e) {
posX= e.getX();
posY=e.getY();
}
private void mouseDraggedOnTitlebar(MouseEvent e) {
setLocation(e.getXOnScreen() -posX, e.getYOnScreen() -posY);
}
private void closeButtonPressed(ActionEvent e){
System.exit(0);
}
//Variables declaration
private int posX,posY;
private JButton btnClose;
private JPanel controlBox;
}
setLocation() sets the location of your JPanel (because your class extends JPanel).
If you have a reference to the JFrame, you can call the setLocation method on that object.
frame.setLocation(x, y);
If you don't have the reference, then you can follow this post which accesses the frame via SwingUtilities:
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
I have a program that will make a JFrame with a JTextField. How do I get it to wait for text to be in the JTextField / the enter key is pressed?
public static void main(String[] args) {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int width = (int) screenSize.getWidth();
int height = (int) screenSize.getHeight();
JFrame frame = new JFrame();
frame.getContentPane().add(new Text());
JTextField field = new JTextField(10);
frame.add(field, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width,height-55);
frame.setVisible(true);
// There is a keylistener here called listener. It was 100 lines. Did not want to copy
frame.addKeyListener(listener);
double x = 0;
x = Double.parseDouble(field.getText());
System.out.println(x);
I want
x = Double.parseDouble(field.getText());
to run only when someone types something in the JTextField in the JFrame.
Don't use a KeyListener
Add a DocumentListener to your JTextField's Document.
Inside of this listener check to see if the Document is empty or not.
If not empty, change the state of your program to allow the calculation, perhaps by enabling or disabling a JButton or Action.
For example:
import java.awt.event.ActionEvent;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
public class DisbleButton extends JPanel {
private JTextField field = new JTextField(10);
private ButtonAction buttonAction = new ButtonAction();
private JButton button = new JButton(buttonAction);
public DisbleButton() {
add(field);
add(button);
buttonAction.setEnabled(false);
field.getDocument().addDocumentListener(new FieldDocListener());
}
private class FieldDocListener implements DocumentListener {
#Override
public void changedUpdate(DocumentEvent dEvt) {
testDoc(dEvt);
}
#Override
public void insertUpdate(DocumentEvent dEvt) {
testDoc(dEvt);
}
#Override
public void removeUpdate(DocumentEvent dEvt) {
testDoc(dEvt);
}
private void testDoc(DocumentEvent dEvt) {
Document doc = dEvt.getDocument();
buttonAction.setEnabled(doc.getLength() > 0);
}
}
private class ButtonAction extends AbstractAction {
public ButtonAction() {
super("Press Me");
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO do calculation here!
}
}
private static void createAndShowGui() {
DisbleButton mainPanel = new DisbleButton();
JFrame frame = new JFrame("DisbleButton");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
so this is my problem. I have an 8*8 grid of panels, all white. Then, when one of them is clicked, it's supposed to change to a random color. The only problem I have right now is that I don't know how to see if the user clicked their mouse in a specific panel. Here is the code I have so far (I'm going to implement the random element afterwards)
`
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GridOfPanels extends JPanel{
int x, y;
public GridOfPanels(){
JPanel content = new JPanel(new GridLayout(8,8));
for(int i = 0; i < 64; i++){
JPanel panel = new JPanel();
panel.setBackground(Color.white);
content.add(panel);
}
this.add(content);
}
public GridOfPanels(Color backColor){
setBackground(backColor);
addMouseListener(new PanelListener());
x = 200;
y = 200;
}
private class PanelListener extends MouseAdapter{
public void mousePressed(MouseEvent e){
x = e.getX();
y = e.getY();
repaint();
}
}
public static void main(String[] args){
JFrame theGUI = new JFrame();
theGUI.setTitle("Grid");
theGUI.setVisible(true);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theGUI.setSize(400,400);
Rectangle z = new Rectangle(x, y, 50, 50);
}
}
`
You have to add a listener to each clickable object. Here is a working example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TestFrame extends JFrame{
public TestFrame(int size){
JPanel content = new JPanel(new GridLayout(size, size));
JPanel[] panel = new JPanel[size * size];
PanelListener listener = new PanelListener();
for(int i = 0; i < panel.length; i++){
panel[i] = new JPanel();
panel[i].setBackground(Color.white);
panel[i].addMouseListener(listener);
content.add(panel[i]);
}
this.add(content);
}
// MouseListener offers the method mouseClicked(MouseEvent e)
private class PanelListener implements MouseListener {
#Override
public void mouseClicked(MouseEvent event) {
/* source is the object that got clicked
*
* If the source is actually a JPanel,
* then will the object be parsed to JPanel
* since we need the setBackground() method
*/
Object source = event.getSource();
if(source instanceof JPanel){
JPanel panelPressed = (JPanel) source;
panelPressed.setBackground(Color.blue);
}
}
#Override
public void mouseEntered(MouseEvent arg0) {}
#Override
public void mouseExited(MouseEvent arg0) {}
#Override
public void mousePressed(MouseEvent arg0) {}
#Override
public void mouseReleased(MouseEvent arg0) {}
}
public static void main(String[] args){
TestFrame theGUI = new TestFrame(8);
theGUI.setTitle("Grid");
theGUI.setVisible(true);
theGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
theGUI.setSize(400,400);
}
}
You have to add MouseListener to one of the panels. Only one panel will react to click event. In the listener cast the source to JPanel and change the color.
I have a program which at the moment I am trying to find the position of co-ordinates on the panel when clicked. So far I'm currently get 0,0. Any suggestions?
P.S - Sorry about the lack of comments...
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.lang.Math;
public class ShapePanel extends JPanel{
private JButton startButton, stopButton;
private JTextField textField;
private JLabel label;
private Timer timer;
private final int DELAY = 5;
ArrayList<Shape> obj = new ArrayList<Shape>();
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ShapePanel());
frame.pack();
frame.setVisible(true);
}
public ShapePanel(){
DrawingPanel dpanel = new DrawingPanel();
JPanel cpanel = new JPanel();
startButton = new JButton("Start");
stopButton = new JButton("Stop");
cpanel.setLayout(new GridLayout(2,1));
cpanel.add(startButton);
cpanel.add(stopButton);
dpanel.addMouseListener(new MouseListen());
TimerListener tListen = new TimerListener();
startButton.addActionListener(tListen);
stopButton.addActionListener(tListen);
add(cpanel);
add(dpanel);
timer = new Timer(DELAY, tListen);
timer.start();
}
private class TimerListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if (e.getSource() == timer){
for (int i = 0; i < obj.size(); i++){
obj.get(i).move();
}
}else if (e.getSource() == startButton){
timer.start();
}else if (e.getSource() == stopButton){
timer.stop();
}
repaint();
}
}
private class MouseListen implements MouseListener {
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
System.out.println(getX());
}
}
private class DrawingPanel extends JPanel{
DrawingPanel(){
setPreferredSize(new Dimension(400,400));
setBackground(Color.pink);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
for(int i = 0; i < obj.size(); i++){
obj.get(i).display(g);
}
}
}
}
Check the following portion of your code:
public void mouseClicked(MouseEvent e) {
System.out.println(getX());
// you are putting here only getX() which get the postion of panel
// put e.getX() instead
}
You need to implement the mouselistener correctly. The MouesEvent carries the position of the MouseClick.
public void mouseClicked(MouseEvent e) {
System.out.println(e.getPoint().x);
}
I have created a frame without the title bar, for that I used the setUndecorated(true); method but after that the frame is became unmovable for some reason.
How can I make my frame movable and still hide my title bar?
The following code will create a JFrame without a title bar, which you can still move around:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class FrameDragListenerExample {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
public void run() {
final JFrame frame = new JFrame("Hello");
frame.setUndecorated(true);
frame.setBounds(0, 0, 400, 400);
JPanel contentPane = new JPanel(new BorderLayout());
JLabel label = new JLabel("Click anywhere in the Jframe and drag");
label.setFont(label.getFont().deriveFont(16f));
label.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
contentPane.add(label);
frame.setContentPane(contentPane);
FrameDragListener frameDragListener = new FrameDragListener(frame);
frame.addMouseListener(frameDragListener);
frame.addMouseMotionListener(frameDragListener);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
};
SwingUtilities.invokeLater(runnable);
}
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCompCoords = null;
public FrameDragListener(JFrame frame) {
this.frame = frame;
}
public void mouseReleased(MouseEvent e) {
mouseDownCompCoords = null;
}
public void mousePressed(MouseEvent e) {
mouseDownCompCoords = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
Point currCoords = e.getLocationOnScreen();
frame.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
}
}
}
You can still drag it around by dragging the body of the frame.
Maybe this will help you Moving Window
I encapsulate a extended JFrame class for you, I called it MoveaFrame, you just need to "extend MoveaFrame" in your practice:
Just copy below codes to your project, and extend it, you can make your Frame window draggable!
Extend MoveJFrame like extend a JFrame, you can directly drag your window:
public class ContactUi extends MoveJFrame implements Runnable {
The MoveJFrame class code, just copy it and extend it like extend JFrame:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
public class MoveJFrame extends JFrame {
public MoveJFrame() {
this.setUndecorated(true);
FrameDragListener frameDragListener = new FrameDragListener(this);
this.addMouseListener(frameDragListener);
this.addMouseMotionListener(frameDragListener);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public static void main(String[] args) throws IOException {
new MoveJFrame();
}
public static class FrameDragListener extends MouseAdapter {
private final JFrame frame;
private Point mouseDownCompCoords = null;
public FrameDragListener(JFrame frame) {
this.frame = frame;
}
public void mouseReleased(MouseEvent e) {
mouseDownCompCoords = null;
}
public void mousePressed(MouseEvent e) {
mouseDownCompCoords = e.getPoint();
}
public void mouseDragged(MouseEvent e) {
Point currCoords = e.getLocationOnScreen();
frame.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
}
}
}