I'm trying to make a a program in MVC architecture which simply opens a frame (JFrame) with some certain design and when clicked somewhere with a mouse simply prints to the console : "sth" notifying that the action went through successfully but it seems that the Input.java class when added to the frame before the Ouput.java class is overridden by the latter and disables MouseListener, or the former overrides the latter where you're able to activate MouseListener executing a certain program when clicked on the frame but doesn't show the design made in Output
Here are the mentioned class files:
input.java:
package MouseListenerTest;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
public class Input extends JPanel implements MouseListener
{
Input()
{
addMouseListener(this);
}
public void mouseClicked(MouseEvent e) {
System.out.println("Ej Adiiiii");
}
public void mousePressed(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
Output.java
package MouseListenerTest;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Output extends JPanel
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 500, 500);
}
}
Frame.java
package MouseListenerTest;
import javax.swing.*;
public class Frame
{
Frame()
{
JFrame frame = new JFrame();
frame.getContentPane().add(new Output());
frame.getContentPane().add(new Input());
frame.setSize(500,500);
frame.setVisible(true);
frame.setTitle("MouseListener test");
}
}
Controller.java
package MouseListenerTest;
public class Controller
{
public static void main(String[] args)
{
new Frame();
}
}
How do I fix this problem?
the problem in your code is because the way you added the elements to frame and I changed to a GridLayout and added them to frame to see both:
frame.setLayout(new GridLayout(2, 1));
frame.getContentPane().add(new Output());
frame.getContentPane().add(new Input());
more info about Layout Manager
You will have to learn at least the basics about laying out components.
Related
Basically, I want to get the coordinates of the mouse when it is pressed. I've done it before and I know it's possible, but it doesn't seem to be working with my current jframe/jpanel set up and I cannot understand why.
Here's a summary of my mouselistener code:
package com.JJEngine.input;
import java.awt.MouseInfo;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import com.JJEngine.output.Window;
public class Mouse implements MouseListener {
public Mouse(){
}
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseEntered(MouseEvent arg0) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mousePressed(MouseEvent arg0) {
//This is where i'd do my stuff if this actually worked
}
#Override
public void mouseReleased(MouseEvent arg0) {
}
}
and here's my jpanel/jframe
package com.JJEngine.output;
import java.awt.Container;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.JJEngine.input.Mouse;
import com.JJEngine.main.Main;
import custom.GameMain;
public class Window extends JPanel{
public static JFrame frame = new JFrame();
public static JPanel gamePanel = new JPanel();
private Container window;
public Window() {
frame.addMouseListener(new Mouse());
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setUndecorated(!GameMain.BORDERS);
frame.setVisible(true);
// Custom options
frame.setSize(Main.game.X, Main.game.Y);
frame.setTitle(Main.game.NAME);
frame.setResizable(Main.game.RESIZABLE);
window = frame.getContentPane();
frame.add(gamePanel);
frame.add(Main.render);
// Built options
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setFocusable(true);
frame.setAlwaysOnTop(true);
}
}
My guess is I will have to restructure my entire Window class. If that is the case, why? Thanks in advance.
I must use a swing-ui designer tool to create my UI, that only supports graphically editing JPanels. Those panels (they basically contain complex button designs) to work like a JButton. I cannot use anything other than JPanel as base class of these panels (UI editor limitation).
What is the most generic solution to do this?
Create a custom button that uses the panel's draw method instead of
it's own?
Create a base-panel class that reimplements the whole
button?
Another more elegant solution?
Here is a quick demo, to show you how you could use borders to simulate a button.
The demo also reacts to mouse and key events :
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
public class JPanelButton extends JPanel {
Border raisedetched = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
Border loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
public static void main(final String[] args) {
JFrame frame = new JFrame();
final JPanelButton panel = new JPanelButton();
panel.raiseBorder();
panel.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(final MouseEvent e) {
panel.lowerBorder();
}
#Override
public void mouseReleased(final MouseEvent e) {
panel.raiseBorder();
}
});
panel.setFocusable(true); // you need this or the panel won't get the key events
panel.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(final KeyEvent e) {
panel.lowerBorder();
}
#Override
public void keyReleased(final KeyEvent e) {
panel.raiseBorder();
}
});
frame.setContentPane(panel);
frame.setSize(100, 100);
frame.setVisible(true);
}
public void raiseBorder() {
setBorder(raisedetched);
}
public void lowerBorder() {
setBorder(loweredetched);
}
}
Simply add MouseListener.
JPanel jp = new JPanel();
jp.addMouseListener(new MouseAdapter(){
public void mouseClicked(MouseEvent e) {
System.out.println("Clicked");
}
});
If this answer isn't specific enough, leave a comment and I'll give you more explanation.
I'm working on an application that allows me to show and hide split planes.
I've read some articles on how to get this but its not what I'm looking for.
here's the code Ive written:
Im currently using netbeans.
private void jSplitPane1MouseEntered(java.awt.event.MouseEvent evt) {
if(MouseInfo.getPointerInfo().getLocation() == jSplitPane1.getLeftComponent().getLocation()){
jSplitPane1.setDividerLocation(100);
System.out.println("Mouse Entered");
}else{
jSplitPane1.setDividerLocation(20);
System.out.println("Mouse Exited");
}
}
I have referred to these posts:
How to make JSplitPane auto expand on mouse hover?
Get Mouse Position
What I want to happen is when I mouse over the left side of the jSplitPane, I would get the divider to extend to 100 as per my first if statement, and when it exists the left side, it contracts back to divider location 20.
This is really, really tricky.
You could use a MouseListener on the "left" component and monitor the mouseEntered and mouseExited events, but these will also get triggered when when you move into and out of a child component which has a MouseListener of it's own (like a JButton).
Okay, you could use a MouseMotionListener on the JSplitPane and monitor for the mouseMoved event and check where the mouse cursor is, but this goes to hell the moment the components (left/right) get their own MouseListener, as the MouseEvents are no longer delivered to the JSplitPane
So, one of the last options you have is to attach a global AWTListener to the event queue and monitor for events which occur on the JSplitPane itself, for example...
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
JSplitPane pane = new JSplitPane();
pane.setLeftComponent(makePane(Color.RED));
pane.setRightComponent(makePane(Color.BLUE));
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent) {
MouseEvent me = (MouseEvent) event;
if (pane.getBounds().contains(me.getPoint())) {
System.out.println("Global Motion in the pane...");
me = SwingUtilities.convertMouseEvent(me.getComponent(), me, pane);
Component left = pane.getLeftComponent();
if (left.getBounds().contains(me.getPoint())) {
pane.setDividerLocation(100);
} else {
pane.setDividerLocation(20);
}
}
}
}
}, MouseEvent.MOUSE_MOTION_EVENT_MASK);
// You don't need this, this is to demonstrate
// that mouse events aren't hitting your component
// via the listener
pane.addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("Motion in the pane...");
Component left = pane.getLeftComponent();
if (left.getBounds().contains(e.getPoint())) {
pane.setDividerLocation(100);
} else {
pane.setDividerLocation(20);
}
}
});
pane.setDividerLocation(20);
add(pane);
}
protected JPanel makePane(Color background) {
JPanel pane = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
pane.setLayout(new GridBagLayout());
pane.add(new JButton("..."));
pane.setBackground(background);
pane.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
System.out.println("...");
}
});
return pane;
}
}
}
Text in transparent windows ( AWTUtilities.setWindowOpaque(window, false) ) is not antialiased correctly, and looks different then in opaque windows.
I'm using JDK 7.40.
Any idea how to workaround it?
In the program below the button text is not antialiased (correctly). Removing the setWindowOpaque() fixes the antialiasing.
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import com.sun.awt.AWTUtilities;
public class TransparentFrame extends JFrame
{
public TransparentFrame()
{
setUndecorated(true);
AWTUtilities.setWindowOpaque(this, false);
add(new JButton(new ExitAction()));
}
public static void main(String[] args)
{
JFrame frame = new TransparentFrame();
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class ExitAction extends AbstractAction
{
public ExitAction()
{
super("Exit");
}
#Override
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
}
I have a main application frame (MainFrame class). On actionperformed event of a JButton, a JPanel (MyJPanel class) is opened by placing it in JDialog. I am not extending JDialog to create MyJPanel class because I might need MyJPanel at other purposes too.
My Problem is I cannot programmatically close the MyJPanel which is displayed in JDialog. Is there anything that I missing? Could you please figure it out?
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class MainFrame extends JPanel {
public MainFrame() {
JButton btnOpenJdialog = new JButton("Open JDialog");
add(btnOpenJdialog);
btnOpenJdialog.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JDialog jd = new JDialog();
MyJPanel mjp = new MyJPanel(true);//showing in JDialog
jd.setTitle("JDialog");
jd.add(mjp);
jd.pack();
jd.setVisible(true);
}
});
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame("Test-JFrame");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainFrame());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
MyJPanel Class :
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JButton;
public class MyJPanel extends JPanel {
private boolean isShownInJDialog = false;
public MyJPanel() {
JButton btnCloseMe = new JButton("Finish Action");
add(btnCloseMe);
btnCloseMe.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (isShownInJDialog) {
MyJPanel.this.setVisible(false);
//how to close the JDialog too.
}
else {
//just hide the content,
MyJPanel.this.setVisible(false);
}
}
});
}
public MyJPanel(boolean isShownInJDialog) {
this();
this.isShownInJDialog = isShownInJDialog;
}
}
UPDATE
I was able to solve this using Howard's answer as :
...
if (isShownInJDialog) {
Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
w.setVisible(false);
}
...
If I understand your question correctly, you want to close the JDialog which your MyJPanel is contained in but do not have a reference to it?
You may either provide such a reference using the constructor of MyJPanel or change the code inside your ActionListener to
Window w = SwingUtilities.getWindowAncestor(MyJPanel.this);
w.setVisible(false);
which looks up the parent window of your panel without direct reference.