How to externalize a MouseListener? - java

(Note: I am aware of the existence of the MouseAdapter-class, but since I am probably overriding all methods later on, the advantage of it is lost?)
I have a class MainProgram.java in which I'm adding several components. Most of them have a Listener (ActionListener, MouseListener, ...), which get's a bit crowded in my main class.
Therefore I am trying to "externalize" those Listeners into their own classes. So far I have used inner classes in my main-class, which makes accessing the variables, components, ... pretty easy and straightforward.
But with the external Listeners I am not sure what is the best way to implement them.
For example, when I want to find out, which of the lables has been clicked, I am getting the event, get the source of the event, cast it to a JLabel and then get the text on the label with which I compare a string!
This works, but seems very prone to errors (what if I change the JLabel-text in my main-class? -> Listener breaks) and pretty unclean.
I've tried to search via google and on StackOverflow for better ways to do this, but only found the inner class approach.
So is there a better way to get access to my components / externalize my listeners?
public class MainProgram extends JFrame {
public MainProgram() {
super("Landing Page");
setSize(400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel westPanel = new JPanel();
JLabel lbl_orderStatus = new JLabel("Order Status");
JLabel lbl_technicalDocu = new JLabel("Technical Documentation");
JLabel lbl_checkReport = new JLabel("Check Report");
MouseListenerBoldFont mouseListenerLabelBoldPlain = new MouseListenerBoldFont();
lbl_orderStatus.addMouseListener(mouseListenerLabelBoldPlain);
lbl_technicalDocu.addMouseListener(mouseListenerLabelBoldPlain);
lbl_checkReport.addMouseListener(mouseListenerLabelBoldPlain);
westPanel.add(lbl_orderStatus);
westPanel.add(lbl_technicalDocu);
westPanel.add(lbl_checkReport);
add(westPanel);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
MainProgram window = new MainProgram();
window.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
The MouseListenerBoldFont.java:
public class MouseListenerBoldFont implements MouseListener{
Object lbl_westPanel;
#Override
public void mouseClicked(MouseEvent e) {
if(((JLabel)e.getSource()).getText().equals("Order Status")){
System.out.println("Order Status clicked");
};
if(((JLabel)e.getSource()).getText().equals("Technical Documentation")){
System.out.println("Technical Documentation clicked");
};
if(((JLabel)e.getSource()).getText().equals("Check Report")){
System.out.println("Check Report clicked");
};
}
#Override
public void mouseEntered(MouseEvent e) {
lbl_westPanel = e.getSource();
((JComponent) lbl_westPanel).setFont(new Font("tahoma", Font.BOLD, 12));
}
#Override
public void mouseExited(MouseEvent e) {
lbl_westPanel = e.getSource();
((JComponent) lbl_westPanel).setFont(new Font("tahoma", Font.PLAIN, 11));
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
}

sure this is not the best way but may be useful for your problem
public class MyLabel extends JLabel implements MouseListener {
public MyLabel() {
addMouseListener(this);
}
public MyLabel(String txt) {
super(txt);
addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
System.out.println(getText() + " clicked");
}
public void mouseEntered(MouseEvent e) {
setFont(new Font("tahoma", Font.BOLD, 12));
}
public void mouseExited(MouseEvent e) {
setFont(new Font("tahoma", Font.PLAIN, 11));
}
public void mousePressed(MouseEvent e) { }
public void mouseReleased(MouseEvent e) { }
}
then
JLabel lbl_orderStatus = new MyLabel("Order Status");
JLabel lbl_technicalDocu = new MyLabel("Technical Documentation");
JLabel lbl_checkReport = new MyLabel("Check Report");
// MouseListenerBoldFont mouseListenerLabelBoldPlain = new MouseListenerBoldFont();
//
// lbl_orderStatus.addMouseListener(mouseListenerLabelBoldPlain);
// lbl_technicalDocu.addMouseListener(mouseListenerLabelBoldPlain);
// lbl_checkReport.addMouseListener(mouseListenerLabelBoldPlain);

My recommendation is to write inline (anonymous-class) handlers that forward the actual handling to another, non-anonymous function. This would give you something like:
JLabel lblOrderStatus = new JLabel("Order Status");
lblOrderStatus.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent evt) {
doWhateverClickOnOrderStatusRequires();
}
});
// much later
private void doWhateverClickOnOrderStatusRequires() { ... }
The name of the external not-quite-handler method (doWhateverClickOnOrderStatusRequires) should capture the task that it attempts to achieve (for example, launchRockets); and with this pattern, you can call the same not-quite-handler method from multiple handlers. Since the compiler will check that the calls are valid a compile-time, there are no fragile string-constants involved.

You probably still want to use a class which extends MouseAdapter, since it can be used as a MouseListener, a MouseMotionListener, and a MouseWheelListener all at once (You just have to add it as all of those into a component). I'm not sure why you need to get the text on a JLabel to detect if it's the one that has been clicked. You should create a class which extends MouseAdapter and make it solely for JLabels, then add it to that JLabel. You should define a custom constructor if you want that takes a JLabel for an argument so that it will automatically know what JLabel is being interacted with. You can then add a method which passes an event to the main class.

Related

How to open new window by clicking label in java?

I want to open a new window when I click the label. By implementing a key pressed listener. But it is not working. Even nothing is happening.
JLabel lblNewLabel_2 = new JLabel("Create New Account!!!!");
lblNewLabel_2.setForeground(Color.GREEN);
lblNewLabel_2.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
Dosomething();
}
});
private void Dosomething() {
hide();
Account account=new Account();
account.visible();
}
protected static void hide() {
frame.hide();
}
You can use JButton as others say and remove its border to make it look like JLabel but if you really want to use JLabel and detect clicks I think you should write a MouseAdapter for it.
JLabel fooLabel = new JLabel("foo");
fooLabel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
doSomething();
}
}
);
You can also override mouseClicked method but in that case the user must not move the cursor while clicking.

Java: Reference to constructor in another class

I am trying to make a program, that automaticly extracts a link from a .json file. I'm new to programming, and I'm trying to organize the code, so other people will be able to understand it more easily.
I have a constructor called Gui, where it adds a close button, and a file explorer with awt. To organize the project, I want to make another class to extract the link, but I can't figure out, how I can refer to the TextField with the file path, in the Gui class's constructor.
I need to get the text from fe in another class.
I have searched the web for hours, but I can't find anything that works for me.
public class Gui extends Frame {
public Gui() {
Frame gui = new Frame(Strings.name);
// add "close" button
Button cls = new Button(Strings.close);
cls.setBounds(30, 30, 100, 30);
gui.add(cls);
cls.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
// file explorer
TextField fe = new TextField(Strings.file);
fe.setBounds(50,100, 200,30);
fe.setLocation(75, 75);
gui.add(fe);
fe.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseClicked(MouseEvent e) {
FileDialog fd = new FileDialog(gui, Strings.cfile, FileDialog.LOAD);
fd.setVisible(true);
fe.setText(fd.getDirectory());
}
});
// make application work
gui.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
gui.setSize(1200, 900);
gui.setLayout(null);
gui.setVisible(true);
}
}
Could try with the following updates
public class Gui extends Frame {
//create an inner class
class MyProcess
{
MyProcess(String s)
{
System.out.println("do something with s="+s);
}
}
public static void main(String args[])
{
new Gui();
}
...
#Override
public void mouseClicked(MouseEvent e) {
FileDialog fd = new FileDialog(gui, "file", FileDialog.LOAD);
fd.setVisible(true);
fe.setText(fd.getDirectory());
//use the inner class as needed
new MyProcess(fe.getText());
}
Possible output on console
do something with s=D:\some_path\
Kindly note that is not mandatory an inner class, could be also an external one. That depends only of your design. Maybe also in the future for graphic interfaces you could do some researches on : JavaFx,Swing maybe Eclipse Graphics Library. Awt library is the most ancient one.
you should put your references to your classes e.g. text outside of your constructor for example,
public class Gui extends Frame {
// your reference
private TextField text;
Gui() {
// now instantiate your textField
text = new TextField();
}
// getter method that returns your textField
public TextField getTextField() {
return text;
}
}
then you can get your text from your gui.
Gui gui = new Gui();
TextField field =gui.getTextField();
I recommend that learn the basics of java programming and then define bigger project for your self.

Mouse entered, mouse exited changing the text on the button on each event

I am trying to connect a button to say "Hi" when the mouse enters it and "Bye" when the mouse leaves. I have been using mouse events with a MouseListener but to no avail.
I'm new to Java and this question has been plaguing me for the last 2 days and I just have not been able to figure it out. Any help would be greatly appreciated.
private abstract class HandlerClass implements MouseListener {
}
private abstract class Handlerclass implements MouseListener {
#Override
public void mouseEntered(java.awt.event.MouseEvent e) {
mousebutton.setText("Hi");
}
#Override
public void mouseExited(java.awt.event.MouseEvent e) {
mousebutton.setText("Bye");
}
}
Try like this. It is working for me.
public class ChangeTextMouseEvent extends Frame
{
static JButton btn;
public ChangeTextMouseEvent()
{
setTitle("ChangeText");
btn = new JButton("SSS");
add(btn);
setVisible(true);
setBounds(0, 0, 100, 100);
}
public static void main(String[] args)
{
ChangeTextMouseEvent frame = new ChangeTextMouseEvent();
btn.addMouseListener(new MouseAdapter(){
#Override
public void mouseExited(MouseEvent e)
{
btn.setText("Bye");
}
#Override
public void mouseEntered(MouseEvent e)
{
btn.setText("Hi");
}
});
}
}
Updating the UI component alone is often not enough; you also have to trigger a repaint action.
In other words: there are two "layers" here. One is the "data model" (where some button knows about its text); the other is the actual "graphical content". The later one comes into existence by somehow displaying the first parts. Therefore both layers need to be addressed in order to make your chances visible to the user.
See here for some examples around that.

how to impliment mouse listener

Kind of a noob question, but then again, I am a noob. I'm trying to implement a sort of "universal" mouse listener. That is, when I click any of the objects on screen, it runs a specific amount of code. I have the current solution below, but the code I want to run is the same for 10 different objects, so this gets rather tedious.
difference2 = new JLabel(new ImageIcon("transparent.png"));
difference2.setBounds(645,490,10,10); //left, top, width, height
contentPane.add(difference2);
difference2.setVisible(true);
difference2.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e) {
//code
}
});
I am aware I can create a separate method such as the following
public void mouseClicked(MouseEvent e) {
JOptionPane.showMessageDialog(null,"this would be nice");
}
But I can't figure out how to set up a mouse listener on every object for it. The JOptionPane currently does nothing.
I might have misread your question, but if you want the same mouselistener on various objects,you could store the instance of your listener in a variable once and then add it to whatever gui object you want it added to.
MouseListener ml = new MouseListener() {
#Override
public void mouseReleased(MouseEvent e) {//code}
#Override
public void mousePressed(MouseEvent e) {//code}
#Override
public void mouseExited(MouseEvent e) {//code}
#Override
public void mouseEntered(MouseEvent e) {//code}
#Override
public void mouseClicked(MouseEvent e) {//code}
};
JLabel j1 = new JLabel("Label1");
j1.addMouseListener(ml);
JLabel j2 = new JLabel("Label2");
j2.addMouseListener(ml);
You can create an instance of an anonymous class that extends MouseAdapter and assign it to a variable that you can reuse (myMouseListener in this case):
MouseListener myMouseListener = new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
JOptionPane.showMessageDialog(null,"this would be nice");
}
};
difference2.addMouseListener(myMouseListener);
aSecondObject.addMouseListener(myMouseListener);
aThirdObject.addMouseListener(myMouseListener);
...

Java - How to make the images disappear

Hi I want to make my JPanel disappear so I wrote these lines of code
removeAll();
updateUI();
revalidate();
That only made the JComponents and JButtons disappear. I would like to make the images that I have displayed with the paint method disappear also. If I do setVisible(false), then I cannot add another JPanel behind it.
This is my class:
package screens;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class menuScreen extends JPanel implements MouseListener{
private static final long serialVersionUID = 1L;
//-------------VARIABLES---------------//
Image wallpaper = (Image)Toolkit.getDefaultToolkit().getImage(getClass().getResource("images/wallpaper.jpg"));
Image title_text = (Image)Toolkit.getDefaultToolkit().getImage(getClass().getResource("images/title-text.png"));
ImageIcon startGameimg = new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("images/startGame.png")));
ImageIcon optionsimg = new ImageIcon(Toolkit.getDefaultToolkit().getImage(getClass().getResource("images/options.png")));
//JButton start = new JButton(basketball);
JLabel options = new JLabel(optionsimg);
JLabel startGame = new JLabel(startGameimg);
gameScreen gS = new gameScreen();
CardLayout scenechange = new CardLayout();
JPanel scenechange1 = new JPanel (scenechange);
//-------------PAINT FUNCTION----------//
public void paintComponent(Graphics g){
g.drawImage(wallpaper,0,0,this);
g.drawImage(title_text,0,0,this);
//g.drawImage(basketball1,110,180,this);
}
//-------------CONSTRUCTOR-------------//
public menuScreen(){
scenechange.addLayoutComponent(this,"menuScreen");
scenechange.addLayoutComponent(gS,"gameScreen");
//scenechange.show(this,"menuScreen");
this.setLayout(null);
this.add(options);
this.add(startGame);
startGame.setBounds(110,180,110,110);
options.setBounds(110,300,110,110);
startGame.addMouseListener(this);
options.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
if(e.getSource() == (startGame)){
removeAll();
revalidate();
add(gS);
}
if(e.getSource() == (options)){
setVisible(false);
}
}
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
}
}//END OF CLASS startingScreen
Thanks in advance.
First, don't call updateUI, it's related to the Look and Feel and not (directly) to updating your components.
If you have provided a custom paint routine within in your panel, then you need away to stop it from painting the images (without preventing it from painting it's own content). removeXxx will remove child components that you have previously added to the container.
A little more code would be useful
UPDATE
Fisrt, the images your painting aren't components of you container, they are been "stamped", you need some way to tell the component not to the paint the images
public void paintComponent(Graphics g){
super.paintComponent(g); // this is super important
if (paintImages){ // you need to define and set this flag
g.drawImage(wallpaper,0,0,this);
g.drawImage(title_text,0,0,this);
}
}
Now, this will stop the images from been painted.
If, however, you no longer want to use the component (ie, you want to remove it from the screen so you can place a new component on the screen in its place), you need to remove this component from it's parent, which Code-Guru has suggested (so I won't steal his answer ;))
UPDATE
Okay, you had a kernel of an idea but either didn't quite know how to implement it or decided to discard it.
Basically, from the looks of your code, you were either trying to, or had, implement a CardLayout, unfortunately, you kind of got the wrong idea with it.
With CardLayout, you need to "controller", a component that is responsible for switching the screens...
public class ScreenController extends JPanel {
private static final long serialVersionUID = 1L;
//-------------VARIABLES---------------//
MenuScreen ms = new MenuScreen();
GameScreen gs = new GameScreen();
CardLayout sceneChange;
//-------------CONSTRUCTOR-------------//
public ScreenController() {
sceneChange = new CardLayout();
this.setLayout(sceneChange);
add(ms, "menuScreen");
add(gs, "gameScreen");
sceneChange.show(this, "menuScreen");
ms.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("startgame")) {
sceneChange.show(ScreenController.this, "gameScreen");
}
}
});
}
}//END OF CLASS startingScreen
Then you have your menu and game screens...
public class MenuScreen extends JPanel implements MouseListener {
private static final long serialVersionUID = 1L;
//-------------VARIABLES---------------//
//JButton start = new JButton(basketball);
JLabel options = new JLabel("Options");
JLabel startGame = new JLabel(" >> Start << ");
// gameScreen gS = new gameScreen();
BufferedImage wallpaper;
//-------------PAINT FUNCTION----------//
#Override
public void paintComponent(Graphics g) {
System.out.println("paint");
super.paintComponent(g);
if (wallpaper != null) {
g.drawImage(wallpaper, 0, 0, this);
}
}
//-------------CONSTRUCTOR-------------//
public MenuScreen() {
// Please handle your exceptions better
try {
wallpaper = ImageIO.read(getClass().getResource("/Menu.png"));
setPreferredSize(new Dimension(wallpaper.getWidth(), wallpaper.getHeight()));
} catch (IOException ex) {
ex.printStackTrace();
}
setLayout(new GridBagLayout());
Cursor cusor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
options.setCursor(cusor);
startGame.setCursor(cusor);
Font font = UIManager.getFont("Label.font").deriveFont(Font.BOLD, 48);
options.setFont(font);
startGame.setFont(font);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
this.add(options, gbc);
gbc.gridy++;
this.add(startGame, gbc);
startGame.addMouseListener(this);
options.addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
if (e.getSource() == (startGame)) {
fireActionPerformed("startGame");
}
if (e.getSource() == (options)) {
fireActionPerformed("gameOptions");
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void addActionListener(ActionListener listener) {
listenerList.add(ActionListener.class, listener);
}
public void removeActionListener(ActionListener listener) {
listenerList.remove(ActionListener.class, listener);
}
protected void fireActionPerformed(String cmd) {
ActionListener[] listeners = listenerList.getListeners(ActionListener.class);
if (listeners != null && listeners.length > 0) {
ActionEvent evt = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, cmd);
for (ActionListener listener : listeners) {
listener.actionPerformed(evt);
}
}
}
}
Menu Screen...
And when you click start...the game screen...
Now this is an EXAMPLE. Please try and take the time to understand what it going on in the code before you march ahead and implement it. I used by own images, you'll need to get your own..
There are several ways to stop your JPanel from "appearing" depending on exactly what you want to accomplish. One was it to to call setOpaque(false);. I'm not entirely sure how this affects custom painting, though.
Another posibility is
Container parent = getParent().remove(this);
parent.validate();
A third posibility is to add a flag in your class which is set when you click on a JLabel (or better yet a JButton -- see comments below). Then in your paintComponent() method you can check the flag and draw accordingly.
Note:
You are incorrectly using a JLabel and mouse events to respond to user input. Typically in a Swing application, we use JButtons and ActionListeners to accomplish what you are trying to do here. One advantage of this is that you only have to implement one method called onActionPerformed() and don't need to worry about adding all the mouse event handlers that you don't want to even respond to.

Categories

Resources