MouseEntered and MouseExited not working - java

I am having trouble with mouseExited and mouseEntered events. They are not executed. And I know it is because of the setLayout. If I comment it, the problem dissapears.This is my code :
public class Test{
public static void main(String[] args) {
new Test();
}
public Test() {
JFrame frame = new JFrame();
frame.setContentPane(new Pane());
frame.getContentPane().setBackground(Color.GRAY);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(true);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public class Pane extends JPanel{
public Pane(){
ImageIcon start = new ImageIcon("Start.png");
JLabel bStart = new JLabel(start);
ImageIcon exit = new ImageIcon("Exit.png");
JLabel bExit = new JLabel(exit);
setLayout(new BorderLayout());
add(bStart, BorderLayout.CENTER);
bStart.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e){
ImageIcon image = new ImageIcon("Start-Pressed.png");
bStart.setIcon(image);
Container parent = bStart.getParent();
parent.remove(bStart);
add(bExit);
parent.revalidate();
parent.repaint();
}
public void mouseEntered(MouseEvent arg0) {
ImageIcon image = new ImageIcon("Start-Hover.png");
bStart.setIcon(image);
}
public void mouseExited(MouseEvent arg0) {
ImageIcon image = new ImageIcon("Start.png");
bStart.setIcon(image);
}
});
bExit.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
System.exit(0);
}
public void mouseEntered(MouseEvent e){
ImageIcon image = new ImageIcon("Exit-Hover.png");
bExit.setIcon(image);
}
public void mouseExited(MouseEvent e){
ImageIcon image = new ImageIcon("Exit.png");
bExit.setIcon(image);
}
});
}
}
}

And i know it is because of the setLayout. If i comment it, the problem dissapears.
I doubt the layout is the problem. If the component appears, then the layout manager has nothing to do with how MouseEvents are generated.
From you code is looks like you are trying to provide rollover effects. Instead of using a JLabel for this you can use a JButton and set Icons for the different rollover effects:
button.setBorderPainted( false );
button.setRolloverEnabled( true );
button.setRolloverIcon( ... );
button.setRolloverSelectedIcon(...);
button.setSelectedIcon(...);
Then there is no need to manage the MouseListener as the UI will do it for you.
To handle a mousePressed you should then be using an ActionListener on the JButton. Read the section from the Swing tutorial on How to Write an ActionListener for more information.

Related

How do you make a JFrame intangible?

Im a real novice at java coding and for just a little project I'd like the following code to be untouchable eg. anything behind the frame(and its contents) can be clicked on. But I don't know how to do it! I've searched everywhere but haven't found anything.
import java.awt.*;
import java.swing.*;
public class swag {
static Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
public static void main(String[] args)throws Exception{
JLabel lb = new JLabel();
lb.setFont(new Font("Century Gothic",Font.PLAIN,50));
lb.setHorizontalAlignment(SwingConstants.CENTER);
lb.setForeground(Color.WHITE);
lb.setBackground(Color.BLACK);
JFrame f = new JFrame();
f.setSize(dim.width,100);
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
f.setUndecorated(true);
f.add(lb);
f.setVisible(true);
int r=255;int g=0;int b=0;
int a=80;int t=15;
while(true){
while(true){
lb.setText((System.currentTimeMillis()+""));
f.setBackground(new Color(r--,g++,0,a));
Thread.sleep(t);
if(r==0&&g==255){break;}
} while(true){
lb.setText((System.currentTimeMillis()+""));
f.setBackground(new Color(0,g--,b++,a));
Thread.sleep(t);
if(g==0&&b==255){break;}
} while(true){
lb.setText((System.currentTimeMillis()+""));
f.setBackground(new Color(r++,0,b--,a));
Thread.sleep(t);
if(b==0&&r==255){break;}
}}}
}//class
Note: haven't worked on efficiency yet :)
Read about the glass pane of JFrame. Using it you are able to show the UI components but block all user interactions.
Example:
public class FreezePane extends JComponent {
public FreezePane() {
// trap mouse, key, and focus events
addMouseListener( new MouseAdapter() );
addMouseMotionListener( new MouseMotionAdapter() );
addKeyListener( new KeyAdapter() );
addFocusListener( new FocusListener() {
// do not let any component take focus while visible
public void focusLost(FocusEvent e) {
requestFocusInWindow();
}
public void focusGained(FocusEvent e) {}
}
}
}
Then just set the glass pane and make it visible.
JFrame frame = new JFrame();
frame.setGlassPane( new FreePane() );
frame.getGlassPane().setVisible(true);

Focus component after changing content pane of JFrame

I'm changing my JFrame's content pane and simply want to focus a JTextField in the new panel. So I'm doing this:
JPanel pNew = new JPanel();
frame.setContentPane(pNew);
frame.revalidate();
frame.repaint();
public JPanel() {
...
tf.requestFocusInWindow();
}
When I use setVisible(false) and setVisible(true) instead of revalidating and repainting my frame, I get my wished effect, but that's not the way I want to do it.
What else happens in setVisible() but revalidating and repainting?
A CardLayout is typically used to swap panels.
However, even the default implementation of CardLayout does not set focus on the panel when it is swapped. However you can check out Card Layout Focus which will allow you to request focus on the panel when it is switched.
The requestFocusInWindow() method only works on a component that is displayed in a visible frame. So you can't invoke the method in the constructor of the class.
You could use the RequestFocsListener found in Dialog Focus. It will wait until the panel is added to a visible GUI before generating the event.
I got it to work simply by putting the requestFocusInWindow() call in the button's action listener. As camickr mentioned the call needs to be made after the constructor. Here's an example program showing how I got it to work. Hope it helps!
public class PanelRevalidate {
public JFrame frame;
public MyPanel panel1, panel2;
public PanelRevalidate() {
frame = new JFrame();
panel1 = new MyPanel(1);
panel2 = new MyPanel(2);
frame.setContentPane(panel1);
panel1.getSwap().addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
frame.setContentPane(panel2);
frame.revalidate();
panel2.getTextField().requestFocusInWindow();
}
});
panel2.getSwap().addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
frame.setContentPane(panel1);
frame.revalidate();
panel1.getTextField().requestFocusInWindow();
}
});
frame.setVisible(true);
frame.setResizable(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
new PanelRevalidate();
}
});
}
}
And the MyPanel class:
public class MyPanel extends JPanel {
public JTextField tf;
public JButton swap;
public JLabel panel_label;
public MyPanel(int n) {
tf = new JTextField(25);
swap = new JButton("Swap");
panel_label = new JLabel("panel " + n);
add(tf);
add(swap);
add(panel_label);
}
public JButton getSwap() {
return swap;
}
public JTextField getTextField() {
return tf;
}
}

Java ComponentResized - Detect whether user resized the window or it was resized programatically

I have a JFrame in which I remove and add components and each time I do this, I resize the frame accordingly. I added a Component Listener but of course it gets triggered both by the user resizing the window and also by my setSize() methods.
Is there any way to see from the ComponentEvent whether the user resized the window or I did through setSize()?
The posible solutions I found are:
1. Use a flag - boolean resizing - which I set to true before setSize() and to false after that.
2. Add a mouseDragged listener and compare sizes before and after the drag.
The second one is definitely not a good choice. The first one would work but I would like to know if I can find in a simple way whether the user is the one who resized the window or not.
I resize the frame accordingly
Whats wrong with using pack()?
I remove and add components and each time I do this,
Then this is where you should set your Boolean value:
programResize == true:
panel.add(...);
frame.setSize(...); // this should cause the ComponentListener to fire
// the ComponentListener would then use programResize == false;
Or a better option option could be:
component.removeComponentListener(...);
panel.add(...);
frame.setSize(...);
component.addComponentListener(...);
I like this approach better because all the logic based on the manual update is self contained in one place and there is no need to define a Boolean variable.
Is there any way to see from the ComponentEvent whether the user
resized the window or I did through setSize()?
yes it is, use boolean flag reseted by Swing Timer
in the case that user resized window then ComponentListener firing a new event per every pixel, bunch of events
by determine the contianer set(Xxx)Size is this event fired only once time
example about events from ComponentListner
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
public class ComponentEventDemo extends JPanel
implements ComponentListener, HierarchyListener,
ItemListener {
private JFrame frame;
private static final long serialVersionUID = 1L;
private JTextArea display;
private JLabel label;
private JButton button = new JButton("Change Size");
private String newline = "\n";
public ComponentEventDemo() {
display = new JTextArea();
display.setEditable(false);
JScrollPane scrollPane = new JScrollPane(display);
scrollPane.setPreferredSize(new Dimension(350, 200));
label = new JLabel("This is a label", JLabel.CENTER);
label.addComponentListener(this);
JCheckBox checkbox = new JCheckBox("Label visible", true);
checkbox.addItemListener(this);
checkbox.addComponentListener(this);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Dimension dim = frame.getPreferredSize();
if (!dim.equals(new Dimension(800, 600))) {
frame.setPreferredSize(new Dimension(800, 600));
frame.pack();
} else {
frame.setPreferredSize(new Dimension(400, 300));
frame.pack();
}
}
});
JPanel panel = new JPanel(new GridLayout(1, 3));
panel.add(label);
panel.add(checkbox);
panel.add(button);
panel.addComponentListener(this);
frame = new JFrame("ComponentEventDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scrollPane, BorderLayout.CENTER);
frame.add(panel, BorderLayout.PAGE_END);
frame.pack();
frame.setVisible(true);
}
#Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
label.setVisible(true);
label.revalidate();
label.repaint();
} else {
label.setVisible(false);
}
}
protected void displayMessage(String message) {
//If the text area is not yet realized, and
//we tell it to draw text, it could cause
//a text/AWT tree deadlock. Our solution is
//to ensure that the text area is realized
//before attempting to draw text.
// if (display.isShowing()) {
display.append(message + newline);
display.setCaretPosition(display.getDocument().getLength());
//}
}
#Override
public void componentHidden(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
}
#Override
public void componentMoved(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Moved");
}
#Override
public void componentResized(ComponentEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
}
#Override
public void componentShown(ComponentEvent e) {
//displayMessage(e.getComponent().getClass().getName() + " --- Shown");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
ComponentEventDemo componentEventDemo = new ComponentEventDemo();
}
});
}
#Override
public void hierarchyChanged(HierarchyEvent e) {
displayMessage(e.getComponent().getClass().getName() + " --- Hierarchy changed");
}
}

Create a custom function that returns JLabel to main JFrame?

I hope I can remember to include all my details so here it goes.
I'm working with Java and I'm creating my own interface with the main window being a JFrame, the background is attached to the JFrame with a Background image(as JLabel) that fits exactly with the window. Then I have an image that is attached to the background Jlabel to act as a "start" button. My problem is I'd like to create a custom class that will facilitate each buttons functions inside its own class.
so instead of having functions in the main class that will react to the buttons, I'd like to make a class that can be added to the background... here is my code maybe someone could give me an example and I can figure out the rest or point me in the right direction.
The following code contains the original, please provide an example of how you would change it to encapulate eventlisteners in its own class for the Jlabel button
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class pipboy{
public static void main(String[] args){
pipboy pipboy_os = new pipboy();
pipboy_os.runmain();
}
public void runmain(){
//Create and set up the window.
JFrame frame = new JFrame("PIPBOY Research v0.0.03");
//background
ImageIcon background = new ImageIcon("UI/background/default.png");
JLabel label=new JLabel(background);
//radiation animated
ImageIcon animated_loading = new ImageIcon("UI/icon/loading/loading.png");
JLabel animated_icon = new JLabel(animated_loading);
animated_icon.setSize(128, 128);
animated_icon.setLocation(300, 125);
//Buff arm guy icon
ImageIcon icon_loading = new ImageIcon("UI/icon/34.png");
JLabel icon = new JLabel(icon_loading);
icon.setSize(128, 128);
icon.setLocation(300, 50);
label.add(icon);
label.add(animated_icon);
frame.add(label);
//Display the window.
frame.pack();
frame.setVisible(true);
//Full screen
frame.setSize(800,480);
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
//Set default close operation for JFrame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//This is the handler class i made but i want it in its own class with the buff arm icon picure so it can do something specific when the image is pressed
HandlerClass handler = new HandlerClass();
frame.addMouseListener(handler);
frame.addMouseMotionListener(handler);
}
private static class HandlerClass implements MouseListener, MouseMotionListener{
public void mouseClicked(MouseEvent event){
System.out.println(String.format("Clicked at %d,%d", event.getX(), event.getY()));
}
public void mousePressed(MouseEvent event){
}
public void mouseReleased(MouseEvent event){
}
public void mouseEntered(MouseEvent event){
}
public void mouseExited(MouseEvent event){
}
public void mouseDragged(MouseEvent event){
}
public void mouseMoved(MouseEvent event){
}
}
}
Apparently I didn't know how polymorhpism worked in Java but here is my solution (with some names altered)
import javax.swing.*;
class GUItests{
public JFrame mainContainerFrame;
public static void main(String[] args){
GUItests mainController = new GUItests();
mainController.startGUI();
}
public void startGUI(){
mainContainerFrame = new JFrame("test Frame");
mainContainerFrame.setSize(800,480);
mainContainerFrame.pack();
mainContainerFrame.setVisible(true);
mainContainerFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel customButtonVar = customButton();
mainContainerFrame.getContentPane().add(customButtonVar);
}
public JLabel customButton(){
JLabel icon = new JLabel("testing");
icon.setSize(128, 128);
icon.setLocation(300, 50);
return icon;
}
}

How do I call an actionlistener while the slider is moving, not just when I let go of the mouse?

class AngleSlider implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
if (!source.getValueIsAdjusting()) {
double dAngle = (double)source.getValue();
pnlCannon.dCannonAngle=Math.toRadians(dAngle);
pnlCannon.repaint();
}
}
}
This is our current event listener. Is there a different listener required to do what I want?
No, you will only need to remove the getValueIsAdjusting() check. So, this will repaint your cannon when you move your mouse:
class AngleSlider implements ChangeListener {
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider) e.getSource();
double dAngle = (double)source.getValue();
pnlCannon.dCannonAngle=Math.toRadians(dAngle);
pnlCannon.repaint();
}
}
This is another example that shows the same, it will print the value of the slider as you move it:
public static void main(String[] args) {
JFrame frame = new JFrame("Test");
JSlider slider = new JSlider();
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent ce) {
System.out.println(((JSlider) ce.getSource()).getValue());
}
});
frame.add(slider);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
frame.setVisible(true);
}
The !source.getValueIsAdjusting() is preventing the update code form executing.
Why do you think that condition is necessary?

Categories

Resources