1st time poster here!
I am working on a Java Photo Viewer Gallery.
I want to add all Labels from an ArrayList to a MouseListener. So I can go and open the picture the user clicked at in a new big window.
I have a file chooser where the user can select i number of pictures. I scaled them and put them in a:
ArrayList scaled = new ArrayList();
Error: The method addMouseListener(MouseListener) in the type Component is not applicable for the arguments (new ActionListener(){})
I tried to use
for (int i=0; i< scaled.size(); i++){
panel.add(new JLabel(new ImageIcon (scaled.get(i))));
JLabel l = new JLabel(new ImageIcon(scaled.get(i)));
l.addMouseListener(this); //<- Compiler Error
}
The complete Code is:
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Label;
import java.awt.List;
import java.awt.event.*;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.*;
public class ImageViewer {
public static void main(String[] args) {
JFrame frame = new ImageViewerFrame();
frame.setTitle("PhotoViewer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
#SuppressWarnings("serial")
class ImageViewerFrame extends JFrame implements MouseListener{
JLabel label;
JFileChooser chooser;
JMenuBar menubar;
JMenu menu;
JMenuItem menuitem;
JPanel panel = new JPanel();
// JLabel l1= new JLabel("First");
// JLabel l2= new JLabel("Second");
// JLabel l3= new JLabel("Third");
// JLabel l4= new JLabel("Fourth");
public ArrayList<File> images = new ArrayList <File>();
public ImageViewerFrame() {
setSize(500,500);
panel.setLayout(new GridLayout(0,5));
label = new JLabel();
add(label);
add(panel);
JButton test = new JButton ("TEST");
test.addMouseListener(this);
panel.add(test);
panel.setVisible(true);
chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
chooser.setMultiSelectionEnabled(true);
menubar = new JMenuBar();
setJMenuBar(menubar);
menu = new JMenu("File");
menubar.add(menu);
menuitem = new JMenuItem("Open");
menu.add(menuitem);
ArrayList<ImageIcon> AL = new ArrayList<ImageIcon>();
ArrayList<Image> scaled = new ArrayList<Image>();
menuitem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event){
int result = chooser.showOpenDialog(null);
if(result == JFileChooser.APPROVE_OPTION) {
//label.setIcon(new ImageIcon(name));
File[] f = chooser.getSelectedFiles();
for(int i=0; i< f.length; i++)
{
images.add(f[i]);
ImageIcon imageicon = new ImageIcon(f[i].toString());
AL.add(imageicon);
}
for (ImageIcon x : AL){
System.out.println(x);
Image image = x.getImage();
Image newimg = image.getScaledInstance(120,120, java.awt.Image.SCALE_SMOOTH);
scaled.add(newimg);
}
for (int i=0; i< scaled.size(); i++){
panel.add(new JLabel(new ImageIcon (scaled.get(i))));
JLabel l = new JLabel(new ImageIcon(scaled.get(i)));
l.addMouseListener(this);
}
}
}
});
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
}
}
It wont let me add the JLabel l to the MouseListener
First of all you don't add a label to a MouseListener. You add a MouseListener to the label. You didn't implement the MouseListener interface so you get the compile error. You need to implement all the methods (mousePressed, mouseReleased ...).
Read the section from the Swing tutorial on How to Write a MouseListener for working examples.
Also, once you get the MouseListener working you don't need to create two labels. The basic code might be something like:
JLabel l = new JLabel(new ImageIcon(scaled.get(i)));
label.addMouseListener(this); //<- Compiler Error
panel.add( label );
Finally, you may want to consider using a JList to display the Icons. It is more efficient because it just renders the images. Then you can use a ListSelectionListener to do processing when an image is selected. Read the section from the Swing tutorial on How to Use Lists for more information.
I would use an array to store all the mouse information.
Example :
public class MyApp extends JFrame implements MouseListener, MouseWheelListener {
public int[] mouse=new int[5];
public void mousePressed(MouseEvent m) {
if (m.getButton() == m.BUTTON1) {
mouse[2]=1;
}
if (m.getButton() == m.BUTTON2) {
mouse[3]=1;
}
if (m.getButton() == m.BUTTON3) {
mouse[4]=1;
}
}
public void mouseClicked(MouseEvent m) {
if (m.getButton() == m.BUTTON1) {
mouse[2]=3;
}
if (m.getButton() == m.BUTTON2) {
mouse[3]=3;
}
if (m.getButton() == m.BUTTON3) {
mouse[4]=3;
}
}
public void mouseReleased(MouseEvent m) {
if (m.getButton() == m.BUTTON1) {
mouse[2]=2;
}
if (m.getButton() == m.BUTTON2) {
mouse[3]=2;
}
if (m.getButton() == m.BUTTON3) {
mouse[4]=2;
}
}
public void mouseEntered(MouseEvent m) {
}
public void mouseExited(MouseEvent m) {
}
public void mouseWheelMoved(MouseWheelEvent w) {
mouse[3]=w.getWheelRotation();
}
public MyApp() {
super("MyApp");
//Do your stuff here...
//...
//...
setTitle("Image Picker");
requestFocus();
addMouseListener(this);
addMouseWheelListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1400,1000);
setResizable(true);
setVisible(true);
int gc=0;
Rectangle r;
while (true){
try {
Thread.sleep(33);
} catch(InterruptedException bug) {
Thread.currentThread().interrupt();
System.out.println(bug);
}
r=getComponents()[0].getBounds();
gc=gc+1;
if (gc==500) {
System.gc();
gc=0;
}
mouse[0]=MouseInfo.getPointerInfo().getLocation().x-getComponents()[0].getLocationOnScreen().x;
mouse[1]=MouseInfo.getPointerInfo().getLocation().y-getComponents()[0].getLocationOnScreen().y;
//Display labels
}
}
public static void main(String args[]){
new MyApp();
}
}
The mouse array will be :
mouse[0] - mouse x pos
mouse[1] - mouse y pos
mouse[2] - left mouse button
mouse[3] - middle mouse button
mouse[4] - right mouse button
mouse[5] - mouse wheel rotation, 0 if none, else -n to n
And it should be easy to check if a point (the mouse) is over a rectangle (the label). If you dont know how to get the positions of the labels, simply use this code :
Rectangle r=getComponents()[1+n].getBounds();
//r.x, r.y, r.width, r.height
Hope it helps you !
Related
Here is my whole program, don't wonder about the words I am using, I am German.
Down from l. 95 to l. 103 is the action performed method, (I only did the System.out.println() to see wether it is working or not).
I wrote other programs, where I never had any such problems, and I tried so many things, but I did not find the problem, maybe it is a total simple one...
So I would appreciate it if you help me!
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class GameFrame implements ActionListener {
String wochentag;
int itag = 0;
int imonat = 0;
int ijahrhundert = 0;
int ijahr = 0;
String stag;
String smonat;
String sjahr;
String sJahrhundert;
boolean rechnen = false;
JFrame frame = new JFrame();
JButton start = new JButton("Wochentag errechnen");
JButton update = new JButton("Datum anzeigen");
JPanel alles = new JPanel();
JLabel Tag = new JLabel("Tag");
JLabel Monat = new JLabel("Monat");
JLabel Jahr = new JLabel("Jahr");
JLabel Jahrhundert = new JLabel("Jahrhundert");
JTextField Datum = new JTextField(" Welchen Wochentag hatte der --.--.---- ");
JTextField Output = new JTextField(" Dieser Tag war ein ------tag");
JTextField tag = new JTextField();
JTextField monat = new JTextField();
JTextField jahr = new JTextField();
JTextField jahrhundert = new JTextField();
GameFrame(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.getContentPane().setBackground(Color.WHITE);
frame.setLayout(new BorderLayout());
frame.setVisible(true);
frame.setFocusable(false);
frame.setResizable(false);
alles.setBounds(0,0,500,500);
Datum.setBounds(75,40,280,40);
Datum.setEditable(false);
Tag.setBounds(175,100,45,25);
Monat.setBounds(175,150,55,25);
Jahr.setBounds(175,200,50,25);
Jahrhundert.setBounds(175,250,75,25);
Output.setBounds(118,400,202,40);
Output.setEditable(false);
tag.setBounds(250,100,75,25);
tag.setEditable(true);
monat.setBounds(250,150,75,25);
jahr.setBounds(250,200,75,25);
jahrhundert.setBounds(250,250,75,25);
start.setBounds(165,350,170,25);
start.setFocusable(false);
update.setBounds(175,300,150,25);
update.setFocusable(false);
frame.add(alles);
alles.add(Datum);
alles.add(Tag);
alles.add(Monat);
alles.add(Jahr);
alles.add(Jahrhundert);
alles.add(Output);
alles.add(tag);
alles.add(monat);
alles.add(jahr);
alles.add(jahrhundert);
alles.add(start);
alles.add(update);
}
public static void main(String[] args) {
GameFrame gameframe = new GameFrame();
}
#Override
public void actionPerformed(ActionEvent e){
if(e.getSource() == update){
stag = tag.getText();
tag.setText("");
System.out.println(stag);
}
}
}
As the guys mentioned in the comments, you have not added the listener to your component (update button). If you are using a button, you might consider using a MouseListener instead
public class GameFrame implements MouseListener {
JButton update = new JButton("Datum anzeigen");
GameFrame()
{
//other code
update.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
}
If you want to have multiple listeners for your separate buttons you can also create them within your constructor
update.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
System.out.println("Start button wurde geklickt");
}
};
start.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
System.out.println("Update button wurde geklickt");
}
};
How do I make the Enter key trigger a JComboBox or JButton in a GUI rather than having to hit the Space key? I have an assortment of text fields and check boxes with buttons and combo boxes in between. I'd like to avoid having to switch between hitting space and enter and rather only have to hit enter for all components.
package koning.personal.dungeonsanddragons;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class test {
JFrame window = new JFrame("testGUI");
JPanel windowPanel = new JPanel();
public static JLabel labelSize;
public static JComboBox<String> comboSize;
public static JLabel labelButton;
public static JButton buttonButton;
public test () {
super();
labelSize = new JLabel("Monster Size:");
String[] sizeChoices = { "None", "Tiny", "Small", "Medium", "Large", "Huge", "Colossal"};
comboSize = new JComboBox<String>(sizeChoices);
comboSize.setToolTipText("The creature's size.");
labelButton = new JLabel("Button:");
buttonButton = new JButton();
windowPanel.setLayout(new FlowLayout());
windowPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
windowPanel.add(labelSize);
windowPanel.add(comboSize);
windowPanel.add(labelButton);
windowPanel.add(buttonButton);
windowPanel.setVisible(true);
window.setSize(500, 500);
window.setLayout(new FlowLayout());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
window.add(windowPanel);
comboSize.addActionListener(handler);
buttonButton.addActionListener(handler);
}
ActionHandler handler = new ActionHandler();
public class ActionHandler implements ActionListener {
public void actionPerformed(ActionEvent eventFocus){
if (eventFocus.getSource() == comboSize){
buttonButton.requestFocusInWindow();
}
if (eventFocus.getSource() == buttonButton){
comboSize.requestFocusInWindow();
}
}
}
#SuppressWarnings("unused")
public static void main(String[] args) {
test GUITest = new test();
}
}
You can add a KeyListener and execute doClick
JButton btn = new JButton();
btn.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER)
btn.doClick();
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
});
If the goal is to have something happen when the enter button is pressed (pressed once and something happens with all the components) then you can add a KeyListener to the JFrame:
JFrame frame = new JFrame("Examplpe");
//here you create and add the components to the frame
and then you can add a KeyListener:
frame.addKeyListener(new KeyListener(
#Override
public void keyTyped(KeyEvent e) {
if(e.getKeyCode == KeyEvent.VK_ENTER){//this is the if block I'm refering to in the following explanation
//do something with all the components
}
}
#Override
public void keyReleased(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {}
}
and then when you press Enter, the code inside the if block will be executed.
Hope this helps :)
This is homework. I included relevant code at the bottom.
Problem:
In an attempted to allow the user to resize the grid, the grid is now being drawn severely overpopuated.
Screen Shots:
"Overpopulation" -
http://i.imgur.com/zshAC6n.png
"Desired Population" -
http://i.imgur.com/5Rf6P42.png
Background:
It's a version of Conway's Game of Life. In class we completed 3 classes: LifeState which handles the game logic, LifePanel which is a JPanel that contains the game, and a driver that created a JFrame and added the LifePanel. The assignment was to develop it into a full GUI application with various requirements. My solution was to extend JFrame and do most of my work in that class.
Initializing the LifePanel outside of the actionlistener yields normal population, but intializing the LifePanel in the actionlistener "overpopulates" the grid.
Question: Why is the overpopulation occurring?
LifePanel class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
public class LifePanel extends JPanel implements MouseListener
{
private int row;
private int col;
private int scale;
private LifeState life;
boolean state;
boolean wrap;
int delay;
Timer timer;
public LifePanel(int r, int c, int s, int d)
{
row = r;
col = c;
scale = s;
delay = d;
life = new LifeState(row,col);
Random rnd = new Random();
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
life.setCell(i,j,rnd.nextBoolean());
timer = new Timer(delay, new UpdateListener());
setPreferredSize( new Dimension(scale*row, scale*col));
addMouseListener(this);
timer.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
if(life.getCell(i,j))
g.fillRect(scale*i,scale*j,scale,scale);
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public int getScale() {
return scale;
}
public void setScale(int scale) {
this.scale = scale;
}
public int getDelay() {
return delay;
}
public void setDelay(int delay) {
this.delay = delay;
timer.setDelay(delay);
}
public void pauseGame(){
timer.stop();
}
public void playGame(){
timer.restart();
}
public void setInitState(boolean set){
state = set;
if(state){
timer.stop();
}
}
public void setWrap(boolean set){
wrap = set;
if(wrap){
//implement allow wrap
}
}
#Override
public void mouseClicked(MouseEvent e) {
if(state){
int x=e.getX();
int y=e.getY();
boolean isFilled;
isFilled = life.getCell(x,y);
//Test pop-up
JOptionPane.showMessageDialog(this, x+","+y+"\n"+life.getCell(x,y));
if(isFilled){
life.setCell(x,y,false);
}else{
life.setCell(x,y,true);
}
repaint();
}
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
private class UpdateListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
life.iterate();
repaint();
}
}
}
LifeFrame class
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LifeFrame extends JFrame implements ActionListener{
JMenuBar menuBar;
JMenu mainMenu, helpMenu;
JMenuItem restartItem, quitItem, helpItem;
JButton stopButton, playButton, pauseButton, startButton;
CardLayout cardLayout = new MyCardLayout();
CardLayout cardLayout2 = new MyCardLayout();
SetupPanel setupPanel; //panel for input
LifePanel gamePanel; //game panel
JPanel controls = new JPanel(); //controls for game
JPanel controls2 = new JPanel(); //controls for input panel
JPanel cardPanel = new JPanel(cardLayout);
JPanel cardPanel2 = new JPanel(cardLayout2);
int gridRow=480;
int gridCol=480;
int scale=1;
int delay=2;
boolean setState = false;
boolean setWrap = false;
public LifeFrame() {
setTitle("Game of Life");
setLayout(new BorderLayout());
//Add the Panels
setupPanel = new SetupPanel();
gamePanel = new LifePanel(gridRow,gridCol,scale,delay);
cardPanel.add(setupPanel, "1");
cardPanel.add(gamePanel, "2");
add(cardPanel, BorderLayout.NORTH);
cardPanel2.add(controls2, "1");
cardPanel2.add(controls, "2");
add(cardPanel2, BorderLayout.SOUTH);
//init menu
menuBar = new JMenuBar();
//button listener setup
stopButton = new JButton("Stop");
pauseButton = new JButton("Pause");
playButton = new JButton("Play");
startButton = new JButton("Start");
stopButton.addActionListener(this);
pauseButton.addActionListener(this);
playButton.addActionListener(this);
startButton.addActionListener(this);
//menu listener setup
restartItem = new JMenuItem("Restart", KeyEvent.VK_R);
quitItem = new JMenuItem("Quit", KeyEvent.VK_Q);
helpItem = new JMenuItem("Help", KeyEvent.VK_H);
restartItem.addActionListener(this);
quitItem.addActionListener(this);
helpItem.addActionListener(this);
//add buttons
controls.add(stopButton);
controls.add(pauseButton);
controls.add(playButton);
controls2.add(startButton);
//build the menus
mainMenu = new JMenu("Menu");
mainMenu.setMnemonic(KeyEvent.VK_M);
helpMenu = new JMenu("Help");
helpMenu.setMnemonic(KeyEvent.VK_H);
menuBar.add(mainMenu);
menuBar.add(helpMenu);
setJMenuBar(menuBar);
//add JMenuItems
restartItem.getAccessibleContext().setAccessibleDescription("Return to setup screen");
mainMenu.add(restartItem);
mainMenu.add(quitItem);
helpMenu.add(helpItem);
this.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
System.exit(0);
}
});
pack();
setLocationRelativeTo(null);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
#Override
public void actionPerformed(ActionEvent e) {
try{
gridRow = setupPanel.getRowSize();
gridCol = setupPanel.getColSize();
scale = setupPanel.getScale();
delay = setupPanel.getDelay();
setWrap = setupPanel.getSetWrap();
setState = setupPanel.getSetState();
}catch (NumberFormatException n){
JOptionPane.showMessageDialog(LifeFrame.this, "Make sure the fields contain only digits and are completed!");
return;
}
if(e.getSource() == pauseButton){
gamePanel.pauseGame();
}else if(e.getSource() == playButton){
gamePanel.playGame();
}else if(e.getSource() == quitItem){
System.exit(0);
}else if(e.getSource() == restartItem || e.getSource() == stopButton){
cardLayout.show(cardPanel, "1");
cardLayout2.show(cardPanel2, "1");
pack();
setLocationRelativeTo(null);
}else if(e.getSource() == helpItem){
String helpText = "Help\nPlease make sure every field is completed and contains only digits\nCurrent Stats:\nGrid Size: "+gamePanel.getRow()+" by "+gamePanel.getCol()+"\nScale: "+ gamePanel.getScale() +"\nDelay: "+gamePanel.getDelay()+"\nManual Initial State: "+setState+"\nEnable Wrapping: "+setWrap;
JOptionPane.showMessageDialog(LifeFrame.this, helpText);
}else if(e.getSource() == startButton){
gamePanel = new LifePanel(gridRow,gridCol,scale,delay);
cardPanel.add(gamePanel, "2");
/*
* Alternate solution, throws array index out of bounds due to array usage in the LifePanel, but properly
* populates the grid.
*
gamePanel.setRow(gridRow);
gamePanel.setCol(gridCol);
gamePanel.setScale(scale);
gamePanel.setDelay(delay);
*/
if(setWrap){
gamePanel.setWrap(true);
gamePanel.playGame();
}else if(setState){
gamePanel.setInitState(true);
}else{
gamePanel.setWrap(false);
gamePanel.setInitState(false);
gamePanel.playGame();
}
gamePanel.repaint();
cardLayout.show(cardPanel, "2");
cardLayout2.show(cardPanel2, "2");
pack();
setLocationRelativeTo(null);
}
}
public static class MyCardLayout extends CardLayout {
#Override
public Dimension preferredLayoutSize(Container parent) {
Component current = findCurrentComponent(parent);
if (current != null) {
Insets insets = parent.getInsets();
Dimension pref = current.getPreferredSize();
pref.width += insets.left + insets.right;
pref.height += insets.top + insets.bottom;
return pref;
}
return super.preferredLayoutSize(parent);
}
public Component findCurrentComponent(Container parent) {
for (Component comp : parent.getComponents()) {
if (comp.isVisible()) {
return comp;
}
}
return null;
}
}
}
Thanks for reading all this, and in advance for any help/advice you offer.
EDIT: Added screen shots and refined question.
Based on how you initialize LifePanel
Random rnd = new Random();
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
life.setCell(i,j,rnd.nextBoolean());
what you call "overpopulation" is the expected state. The above code will set about 1/2 of the cells to "alive" (or "occupied"), which is what your "overpopulated" state looks like.
The "desired population" screenshot contains many "life" artifacts such as "beehives", "gliders", "traffic lights", etc, and was either manually constructed or is the result of running several iterations on an initially 50% random population. With a 50% occupied population the first generation will result in wholesale clearing ("death") of many, many cells due to the proximity rules.
Most crucially, consider that, when starting up, your program does not paint the initial configuration. At least one iteration occurs before the first repaint() call.
I don't think your code is broken at all, just your expectation for what the initial population looks like.
I have a java program that opens a popup menu when right clicked in a JPanel. When any of the popup menu items are clicked, I want to print the location of the right click that triggered the popupmenu in the terminal. How do I do this? How do I get the location of where the right click happened from within popup action events?
How does the code change if the popup menu is in a JComponent?
Here is the program.
import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;
public class MenuTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
MenuFrame frame = new MenuFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class MenuFrame extends JFrame
{
public MenuFrame()
{
setTitle("MenuTest");
setSize(300, 200);
Action cutAction = new TestAction("Cut");
Action copyAction = new TestAction("Copy");
Action pasteAction = new TestAction("Paste");
JPopupMenu popup = new JPopupMenu();
popup.add(cutAction);
popup.add(copyAction);
popup.add(pasteAction);
JPanel panel = new JPanel();
panel.setComponentPopupMenu(popup);
add(panel);
panel.addMouseListener(new MouseAdapter() {});
}
class TestAction extends AbstractAction
{
public TestAction(String name)
{
super(name);
}
public void actionPerformed(ActionEvent event)
{
System.out.println("Right click happened at ?"); // How do I get right click location?
}
}
}
Add a mouse listener to pressed events, (clicked events get captured by popup):
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
clickLocation.setSize(e.getX(), e.getY());
}
});
Action cutAction = new TestAction("Cut", clickLocation);
Action copyAction = new TestAction("Copy", clickLocation);
Action pasteAction = new TestAction("Paste", clickLocation);
Print out the dimension:
private Dimension clickLocation;
public TestAction(String name, Dimension clickLocation) {
super(name);
this.clickLocation = clickLocation;
}
public void actionPerformed(ActionEvent event) {
System.out.println("Right click happened at " + clickLocation);
}
you were on the right track. i personally prefer to show it manually in the MouseAdapter so i can add methods on other mouseevents. for this you probably need to remove the panel.setComponentPopupMenu(popup);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if (arg0.getButton() == MouseEvent.BUTTON3) { //Button3 is rightclick
popup.show(panel, arg0.getX(), arg0.getY());
}
}
});
Here is the code that I was looking for. Thank you Schippi and Garret for your help.
import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;
public class MenuTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
MenuFrame frame = new MenuFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
}
class MenuFrame extends JFrame
{
public MenuFrame()
{
setTitle("MenuTest");
setSize(300, 200);
Action cutAction = new TestAction("Cut");
Action copyAction = new TestAction("Copy");
Action pasteAction = new TestAction("Paste");
JPopupMenu popup = new JPopupMenu();
popup.add(cutAction);
popup.add(copyAction);
popup.add(pasteAction);
JPanel panel = new JPanel();
panel.setComponentPopupMenu(popup);
add(panel);
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
clickLocation= e.getPoint();
}
});
}
class TestAction extends AbstractAction
{
public TestAction(String name)
{
super(name);
}
public void actionPerformed(ActionEvent event)
{
System.out.println("Right click happened at (" + clickLocation.getX()+"," + clickLocation.getY()+ ")");
}
}
private Point2D clickLocation;
}
Or if you don't want to get it from the event.
Point mousepospoint=null;
if((mousepospoint=componentname.getMousePosition()) != null){
//mouseposArray[0]=mousepospoint.x;
//mouseposArray[1]=mousepospoint.y;
mousepoints(mousepospoint.x,mousepospoint.y);
}//enif
int[] mouseposArray={0,0};
// requires a function to return it if mouseposArray[] is global
protected int[] mousepoints(int xpo,int ypo){
mouseposArray=new int[2];
mouseposArray[0]=xpo;
mouseposArray[1]=ypo;
return mouseposArray;
}//enmeth
Is there a way to toggle a read-only mode so when you click any object in your window it simply returns what you clicked, ignoring the object's usual event handling? IE, while in this "read-only" mode, if you click on a Button, it simply returns the button, not actually pressing the button. Then I could do something like:
if ("thing pressed" == button) "do this";
else if ("thing pressed" == panel) "do that";
else "do nothing";
Here's my code, its a frame with 3 colored boxes. Clicking the 2nd box, the 3rd box, or the background will display a message. Clicking box 1 does nothing. I like using new mouse adapters so I want to do it this way.
Now what I want is when you click box 1, box 1 is treated as selected (if that helps you get the picture). Then if you click anywhere, including box 1 again, box 1 is deselected and nothing else (meaning that box 2, box 3. or the background's message will display). At that time, only if box 2 or 3 were clicked, they will still not display their normal message but a different message would be displayed.
I'm very sorry if I come off a little short.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Labels {
public static void main(String[] args) {
new Labels();
}
Square l1, l2, l3;
public Labels() {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
l1 = new Square();
l2 = new Square();
l3 = new Square();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(120, 150);
frame.setResizable(false);
panel.setVisible(true);
panel.setLayout(null);
l1.setLocation(5, 5);
l2.setLocation(5, 60);
l3.setLocation(60, 5);
l2.setColor("yellow");
l3.setColor("black");
l1.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
//do nothing
}
});
l2.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Pushed label 2");
}
});
l3.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("Pushed label 3");
}
});
panel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("pushed background");
}
});
frame.add(panel);
panel.add(l1);
panel.add(l2);
panel.add(l3);
}
class Square extends JLabel{
Color color = Color.blue;
public Square() {
// TODO Auto-generated constructor stub\
setVisible(true);
setSize(50,50);
}
public void paint(Graphics g) {
super.paint(g);
g.setColor(color);
g.fillRect(0, 0, 50, 50);
}
public void setColor(String color){
if (color == "white") this.color = Color.white;
else if (color == "black") this.color = Color.black;
else if (color == "yellow") this.color = Color.yellow;
else {
System.out.println("Invalid color");
return;
}
repaint();
}
}
}
Don't disable anything. Simply change the state of your class, perhaps by using a few boolean flag variables/fields and change these flags depending on what is pressed.
So have boolean fields called label1PressedLast, label2PressedLast, and label3PressedLast or something similar, and when a label is pressed, check the states of all other flags and have your program's behavior change depending on the state of these flags and the label that was just pressed. Then set all flags to false except for the one corresponding to the label that was just pressed.
For example, this little program reacts only if the first and then the third JLabel have been pressed:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;
public class FlagEg extends JPanel {
private static final int LABEL_COUNT = 3;
private JLabel[] labels = new JLabel[LABEL_COUNT];
private boolean[] flags = new boolean[LABEL_COUNT];
public FlagEg() {
setLayout(new GridLayout(1, 0, 20, 0));
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
// panel mouse listener
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
inactivateAll();
}
});
MouseListener labelsMouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvt) {
myMousePressed(mouseEvt);
}
};
// create JLabels and add MouseListener
for (int i = 0; i < labels.length; i++) {
labels[i] = new JLabel("Label " + (i + 1));
labels[i].addMouseListener(labelsMouseListener);
labels[i].setOpaque(true);
labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
add(labels[i]);
}
}
private void inactivateAll() {
for (int i = 0; i < labels.length; i++) {
labels[i].setBackground(null);
flags[i] = false;
}
}
private void myMousePressed(MouseEvent mouseEvt) {
JLabel label = (JLabel) mouseEvt.getSource();
// which label was pressed?
int index = -1;
for (int i = 0; i < labels.length; i++) {
if (label == labels[i]) {
index = i;
}
}
// check if first label and then third pressed:
if (flags[0] && index == 2) {
System.out.println("first and then third label pressed!");
}
// reset all labels and flags to initial state
inactivateAll();
// set pressed label background color and set flag of label just pressed
labels[index].setBackground(Color.pink);
flags[index] = true;
}
private static void createAndShowGui() {
FlagEg mainPanel = new FlagEg();
JFrame frame = new JFrame("Flag Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Logic iteration two: only label 1 is the "primer" JLabel. This is actually easier to implement, because now you only need one boolean flag, that representing label 1 being pressed:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class FlagEg2 extends JPanel {
private static final int LABEL_COUNT = 3;
private JLabel[] labels = new JLabel[LABEL_COUNT];
private boolean label1Flag = false;
public FlagEg2() {
setLayout(new GridLayout(1, 0, 20, 0));
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
// panel mouse listener
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent arg0) {
inactivateAll();
}
});
MouseListener labelsMouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvt) {
myMousePressed(mouseEvt);
}
};
// create JLabels and add MouseListener
for (int i = 0; i < labels.length; i++) {
labels[i] = new JLabel("Label " + (i + 1));
labels[i].addMouseListener(labelsMouseListener);
labels[i].setOpaque(true);
labels[i].setBorder(BorderFactory.createLineBorder(Color.black));
add(labels[i]);
}
}
private void inactivateAll() {
for (int i = 0; i < labels.length; i++) {
labels[i].setBackground(null);
label1Flag = false;
}
}
private void myMousePressed(MouseEvent mouseEvt) {
JLabel label = (JLabel) mouseEvt.getSource();
// which label was pressed?
int index = -1;
for (int i = 0; i < labels.length; i++) {
if (label == labels[i]) {
index = i;
}
}
if (label1Flag) {
if (index == 1) {
System.out.println("Label 1 and label 2 pressed");
} else if (index == 2) {
System.out.println("Label 1 and label 3 pressed");
}
}
// reset all labels and flags to initial state
inactivateAll();
// if label1, then activate it
if (index == 0) {
labels[0].setBackground(Color.pink);
label1Flag = true;
}
}
private static void createAndShowGui() {
FlagEg2 mainPanel = new FlagEg2();
JFrame frame = new JFrame("Flag Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
package javaapplication6;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
/**
*
* #author Jan Vorcak <vorcak#mail.muni.cz>
*/
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
MouseListener listener = new MouseAdapter() {
private int count = 0;
#Override
public void mouseClicked(MouseEvent e) {
if(e.getComponent() instanceof JLabel) {
count++;
if (count >= 2) {
System.out.println("clicked 2 times on labels");
count = 0;
}
} else {
count = 0;
}
}
};
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel l1 = new JLabel("Label 1");
JLabel l2 = new JLabel("Label 2");
JLabel l3 = new JLabel("Label 3");
l1.addMouseListener(listener);
l2.addMouseListener(listener);
l3.addMouseListener(listener);
frame.addMouseListener(listener); // or panel.addMouseListener(listener);
panel.add(l1);
panel.add(l2);
panel.add(l3);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
You could want to create a listener that do the job for using the putClientProperty method of JComponent.
public class JComponentClickCountListener extends MouseAdapter {
private final Integer ONE = 1;
#Override
public void mouseClicked(MouseEvent e) {
if (e.getComponent() instanceof JComponent) {
JComponent jComponent = (JComponent) e.getComponent();
Object property = jComponent.getClientProperty(JComponentClickCountListener.class);
if (property instanceof Number) {
property = ONE + ((Number) property).intValue();
}
else {
property = ONE;
}
jComponent.putClientProperty(JComponentClickCountListener.class, property);
}
}
}
Then in your code you can decide to have a single instace of that class for all of your components or create a new one each time.
This could give you the advantage of using the propertyChangeListener for future actions.
PS.
The code example do not represent all logic for OP question but i could by used as solid base. Later on i will try to update it. To cover that.
EDIT2:
I think that you should separate the logic, of selection and action over selected items. Then the task is divided into two tasks. First is the possibility to store the information about it state, clicked active, clicked again inactive. The second tasks it to operate on that status when a jComponent status was changed.
This is an simple example that i wrote, the functionality is to highlight the background of labels when the are selected and remove it when it was clicked again or the panel was clicked remove all selections.
This example is divided to three elements Enum, Iterface and class that manage the logic of selection
Enum - we store the possible statuses and a property key.
public enum JComponentActivationStatus {
NONE,
ACTIVE,
INACTIVE;
public static final String PROPERTY_KEY = JComponentActivationStatus.class.getCanonicalName();
}
Interface - provide a delegate for action to be taken when jcomponenet status change.
public abstract interface JComponenetActivationStatusChangeAction<T extends JComponent> {
public abstract void onActivation(T object);
public abstract void onDeactivation(T object);
}
Class - This class mange the status logic of jcomponents.
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
public class JComponenetActivationManager {
public static <T extends JComponent> T addMouseStatusControl(T jComponent) {
jComponent.addMouseListener(new JComponentMouseStatusModyfier());
return jComponent;
}
public static <T extends JComponent> T addActivationStatusChangeAction(T jComponenet, JComponenetActivationStatusChangeAction<T> statusChangeAction) {
jComponenet.addPropertyChangeListener(craeteJCompositeActivationStatusChangeListener(statusChangeAction));
return jComponenet;
}
public static <T extends JComponent> PropertyChangeListener craeteJCompositeActivationStatusChangeListener(JComponenetActivationStatusChangeAction<T> action) {
return new JComponentStatusPropertyChangeListener<T>(action);
}
/**
* Class that set the status for the JComponet after doubClicl
*/
private final static class JComponentMouseStatusModyfier extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent e) {
if(e.getComponent() instanceof JComponent) {
JComponent jComponent = (JComponent) e.getComponent();
Object propertyValue = jComponent.getClientProperty(JComponentActivationStatus.PROPERTY_KEY);
if(JComponentActivationStatus.ACTIVE.equals(propertyValue)) { //We check that the ACTIVE status is already selected, if so we inactive.
propertyValue = JComponentActivationStatus.INACTIVE; //If so we inactive it.
} else {
propertyValue = JComponentActivationStatus.ACTIVE; // Otherwise we set it as active
}
jComponent.putClientProperty(JComponentActivationStatus.PROPERTY_KEY, propertyValue); // We use the property key form status
}
}
}
/**
* Help class that fire the actions after status is changed
*/
private static final class JComponentStatusPropertyChangeListener<T extends JComponent> implements PropertyChangeListener {
private final JComponenetActivationStatusChangeAction<T> statusChangeAction;
/**
*
*/
public JComponentStatusPropertyChangeListener(JComponenetActivationStatusChangeAction<T> statusChangeAction) {
if(statusChangeAction == null) {
throw new IllegalArgumentException("action can not be null at this point");
}
this.statusChangeAction = statusChangeAction;
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
if(JComponentActivationStatus.PROPERTY_KEY.equals(evt.getPropertyName())) {
if(JComponentActivationStatus.ACTIVE.equals(evt.getNewValue())) {
statusChangeAction.onActivation((T) evt.getSource());
}
if(JComponentActivationStatus.INACTIVE.equals(evt.getNewValue())){
statusChangeAction.onDeactivation((T) evt.getSource());
}
}
}
}
}
That class contain two public static method, that allow the developer to add the functionality to mange status to any jComponent object, add subscribe the action handler if any change occur.
At the end we have the main method that test our solution
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JLabel l1 = new JLabel("Label 1");
JLabel l2 = new JLabel("Label 2");
JLabel l3 = new JLabel("Label 3");
panel.setBackground(Color.CYAN);
addMouseStatusControl(panel);
addMouseStatusControl(l1);
addMouseStatusControl(l2);
addMouseStatusControl(l3);
JComponenetActivationStatusChangeAction<JLabel> activeBackground = new JComponenetActivationStatusChangeAction<JLabel>() {
#Override
public void onActivation(JLabel object) {
object.setOpaque(true);
object.setBackground(Color.YELLOW);
}
#Override
public void onDeactivation(JLabel object) {
object.setOpaque(false);
object.setBackground(object.getParent().getBackground());
}
};
JComponenetActivationStatusChangeAction<JPanel> deactivateChildrens = new JComponenetActivationStatusChangeAction<JPanel>() {
#Override
public void onDeactivation(JPanel object) {
}
#Override
public void onActivation(JPanel object) {
for(Component component : object.getComponents()) {
if(component instanceof JComponent) {
((JComponent) component).putClientProperty(JComponentActivationStatus.PROPERTY_KEY,JComponentActivationStatus.INACTIVE);
}
}
}
};
addActivationStatusChangeAction(l1, activeBackground);
addActivationStatusChangeAction(l2, activeBackground);
addActivationStatusChangeAction(l3, activeBackground);
addActivationStatusChangeAction(panel, deactivateChildrens);
panel.add(l1);
panel.add(l2);
panel.add(l3);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
The solution is very flexible and extendable in case you will need to add more labels.
The example is for those that want to learn. Any comment would be appreciate.