JPopoupMenu covered by window's title - java

I am writing a Main-menu + Network traffic monitor. My system runs Linux Cinnamon Mint.
The problem is that the application's title always appears over the menu.
When I click over the iconized window, JFrame opens and the JPopoupMenu appears over it.
While the mouse pointer is inside the panel, the title hovers above the iconized window, as it should, but when I move it over the menu it doesn't disappear.
The mouse pointer wasn't captured but it was inside the panel (over the iconized window) in the left picture and over the menu in the right one.
If I do the same, but without showing the menu (JFrame's window with the same size as the menu), the title only appears when the mouse pointer is inside the panel.
I have tried different components for 'popupMenu.setInvoker(Component)' but in the few cases where the problem disappears the menu loses focus.
Thank you beforehand for your help.
Here is a SSCCE (Main.java) that I cobbled together so you can test the code:
// To run: javac Main.java; java Main
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.WindowConstants;
/**
*
* #author Manuel Iglesias Alonso glesialo#gmail.com
*/
public class Main extends JFrame {
private final MainMenu mainMenu;
private boolean menuPopupEnabled;
public Main(ImageIcon icon, File rootMenuDirectory) {
super();
menuPopupEnabled = false;
setIconImage(icon.getImage());
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowDeiconified(WindowEvent e) {
super.windowDeiconified(e);
if (menuPopupEnabled) {
mainMenu.popup(MouseInfo.getPointerInfo().getLocation());
}
}
});
mainMenu = new MainMenu(this, rootMenuDirectory);
pack(); // Before setPreferredSize: smaller window size.
setPreferredSize(new Dimension(0, 0)); // Window is always hidden behind menu, the smaller the better.
setVisible(true);
}
private class MainMenu {
private final int panelHeight = 25;
private final int iconizedWindowWidthPanelHeightRatio = 5; // Iconized window's width / Iconized window' height
private final JFrame frame;
private final File rootMenuDirectory;
private final Rectangle graphicsBounds;
private PopupMenuInFrame popupMenu;
private class PopupMenuInFrame extends JPopupMenu {
#Override
protected void firePopupMenuWillBecomeInvisible() {
super.firePopupMenuWillBecomeInvisible();
frame.setExtendedState(JFrame.ICONIFIED);
}
}
/**
*
* #param rootMenuDirectory Directory where menu files are to be found.
*/
public MainMenu(JFrame frame, File rootMenuDirectory) {
this.frame = frame;
this.rootMenuDirectory = rootMenuDirectory;
graphicsBounds = frame.getGraphicsConfiguration().getBounds();
}
private void newMenu() {
popupMenu = new PopupMenuInFrame();
JMenuItem menuItem = new JMenuItem("1st popup menu item");
menuItem.setToolTipText("1st ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("2nd popup menu item");
menuItem.setToolTipText("2nd popup menu item ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("3rd A popup menu item");
menuItem.setToolTipText("menu item ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("4th popup menu item");
menuItem.setToolTipText("4th popup menu item menu item ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("5th popup menu item");
menuItem.setToolTipText("ToolTip");
popupMenu.add(menuItem);
menuItem = new JMenuItem("6th popup menu item");
menuItem.setToolTipText("popup menu item menu item ToolTip");
popupMenu.add(menuItem);
}
public void popup(Point mousePointerPosition) {
Point menuPosition;
newMenu();
popupMenu.setInvoker(frame.getContentPane());
menuPosition = new Point(mousePointerPosition.x, mousePointerPosition.y);
if (mousePointerPosition.x < iconizedWindowWidthPanelHeightRatio * panelHeight) { //If pointer near leftmost border (within width of iconized window).
if (mousePointerPosition.y < (panelHeight + 1)
|| mousePointerPosition.y > (graphicsBounds.height - panelHeight - 1)) { //If pointer inside a top or bottom panel
menuPosition.x = 1; // Position: near left border.
}
}
if (mousePointerPosition.y < (panelHeight + 1)) { //If pointer inside a top panel (within panel's height + 1)
menuPosition.y = panelHeight + 1; //Menu's top edge just below the panel's lower edge.
} else {
if (mousePointerPosition.y > (graphicsBounds.height - panelHeight - 1)) { //If pointer inside a bottom panel (within panel's height + 1)
menuPosition.y = graphicsBounds.height - popupMenu.getPreferredSize().height - panelHeight - 1; //Menu's lower edge just above the panel's upper edge.
}
}
frame.setLocation(menuPosition.x + 5, menuPosition.y + 5); // + 5 to make sure window is hidden behind popupMenu.
popupMenu.setLocation(menuPosition.x, menuPosition.y);
popupMenu.setVisible(true);
}
}
public static void main(String[] args) {
final ImageIcon icon;
final File rootMenuDirectory;
icon = new ImageIcon();
rootMenuDirectory = new File("");
Main frame = new Main(icon, rootMenuDirectory);
frame.setTitle("Test title");
try {
Thread.sleep(500);
} catch (Exception e) {
}
if (!GraphicsEnvironment.isHeadless()) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
frame.setExtendedState(JFrame.ICONIFIED); // Start iconified. If setExtendedState used out of run(), window's events are blocked.
frame.menuPopupEnabled = true; // Menu can pop from now on.
}
});
} else {
System.exit(1);
}
}
}
PS: I have modified the SSCCE adding tool-tips to the menu items. There is another problem: Sometimes (while moving the mouse pointer, up and down, over the menu items) the tool-tips do not appear complete:
Nobody helps? :-(
I have almost finished the application. I have added an extra menu item, 'MainMenu: About', so that that item is the only part covered by the damn vindow title (title disappears once the menu operates: submenus, tooltips...). The problem with incomplete tooltips also happens with oracle' tutorial examples (if I add tooltips) so it has nothing to do with my code.
Here is a picture of the running menu (It will move to just over the iconized window when it is on the far left of the panel: first startup application):
The application sends an 'sticky' hint to the Window Manager and the window appears in all workspaces.

Related

Resize JPanel and JPopupMenu automatically on JPanel expand

I am currently facing a small issue that goes like this: I have a button which, when clicked, will trigger the display of a JPopupMenu under it ( I grab the location of the button, substract a bit from it's height and display the JPopupMenu). This is all made in NetBeans with the GUI builder.
The JPopupMenu is composed of several JPanels, which contain a JLabel, a Button, a TextField and a CheckBox. Those JPanels, I want them to be first initialized in a "minimized" mode( display only the label), but, when the user clicks on them, to expand and display the other components as well. On a second click, the JPanel will revert to the "minimized" state.
Now, I don't know exactly where the issue is, whether in the way the JPanel is resized or not, but although when I click the button the popup menu is displayed correctly and everything else, if I expand a JPanel inside it, the popup menu does not get resized -> it has the same width/height no matter what I do. I tried to change the Layout Manager used by JPopupMenu to FlowLayout,BoxLayout, but ultimately they had no effect. Now, a few snippets of points of interest in the code:
public class WifiItem extends javax.swing.JPanel {
private final Dimension maxDimension;
private final Dimension minDimension;
private boolean maximized;
public WifiItem() {
initComponents();
setBorder(BorderFactory.createLineBorder(Color.black, 1));
maxDimension = new Dimension(386, 62);
minDimension = new Dimension(386, 32);
maximized = false;
setSize(minDimension);
setPreferredSize(minDimension);
setMinimumSize(minDimension);
setMaximumSize(minDimension);
this.setPreferredSize(minDimension);
this.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (maximized) {
setToMin();
} else {
setToMax();
}
}
});
}
public final void setToMax() {
setSize(maxDimension);
setPreferredSize(maxDimension);
setMinimumSize(maxDimension);
setMaximumSize(maxDimension);
maximized = true;
getParent().revalidate();
}
public final void setToMin() {
setSize(minDimension);
setPreferredSize(minDimension);
setMinimumSize(minDimension);
setMaximumSize(minDimension);
maximized = false;
getParent().revalidate();
}
This is where I build the JPopupMenu and set up the display.
public class WifiConnections {
private static final List<WifiItem> connectionsList = new ArrayList<>();
public static JPopupMenu displayPanel;
public WifiConnections() {
displayPanel = new JPopupMenu();
displayPanel.setLayout(new BoxLayout(displayPanel, BoxLayout.Y_AXIS));
WifiItem newItem = new WifiItem();
newItem.setConnectionId("Connection 1.");
WifiItem newItem2 = new WifiItem();
newItem2.setConnectionId("Connection 2.");
connectionsList.add(newItem);
connectionsList.add(newItem2);
connectionsList.forEach((item) -> {
displayPanel.add(item);
});
}
public void displayPopup(Point p) {
displayPanel.setLocation(p.x, p.y + 34);
displayPanel.setVisible(true);
}
public void hidePopup() {
displayPanel.setVisible(false);
}
}
As you can see, if I expand one item, the other one gets covered and the popup does not resize to fit the JPanels, and I am really at a loss at how to continue.

Main class not found Java program

I thought i added my main code in this program but it did not recognize. Am I missing it? I get the error paint.Paintbrush class wasn't found in PaintBrush project. I'm not sure where I can include the main class in the beginning without getting an error being returned. Thank you for any advice or help given.
package PaintBrush;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
/**
*
* #author Olive
*/
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
public class Paintbrush extends Applet implements MouseListener,
MouseMotionListener,
ActionListener
{
// component declarations
Button blackButton;
Button redButton;
Button greenButton;
Button blueButton;
Button penButton;
Button lineButton;
Button eraserButton;
Button clearButton;
Button squareButton;
Button ovalButton;
Button fillSquareButton;
Button fillOvalButton;
Label colourTitle;
Label colourDisplay;
Label toolTitle;
Label toolDisplay;
// required variables to store settings
Color currentColour;
int toolType;
// variables to store interim coordinates
int oldX = -1;
int oldY = -1;
public void init()
{
// create all the buttons
blackButton = new Button("Black");
redButton = new Button("Red");
greenButton = new Button("Green");
blueButton = new Button("Blue");
penButton = new Button("Pen");
lineButton = new Button("Line");
eraserButton = new Button("Eraser");
clearButton = new Button("Clear");
squareButton = new Button("Square");
ovalButton = new Button("Oval");
fillSquareButton = new Button("F Square");
fillOvalButton = new Button("F Oval");
// add action listners for all the buttons
blackButton.addActionListener(this);
redButton.addActionListener(this);
greenButton.addActionListener(this);
blueButton.addActionListener(this);
penButton.addActionListener(this);
lineButton.addActionListener(this);
eraserButton.addActionListener(this);
clearButton.addActionListener(this);
squareButton.addActionListener(this);
ovalButton.addActionListener(this);
fillSquareButton.addActionListener(this);
fillOvalButton.addActionListener(this);
// create the button bar panel
Panel buttonPanel = new Panel();
buttonPanel.setLayout(new GridLayout(6, 2));
buttonPanel.add(blackButton);
buttonPanel.add(redButton);
buttonPanel.add(greenButton);
buttonPanel.add(blueButton);
buttonPanel.add(penButton);
buttonPanel.add(lineButton);
buttonPanel.add(eraserButton);
buttonPanel.add(clearButton);
buttonPanel.add(squareButton);
buttonPanel.add(ovalButton);
buttonPanel.add(fillSquareButton);
buttonPanel.add(fillOvalButton);
// create the status bar panel
colourTitle = new Label("Colour: ");
currentColour = Color.black;
colourDisplay = new Label("Black");
toolTitle = new Label(" Selected Tool: ");
toolType = 0;
toolDisplay = new Label("Pen (Scribble)");
Panel statusPanel = new Panel();
statusPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
statusPanel.add(colourTitle);
statusPanel.add(colourDisplay);
statusPanel.add(toolTitle);
statusPanel.add(toolDisplay);
// arrange final panels in a border layout
this.setLayout(new BorderLayout());
this.add(buttonPanel, BorderLayout.WEST);
this.add(statusPanel, BorderLayout.NORTH);
// add mouse listners to applet
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
// event handling for when an action occurs (in this case, whenever
// a button is pressed)
public void actionPerformed(ActionEvent e)
{
// get the local graphics page to draw on
Graphics page = this.getGraphics();
// red button pressed: set the current colour to red
// and update the status display
if (e.getSource().equals(redButton))
{
currentColour = Color.red;
colourDisplay.setText("Red");
}
// blue button pressed: set the current colour to blue
// and update the status display
if (e.getSource().equals(blueButton))
{
currentColour = Color.blue;
colourDisplay.setText("Blue");
}
// green button pressed: set the current colour to green
// and update the status display
if (e.getSource().equals(greenButton))
{
currentColour = Color.green;
colourDisplay.setText("Green");
}
// black button pressed: set the current colour to black
// and update the status display
if (e.getSource().equals(blackButton))
{
currentColour = Color.black;
colourDisplay.setText("Black");
}
// pen button pressed: set the selected tool to '0'
// and update the status display
if (e.getSource().equals(penButton))
{
toolType = 0;
toolDisplay.setText("Pen (Scribble)");
}
// eraser button pressed: set the selected tool to '1'
// and update the status display
if (e.getSource().equals(eraserButton))
{
toolType = 1;
toolDisplay.setText("Eraser");
}
// square button pressed: set the selected tool to '2'
// and update the status display
if (e.getSource().equals(squareButton))
{
toolType = 2;
toolDisplay.setText("Square");
}
// oval button pressed: set the selected tool to '3'
// and update the status display
if (e.getSource().equals(ovalButton))
{
toolType = 3;
toolDisplay.setText("Oval");
}
// filled square button pressed: set the selected tool to '4'
// and update the status display
if (e.getSource().equals(fillSquareButton))
{
toolType = 4;
toolDisplay.setText("Filled Square");
}
// filled oval button pressed: set the selected tool to '5'
// and update the status display
if (e.getSource().equals(fillOvalButton))
{
toolType = 5;
toolDisplay.setText("Filled Oval");
}
// clear button pressed: get the size of the applet and draw
// a clearing rectangle over it, to clear the screen
if (e.getSource().equals(clearButton))
{
Dimension size = this.getSize();
page.clearRect(0, 0, size.width, size.height);
}
// line button pressed: set the selected tool to '6'
// and update the status display
if (e.getSource().equals(lineButton))
{
toolType = 6;
toolDisplay.setText("Line");
}
}
// event handling for when the mouse button is first pressed
public void mousePressed(MouseEvent e)
{
// store the coordinates for future reference
oldX = e.getX();
oldY = e.getY();
}
// event handling for when the mouse is dragged with the button
// held down
public void mouseDragged(MouseEvent e)
{
Graphics page = this.getGraphics();
// scribble tool: draw a line from the old coordinates to the
// new ones
if (toolType == 0)
{
page.setColor(currentColour);
page.drawLine(oldX, oldY, e.getX(), e.getY());
oldX = e.getX();
oldY = e.getY();
}
// eraser tool: clear a small rectangles' worth at the specified
// coordinate
if (toolType == 1)
{
page.clearRect(e.getX(), e.getY(), 10, 10);
page.setColor(currentColour);
}
}
// resolve method: used to swap two numbers around so the
// smaller is always in element 0, and the larger in element
// 1, of the returned array
public int[] resolve(int newC, int oldC)
{
int start, end;
if (newC < oldC)
{
start = newC;
end = oldC;
}
else
{
start = oldC;
end = newC;
}
int[] blah = {start, end};
return blah;
}
// event handling for when the mouse button is released
public void mouseReleased(MouseEvent e)
{
// get the applet's Graphics page
Graphics page = this.getGraphics();
// resolve the coordinates so that the smaller of the x and y
// coordinates can be picked out easily
int newX = e.getX();
int newY = e.getY();
int[] x = resolve(newX, oldX);
int[] y = resolve(newY, oldY);
// tool type 2: draw a rectangle
if (toolType == 2)
{
page.setColor(currentColour);
page.drawRect(x[0], y[0], (x[1] - x[0]), (y[1] - y[0]));
}
// tool type 3: draw an oval
if (toolType == 3)
{
page.setColor(currentColour);
page.drawOval(x[0], y[0], (x[1] - x[0]), (y[1] - y[0]));
}
// tool type 4: draw a filled rectangle
if (toolType == 4)
{
page.setColor(currentColour);
page.fillRect(x[0], y[0], (x[1] - x[0]), (y[1] - y[0]));
}
// tool type 5: draw a filled oval
if (toolType == 5)
{
page.setColor(currentColour);
page.fillOval(x[0], y[0], (x[1] - x[0]), (y[1] - y[0]));
}
// tool type 6: draw the line
if (toolType == 6)
{
page.setColor(currentColour);
page.drawLine(oldX, oldY, newX, newY);
}
}
// unused methods from listener interfaces
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
}
It looks like you're referencing the Paintbrush class in the paint package but the Paintbrush class itself declares package PaintBrush. You didn't show how you're telling NetBeans what applet to run. But try changing the package statement to package paint and see if that works.

java take mouse coordinates from natural screen and display them in a GUI [duplicate]

This question already has an answer here:
How do I make my JWindow window always stay focused
(1 answer)
Closed 7 years ago.
First of all i don't know good english.
I want to make a window and have 2 labels and 2 fields. One label for x-coordinate and 1 for y-coordinate.Fields will show the x-y coordinates.
Coordinates are from mouse from full screen (meaning outside from window).
I prefer to be on clicking but i have read from other answers and questions that this will not act as we want (because it loses focus).So i tried not to be on clicking
I want help with my code because it has 2 problems-mistakes:
1) window can't close
2)when mouse is not moving fields take the same coordinates forever and i want take 1 time the coordinates and don't take the same until it moves.
here is the full code:
package mouseClick;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class MouseEventDemo extends Frame implements MouseListener {
// Private variables
private TextField tfMouseX; // mouse-click-x
private TextField tfMouseY; // mouse-click-y
// Constructor
public MouseEventDemo() {
//handle the close-window button.
WindowDestroyer listener =new WindowDestroyer();
addWindowListener(listener);
setLayout(new FlowLayout()); // sets layout
// Label
add(new Label("X-Click: ")); // adds component
// TextField
tfMouseX = new TextField(10); // 10 columns
tfMouseX.setEditable(false); // read-only
add(tfMouseX); // adds component
// Label
add(new Label("Y-Click: ")); // adds component
// TextField
tfMouseY = new TextField(10);
tfMouseY.setEditable(false); // read-only
add(tfMouseY); // adds component
// fires the MouseEvent
addMouseListener(this);
setTitle("MouseEvent Demo"); // sets title
setSize(350, 100); // sets initial size
setVisible(true); // shows
}
public static void main(String[] args) {
new MouseEventDemo();
}
// MouseEvent handlers
public void mouseClicked(MouseEvent e) {
while (true){
tfMouseX.setText(Integer.toString(xmouse()));
tfMouseY.setText(Integer.toString(ymouse()));
}
}
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
public void mouseEntered(MouseEvent e) { }
public void mouseExited(MouseEvent e) { }
public class WindowDestroyer extends WindowAdapter {
public void windowClosing (WindowEvent e) {
System.exit(0);
}
}
public int xmouse() {
Point simiox = MouseInfo.getPointerInfo().getLocation();
int x= (int) simiox.getX();
return x;
}
public int ymouse() {
Point simioy = MouseInfo.getPointerInfo().getLocation();
int y=(int) simioy.getY();
return y;
}
}
in order to close the window, use
windowVariable.seDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
where windowVariable is the variable for you JFrame
EDIT:
For returning the value only once, try using a for loop and a hasMoved boolean. For instance,
for (int i = 0; i < 1; i++){
tfMouseX.setText(Integer.toString(xmouse()));
if (hasMoved == true)
i = -1;
}
then do the same for the y.
this basically checks to see if the mouse has moved, and if it has not, it will set the label only once. If it has, it will update the label.

Dynamically initializing JButtons with unique ImageIcons

This is my first attempt at using a GUI layout in Java. I am trying to create a simple memory card game, where the user flips over two cards, and tries to get a match, and if there's no match they flip back over, if there's a match they stay flipped until you get all the matches. I might have made it hard on myself though in that I made the whole game dynamic to the constructor variables that define the number of columns and rows of cards. I thought this was better than hard-coding a certain value in, but now I'm having trouble putting the images in my img folder onto my cards.
I understand that variables of variables are not permitted in Java & this is really hard for me to adapt to as a ColdFusion developer. Can you help me think of ways to accomplish this this the proper way in Java?
Here is a simplified version of my code.
import javax.swing.JFrame;
public class MemoryApp
{
public static void main(String args[])
{
//Creates a new game with 3 columns and 4 rows
final CardGame myGame = new CardGame(3, 4);
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI(myGame.getCols(), myGame.getRows());
}
});
}
private static void createAndShowGUI(int c, int r) {
//Create and set up the window.
Window frame = new Window("GridLayoutDemo", c, r);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set up the content pane.
frame.addComponentsToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
}
Card game class:
public class CardGame
{
private int cols, rows;
public CardGame(int c, int r)
{
cols = c;
rows = r;
}
public int getCols(){
return cols;
}
public int getRows(){
return rows;
}
}
The window with the grid layout:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSeparator;
public class Window extends JFrame
{
private int cols, rows;
GridLayout windowGrid = new GridLayout(1,1);
public Window(String t, int c, int r)
{
super(t);
cols = c;
rows = r;
windowGrid.setColumns(c);
windowGrid.setRows(r);
}
public void addComponentsToPane(final Container pane)
{
final JPanel compsToExperiment = new JPanel();
compsToExperiment.setLayout(windowGrid);
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(cols,rows));
int countCard = (cols * rows) / 2;
/**
* Add buttons to experiment with Grid Layout.
* This is where I'd like to be able to loop through
* countCard and create the required number of buttons
* as well as put images on the buttons like so:
*
* ImageIcon image1 = new ImageIcon(getClass().getResource("card1.png"));
* through
* ImageIcon image1 = new ImageIcon(getClass().getResource("card" & cardCount & ".png"));
*
* Below is how I would attempt this in ColdFusion- I know
* the variable of variables syntax is invalid, it is just
* to show you what I mean.
*/
// for(int i = 0; i < countCard; i++;)
// {
// compsToExperiment.add(new JButton("../img/card" & i & ".png"));
// ImageIcon variables["image" & i] = new ImageIcon(getClass().getResource("card" & i & ".png"));
// imageButton.setIcon(variables["image" & i]);
// etc. with ButtonClickEventHandler, haven't gotten that far yet
// }
pane.add(compsToExperiment, BorderLayout.NORTH);
pane.add(new JSeparator(), BorderLayout.CENTER);
}
}
Based on the code commented-out code that you posted so far, one approach could be like this:
public class Window extends JFrame
{
...
// A java.util.List that stores all the buttons, so
// that their icons may be changed later
private List<JButton> buttons = new ArrayList<JButton>();
// A java.util.List that stores all the ImageIcons that
// may be placed on the buttons
private List<ImageIcon> imageIcons = new ArrayList<ImageIcon>();
public void addComponentsToPane(final Container pane)
{
...
for(int i = 0; i < countCard; i++;)
{
// String concatenation is done with "+" in Java, not with "&"
String fileName = "card" + i + ".png";
// Create the icon and the button containing the icon
ImageIcon imageIcon = new ImageIcon(getClass().getResource(fileName));
JButton button = new JButton(imageIcon);
// Add the button to the main panel
compsToExperiment.add(button);
// Store the button and the icon in the lists
// for later retrieval
imageIcons.add(imageIcon);
buttons.add(button);
// Attach an ActionListener to the button that will
// be informed when the button was clicked.
button.addActionListener(createActionListener(i));
}
}
private ActionListener createActionListener(final int cardIndex)
{
return new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
clickedCardButton(cardIndex);
}
};
}
private void clickedCardButton(int cardIndex)
{
System.out.println("Pressed button for card "+cardIndex);
// Here you can change the icons of the buttons or so...
JButton button = buttons.get(cardIndex);
ImageIcon imageIcon = imageIcons.get(cardIndex);
....
}
You mentioned that this is your first attempt to build a GUI with Java. So I assume that this is only intended for "practicing". If your intention was to build a "real application", you should rather consider some Model-View-Controller (MVC) approach for this.

How do I create a right click context menu in Java Swing?

I'm currently creating a right-click context menu by instantiating a new JMenu on right click and setting its location to that of the mouse's position... Is there a better way?
You are probably manually calling setVisible(true) on the menu. That can cause some nasty buggy behavior in the menu.
The show(Component, int x, int x) method handles all of the things you need to happen, (Highlighting things on mouseover and closing the popup when necessary) where using setVisible(true) just shows the menu without adding any additional behavior.
To make a right click popup menu simply create a JPopupMenu.
class PopUpDemo extends JPopupMenu {
JMenuItem anItem;
public PopUpDemo() {
anItem = new JMenuItem("Click Me!");
add(anItem);
}
}
Then, all you need to do is add a custom MouseListener to the components you would like the menu to popup for.
class PopClickListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger())
doPop(e);
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger())
doPop(e);
}
private void doPop(MouseEvent e) {
PopUpDemo menu = new PopUpDemo();
menu.show(e.getComponent(), e.getX(), e.getY());
}
}
// Then on your component(s)
component.addMouseListener(new PopClickListener());
Of course, the tutorials have a slightly more in-depth explanation.
Note: If you notice that the popup menu is appearing way off from where the user clicked, try using the e.getXOnScreen() and e.getYOnScreen() methods for the x and y coordinates.
This question is a bit old - as are the answers (and the tutorial as well)
The current api for setting a popupMenu in Swing is
myComponent.setComponentPopupMenu(myPopupMenu);
This way it will be shown automagically, both for mouse and keyboard triggers (the latter depends on LAF). Plus, it supports re-using the same popup across a container's children. To enable that feature:
myChild.setInheritsPopupMenu(true);
There's a section on Bringing Up a Popup Menu in the How to Use Menus article of The Java Tutorials which explains how to use the JPopupMenu class.
The example code in the tutorial shows how to add MouseListeners to the components which should display a pop-up menu, and displays the menu accordingly.
(The method you describe is fairly similar to the way the tutorial presents the way to show a pop-up menu on a component.)
The following code implements a default context menu known from Windows with copy, cut, paste, select all, undo and redo functions. It also works on Linux and Mac OS X:
import javax.swing.*;
import javax.swing.text.JTextComponent;
import javax.swing.undo.UndoManager;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class DefaultContextMenu extends JPopupMenu
{
private Clipboard clipboard;
private UndoManager undoManager;
private JMenuItem undo;
private JMenuItem redo;
private JMenuItem cut;
private JMenuItem copy;
private JMenuItem paste;
private JMenuItem delete;
private JMenuItem selectAll;
private JTextComponent textComponent;
public DefaultContextMenu()
{
undoManager = new UndoManager();
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
addPopupMenuItems();
}
private void addPopupMenuItems()
{
undo = new JMenuItem("Undo");
undo.setEnabled(false);
undo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
undo.addActionListener(event -> undoManager.undo());
add(undo);
redo = new JMenuItem("Redo");
redo.setEnabled(false);
redo.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
redo.addActionListener(event -> undoManager.redo());
add(redo);
add(new JSeparator());
cut = new JMenuItem("Cut");
cut.setEnabled(false);
cut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
cut.addActionListener(event -> textComponent.cut());
add(cut);
copy = new JMenuItem("Copy");
copy.setEnabled(false);
copy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
copy.addActionListener(event -> textComponent.copy());
add(copy);
paste = new JMenuItem("Paste");
paste.setEnabled(false);
paste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
paste.addActionListener(event -> textComponent.paste());
add(paste);
delete = new JMenuItem("Delete");
delete.setEnabled(false);
delete.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
delete.addActionListener(event -> textComponent.replaceSelection(""));
add(delete);
add(new JSeparator());
selectAll = new JMenuItem("Select All");
selectAll.setEnabled(false);
selectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
selectAll.addActionListener(event -> textComponent.selectAll());
add(selectAll);
}
private void addTo(JTextComponent textComponent)
{
textComponent.addKeyListener(new KeyAdapter()
{
#Override
public void keyPressed(KeyEvent pressedEvent)
{
if ((pressedEvent.getKeyCode() == KeyEvent.VK_Z)
&& ((pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0))
{
if (undoManager.canUndo())
{
undoManager.undo();
}
}
if ((pressedEvent.getKeyCode() == KeyEvent.VK_Y)
&& ((pressedEvent.getModifiersEx() & Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()) != 0))
{
if (undoManager.canRedo())
{
undoManager.redo();
}
}
}
});
textComponent.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent releasedEvent)
{
handleContextMenu(releasedEvent);
}
#Override
public void mouseReleased(MouseEvent releasedEvent)
{
handleContextMenu(releasedEvent);
}
});
textComponent.getDocument().addUndoableEditListener(event -> undoManager.addEdit(event.getEdit()));
}
private void handleContextMenu(MouseEvent releasedEvent)
{
if (releasedEvent.getButton() == MouseEvent.BUTTON3)
{
processClick(releasedEvent);
}
}
private void processClick(MouseEvent event)
{
textComponent = (JTextComponent) event.getSource();
textComponent.requestFocus();
boolean enableUndo = undoManager.canUndo();
boolean enableRedo = undoManager.canRedo();
boolean enableCut = false;
boolean enableCopy = false;
boolean enablePaste = false;
boolean enableDelete = false;
boolean enableSelectAll = false;
String selectedText = textComponent.getSelectedText();
String text = textComponent.getText();
if (text != null)
{
if (text.length() > 0)
{
enableSelectAll = true;
}
}
if (selectedText != null)
{
if (selectedText.length() > 0)
{
enableCut = true;
enableCopy = true;
enableDelete = true;
}
}
if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor) && textComponent.isEnabled())
{
enablePaste = true;
}
undo.setEnabled(enableUndo);
redo.setEnabled(enableRedo);
cut.setEnabled(enableCut);
copy.setEnabled(enableCopy);
paste.setEnabled(enablePaste);
delete.setEnabled(enableDelete);
selectAll.setEnabled(enableSelectAll);
// Shows the popup menu
show(textComponent, event.getX(), event.getY());
}
public static void addDefaultContextMenu(JTextComponent component)
{
DefaultContextMenu defaultContextMenu = new DefaultContextMenu();
defaultContextMenu.addTo(component);
}
}
Usage:
JTextArea textArea = new JTextArea();
DefaultContextMenu.addDefaultContextMenu(textArea);
Now the textArea will have a context menu when it is right-clicked on.
I will correct usage for that method that #BullyWillPlaza suggested. Reason is that when I try to add add textArea to only contextMenu it's not visible, and if i add it to both to contextMenu and some panel it ecounters: Different parent double association if i try to switch to Design editor.
TexetObjcet.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)){
contextmenu.add(TexetObjcet);
contextmenu.show(TexetObjcet, 0, 0);
}
}
});
Make mouse listener like this for text object you need to have popup on. What this will do is when you right click on your text object it will then add that popup and display it. This way you don't encounter that error. Solution that #BullyWillPlaza made is very good, rich and fast to implement in your program so you should try it our see how you like it.

Categories

Resources