I am trying to get an internal frame to contain tabbed panes. However, my code does not seem to be loading the panes into the internal frame. I have my code in the java files, called InternalFrame.java and TabbedPaneSample.java. The code for both files is included below. Can anyone show me how to fix the code below so that it loads the tabbed panes when I run InternalFrame.java?
Here is my code:
The code for InternalFrame.java is:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLayeredPane;
public class InternalFrame extends JFrame {
JButton openButton;
JLayeredPane desktop;
JInternalFrame internalFrame;
TabbedPaneSample myTabbedPaneSample = new TabbedPaneSample();
public InternalFrame() {
super("Click button to open internal frame with two panels.");
setSize(500, 400);
openButton = new JButton("Open");
Panel p = new Panel();
p.add(openButton);
add(p, BorderLayout.SOUTH);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
openButton.addActionListener(new OpenListener());
desktop = new JDesktopPane();
desktop.setOpaque(true);
add(desktop, BorderLayout.CENTER);
}
class OpenListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if ((internalFrame == null) || (internalFrame.isClosed())) {
internalFrame = new JInternalFrame("Internal Frame", true, true, true, true);
internalFrame.setBounds(50, 50, 200, 100);
internalFrame.add(myTabbedPaneSample, BorderLayout.CENTER);
internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
internalFrame.pack();
internalFrame.setMinimumSize(new Dimension(300, 300));
desktop.add(internalFrame, new Integer(1));
internalFrame.setVisible(true);
}
}
}
public static void main(String args[]) {
InternalFrame myInternalFrame = new InternalFrame();
myInternalFrame.setVisible(true);
}
}
And the code for TabbedPaneSample.java is:
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
public class TabbedPaneSample extends JTabbedPane {
private JTabbedPane tabbedPane = new JTabbedPane();
private ImageIcon closeImage = new ImageIcon("C:/test/shipIcon.gif");
private Dimension closeButtonSize;
private int tabCounter = 0;
public TabbedPaneSample() {
closeButtonSize = new Dimension(closeImage.getIconWidth() + 2, closeImage.getIconHeight() + 2);
}
public void add() {
final JPanel content = new JPanel();
JPanel tab = new JPanel();
tab.setOpaque(false);
JLabel tabLabel = new JLabel("Tab " + (++tabCounter));
JButton tabCloseButton = new JButton(closeImage);
tabCloseButton.setPreferredSize(closeButtonSize);
tabCloseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int closeTabNumber = tabbedPane.indexOfComponent(content);
tabbedPane.removeTabAt(closeTabNumber);
}
});
tab.add(tabLabel, BorderLayout.WEST);
tab.add(tabCloseButton, BorderLayout.EAST);
this.addTab(null, content);
this.setTabComponentAt(this.getTabCount() - 1, tab);
}
public static void main(String[] args) {
TabbedPaneSample main = new TabbedPaneSample();
main.add();
main.add();
}
}
Here's one approach, shown below. A more flexible approach using Action is referenced here.
Addendum: Reviewing your code, you should let the various layout managers and component preferred sizes do more of the work, as shown. In particular, this.setPreferredSize() is done for demonstration purposes. In a real application, you would restore user size and location preferences.
package overflow;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
/** #see https://stackoverflow.com/posts/6514889 */
public class InternalFrame extends JFrame {
JButton openButton;
JLayeredPane desktop;
JInternalFrame internalFrame;
public InternalFrame() {
super("Click button to open internal frame with two tabs.");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setPreferredSize(new Dimension(400, 400));
openButton = new JButton("Open");
JPanel p = new JPanel();
p.add(openButton);
this.add(p, BorderLayout.SOUTH);
openButton.addActionListener(new OpenListener());
desktop = new JDesktopPane();
this.add(desktop, BorderLayout.CENTER);
this.pack();
this.setLocationRelativeTo(null);
}
class OpenListener implements ActionListener {
private static final int DELTA = 40;
private int offset = DELTA;
public void actionPerformed(ActionEvent e) {
internalFrame = new JInternalFrame(
"Internal Frame", true, true, true, true);
internalFrame.setLocation(offset, offset);
offset += DELTA;
internalFrame.add(createTabbedPane());
desktop.add(internalFrame);
internalFrame.pack();
internalFrame.setVisible(true);
}
}
private JTabbedPane createTabbedPane() {
JTabbedPane jtp = new JTabbedPane();
createTab(jtp, "One");
createTab(jtp, "Two");
return jtp;
}
private void createTab(JTabbedPane jtp, String s) {
jtp.add(s, new JLabel("TabbedPane " + s, JLabel.CENTER));
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
InternalFrame myInternalFrame = new InternalFrame();
myInternalFrame.setVisible(true);
}
});
}
}
First of all, I think Finally, I think you shouldn't use desktop.add(internalFrame, new Integer(1)) but rather desktop.add(internalFrame) instead, the reason is that JDesktopPane uses its layers (it is a JLayeredPane subclass) internally, and I don't think you should play with layers yourself.
Then, following this problem I had once with JInternalFrame, I would advise you call pack() after adding the internal frame to the desktop pane.
Hence, you should try with your OpenListener class looking like this:
class OpenListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if ((internalFrame == null) || (internalFrame.isClosed())) {
internalFrame = new JInternalFrame("Internal Frame", true, true, true, true);
internalFrame.setBounds(50, 50, 200, 100);
internalFrame.add(myTabbedPaneSample, BorderLayout.CENTER);
internalFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// internalFrame.pack();
internalFrame.setMinimumSize(new Dimension(300, 300));
// desktop.add(internalFrame, new Integer(1));
desktop.add(internalFrame);
internalFrame.pack();
internalFrame.setVisible(true);
}
}
}
Besides, I also agree with trashgod comments on Action of course and the simplifying rework he has done on your snippet.
I preferred to create in my Main Frame class (which extends JFrame) the following function:
private void showIntFrame(Class intFrameClass) {
JInternalFrame targetFrame = null;
int xoff = 0, yoff = 0;
for(JInternalFrame jif : jdp.getAllFrames()) {
if(jif.getClass().equals(intFrameClass))
targetFrame = jif;
if(jif.getLocation().x > xoff)
xoff = jif.getLocation().x;
if(jif.getLocation().y > yoff)
yoff = jif.getLocation().y;
}
if(targetFrame == null) {
try {
Constructor<JInternalFrame> c = intFrameClass.getConstructor(MainFrame.class);
targetFrame = c.newInstance(MainFrame.this);
} catch (Exception ex) {
System.err.println("Exception in MainFrame.showIntFrame() while creating new JInternalFrame instance. " + ex.getLocalizedMessage());
ex.printStackTrace();
return;
}
jdp.add(targetFrame);
targetFrame.setLocation(xoff + 30, yoff + 30);
}
targetFrame.setVisible(true);
try {
targetFrame.setSelected(true);
} catch (PropertyVetoException ex) {
System.err.println("PropertyVetoException in MainFrame.showIntFrame() while activating JInternalFrame instance. " + ex.getLocalizedMessage());
}
}
Here jdp is instance of JDesktopPane, which previously was set as ContentPane of my main JFrame.
Because my programs often contain numbers of different classes, inherited from JInternalFrame, it is easier to call this function from event handlers to show new subclass of JInternalFrame.
Every subclass of JInternalFrame in my programs have one constructor with one parameter - MainFrame (main JFrame).
Related
I want to be able to call the Introduction.Intro() method into my main file code, but it tells me I am unable to call a non-static method intro from a static context. Since I am still fairly new to coding I'm not entirely sure what the problem is. I've added my codes down below. I've tried countless online methods but sadly none have seemed to work.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Start extends JFrame implements ActionListener
{
private JFrame Main;
private JPanel PanelA, PanelB, PanelC;
private JLabel Text, ImageL;
private JButton Button;
private ImageIcon Image;
public Start ()
{
//Button
Button = new JButton("Start");
Button.addActionListener(new ButtonListener());
//Text
Text = new JLabel("Welcome To The Game"); //ADD NAME OF THE GAME
//Image
Image = new ImageIcon(getClass().getResource("download.jfif")); //ADD THE IMAGE FOR WELCOME
ImageL = new JLabel(Image);
//Top Panel (PanelA) - Image
PanelA = new JPanel();
PanelA.setBorder(BorderFactory.createEmptyBorder(0,200,150,200));
PanelA.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelA.add(ImageL);
//Middle Panel (PanelB) - Text
PanelB = new JPanel();
PanelB.setBorder(BorderFactory.createEmptyBorder(50,200,10,200));
PanelB.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelB.add(Text);
//Bottom Panel (PanelC) - Buttons
PanelC = new JPanel();
PanelC.setBorder(BorderFactory.createEmptyBorder(0,200,20,200));
PanelC.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelC.add(Button);
//Main Frame
Main = new JFrame ();
Main.add(PanelA, BorderLayout.NORTH);
Main.add(PanelB, BorderLayout.CENTER);
Main.add(PanelC, BorderLayout.SOUTH);
Main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Main.setTitle("GAME TITLE"); //ADD THIS LATER
Main.pack();
Main.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae)
{
}
public class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == Button)
{
Introduction.Intro1(); //THESE LINE RIGHT HERE
return null; //THESE LINE RIGHT HERE
}
}
}
public static void main(String[] args)
{
new Start();
}
}
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Introduction
{
private JFrame Main;
private JPanel PanelD;
private JLabel Text, ImageL;
private JButton Button;
private ImageIcon Image;
public void Intro()
{
Image = new ImageIcon(getClass().getResource("guy.jfif"));
ImageL = new JLabel(Image);
PanelD = new JPanel();
PanelD.setBorder(BorderFactory.createEmptyBorder(0,100,10,100));
PanelD.setLayout(new FlowLayout(FlowLayout.CENTER));
PanelD.add(ImageL);
PanelD.setVisible(true);
Main.add(PanelD, BorderLayout.NORTH);
}
}
EDIT: So I made another method in the Introduction class where I added this line of code, it managed to fix the error, however, the panel isn't being saved and my JFrame is outputting blank.
public static JFrame Intro1()
{
Introduction M = new Introduction();
return M;
}
If you are looking to initialize the Introduction class in main method of Start class, You can add belo code in main method after Start()
Introduction M = new Introduction();
You main method becomes :
public static void main(String[] args)
{
new Start();
Introduction M = new Introduction();
m.Intro
}
Looking at this set of code, It looks like there is incompatible issue, as you have declare JFrame as return type, while you are returning instance of Introduction.
public static JFrame Intro1()
{
Introduction M = new Introduction();
return M;
}
I have a class which create a JFrame with an image but everytime I create the class and run the method to instantiate it, it doesn't appear. However, I have noticed that if I was to create the exact same class and run the same method in the main then the frame appears.
This is most of the code from the class with the JFrame that I am trying to create:
JFrame myFrame= new JFrame();
public void CreateFrame()
{
JLabel background=new JLabel(new ImageIcon("image.jpg"));
myFrame.add(background);
background.setLayout(new FlowLayout());
myFrame.setLayout(new GridLayout(1,1));
myFrame.setSize(360,250);
myFrame.setUndecorated(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
myFrame.setLocation((dim.width/2-170), dim.height/2-125);
myFrame.pack();
myFrame.setVisible(true);
}
If I run the code
MyClass mc = new MyClass();
mc.CreateFrame();
in a method in another class it doesn't come up. However, if I run the exact same code in a main method, it works.
For example, this doesn't work:
Example 1
public class otherClass extends JFrame
{
public void MethodA()
{
MyClass mc = new MyClass();
mc.CreateFrame();
}
public static void main(String[] args)
{
otherClass oc = new otherClass();
oc.MethodA();
}
}
but this does work
Example 2
public class otherClass extends JFrame
{
public void MethodA()
{
//CODE
}
public static void main(String[] args)
{
otherClass oc = new otherClass();
oc.MethodA();
MyClass mc = new MyClass();
mc.CreateFrame();
}
}
Can anyone see where I'm going wrong? Sorry if a stupid mistake, I'm still getting to grips with Java.
Thanks
EDIT
import javax.swing.ImageIcon;
import javax.swing.JWindow;
import javax.swing.JLabel;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.util.Timer;
import java.util.Date;
import javax.swing.JFrame;
public class MyClass
{
JFrame homeFrame = new JFrame();
public void createFrame()
{
JLabel background=new JLabel(new ImageIcon("images.jpg"));
myFrame.add(background);
background.setLayout(new FlowLayout());
myFrame.setLayout(new GridLayout(1,1));
myFrame.setSize(360,250);
myFrame.setUndecorated(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
myFrame.setLocation((dim.width/2-170), dim.height/2-125);
myFrame.setAlwaysOnTop(true);
myFrame.pack();
myFrame.setVisible(true);
durationOfTime();
}
public void durationOfTime()
{
MainProgram mp = new MainProgram();
long startTime = System.currentTimeMillis();
long elapsedTime = 0L;
int count =0;
while (elapsedTime < 2*1000)
{
if(count==0)
{
mp.launchInitiation();
}
count+=1;
elapsedTime = (new Date()).getTime() - startTime;
}
myFrame.setVisible(false);
mp.homeFrame.setVisible(true);
}
public static void main(String[] args)
{
MyClass mc = new MyClass();
mc.createFrame();
}
}
Full code from class with JFrame trying to make. I am trying to use this JFrame as a splash screen but whatever class I call
MyClass mc = new MyClass();
mc.createFrame();
from, it just doesn't appear. Two seconds do pass by before my main GUI appears up but this method is supposed to be called in a login type frame. However, I have tested it with a blank JFrame / GUI to appear upon button click also and it still doesn't appear.
EDIT2
I also previously tried this SplashScreen example by # http://examples.oreilly.com/jswing2/code/ch08/SplashScreen.java but I couldn't get it to work (same problem, appears when called from main but not when called from action listener)
import java.awt.*;
import javax.swing.*;
public class SplashScreen extends JWindow {
private int duration;
public SplashScreen(int d) {
duration = d;
}
// A simple little method to show a title screen in the center
// of the screen for the amount of time given in the constructor
public void showSplash() {
JPanel content = (JPanel)getContentPane();
content.setBackground(Color.white);
// Set the window's bounds, centering the window
int width = 450;
int height =115;
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screen.width-width)/2;
int y = (screen.height-height)/2;
setBounds(x,y,width,height);
// Build the splash screen
JLabel label = new JLabel(new ImageIcon("oreilly.gif"));
JLabel copyrt = new JLabel
("Copyright 2002, O'Reilly & Associates", JLabel.CENTER);
copyrt.setFont(new Font("Sans-Serif", Font.BOLD, 12));
content.add(label, BorderLayout.CENTER);
content.add(copyrt, BorderLayout.SOUTH);
Color oraRed = new Color(156, 20, 20, 255);
content.setBorder(BorderFactory.createLineBorder(oraRed, 10));
// Display it
setVisible(true);
// Wait a little while, maybe while loading resources
ClassToLoad ctl = new ClassToLoad();
try {
Thread.sleep(duration);
ctl.initiate();
} catch (Exception e) {}
setVisible(false);
}
public void showSplashAndExit() {
showSplash();
System.exit(0);
}
public static void main(String[] args) {
// Throw a nice little title page up on the screen first
SplashScreen splash = new SplashScreen(10000);
// Normally, we'd call splash.showSplash() and get on with the program.
// But, since this is only a test...
splash.showSplashAndExit();
}
}
I added the code in the lines with ClassToLoad and this SplashScreen is called on an action listener, what happens is the program waits the 2 seconds that I tell it to, no frame appears, and then the main class that I wanted to load while the splash screen is visible loads. I tried this method first but this didn't work which lead to me using the code listed above this edit
EDIT 3
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestFrame extends JFrame implements ActionListener
{
JPanel thePanel = new JPanel(null); //layout
JButton button = new JButton();
public void startGUI()
{
this.setLayout(new GridLayout(1,1));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
CREATEMYPANEL();
this.add(thePanel);
this.setTitle("NO_TITLE_SET");
this.setSize(400,400);
this.setVisible(true);
this.setResizable(true);
}
public void CREATEMYPANEL()
{
button.setLocation(242,151);
button.setSize(100,50);
button.addActionListener(this);
button.setText("button");
thePanel.add(button);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==button)
{
System.out.println("button has been pressed ");
SplashScreen splash = new SplashScreen(1000);
splash.showSplash();
}
}
public static void main(String[] args )
{
TestFrame tf = new TestFrame();
tf.startGUI();
}
}
An example of where I call splash screen from. Still doesn't work. Also, just a note that the image I am loading is a local image
Apologies for bad question formatting
Your code works for me except for some details I noticed:
You're calling setSize(...) and then calling pack(). Probably your image isn't being loaded and thus your JFrame has a size of 0, 0. (And thus it looks like it never appears). .pack() and .setSize(...) are mutually exclusive.
You're setting the JLabel's layout manager to FlowLayout but never adding anything to it. (You can safely remove it)
I see you're importing java.util.Timer if you want to dispose the JFrame after 2 seconds, then you should be using a javax.swing.Timer instead. Otherwise you could get problems related to threading.
Also don't forget to place your program on the Event Dispatch Thread (EDT) as Swing is not thread safe
Following above recommendations you can have this code:
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SplashscreenSample {
private JFrame myFrame;
private JLabel background;
private Timer timer;
public void createFrame() {
timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myFrame.dispose();
#SuppressWarnings("serial")
JFrame frame = new JFrame(getClass().getSimpleName()) {
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
};
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
timer.stop();
}
});
myFrame = new JFrame(getClass().getSimpleName());
try {
background = new JLabel(new ImageIcon(new URL("http://cdn.bulbagarden.net/upload/thumb/6/6b/175Togepi.png/250px-175Togepi.png")));
} catch (MalformedURLException e) {
e.printStackTrace();
}
myFrame.add(background);
timer.setInitialDelay(2000);
timer.start();
myFrame.setLayout(new GridLayout(1, 1));
myFrame.setUndecorated(true);
myFrame.setAlwaysOnTop(true);
myFrame.pack();
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
myFrame.setLocation((dim.width/2-170), dim.height/2-125);
myFrame.setVisible(true);
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new SplashscreenSample().createFrame());
}
}
Or you can use the Splashscreen class...
For example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JWindow;
public class SplashScreen extends JWindow {
private int duration;
public SplashScreen(int d) {
duration = d;
}
// A simple little method to show a title screen in the center
// of the screen for the amount of time given in the constructor
public void showSplash() {
ImageIcon icon = null;
try {
icon = new ImageIcon(new URL("http://www.cqsisu.com/data/wallpapers/5/718448.gif"));
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
JPanel content = (JPanel) getContentPane();
content.setBackground(Color.white);
// Set the window's bounds, centering the window
int width = icon.getIconWidth();
int height = icon.getIconHeight();
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
int x = (screen.width - width) / 2;
int y = (screen.height - height) / 2;
setBounds(x, y, width, height);
// Build the splash screen
JLabel label = new JLabel(icon);
JLabel copyrt = new JLabel("Copyright 2002, O'Reilly & Associates", JLabel.CENTER);
copyrt.setFont(new Font("Sans-Serif", Font.BOLD, 12));
content.add(label, BorderLayout.CENTER);
content.add(copyrt, BorderLayout.SOUTH);
Color oraRed = new Color(156, 20, 20, 255);
content.setBorder(BorderFactory.createLineBorder(oraRed, 10));
// Display it
setVisible(true);
// Wait a little while, maybe while loading resources
loadResources();
setVisible(false);
}
public void loadResources() {
TestFrame tf = new TestFrame();
try {
Thread.sleep(duration);
tf.startGUI();
} catch (Exception e) {
}
}
public static void main(String[] args) {
SplashScreen splash = new SplashScreen(10000);
splash.showSplash();
}
}
Try creating and setting the frame visible in a constructor of the class.
Could it be that while your program is counting
while (elapsedTime < 2*1000)
{
if(count==0)
{
mp.launchInitiation();
}
count+=1;
elapsedTime = (new Date()).getTime() - startTime;
}
it is blocking for said 2 seconds and waiting for this method to finish, return back to the create method and then just finish that one?
it seems this could be a better comment, but i need 50 rep for some reason to comment.
Here's the code. It prints out the mouse location when it's in the panel but not the JTextArea. I added the mouse listener to the text area as well? The problem is that the coordinates are not consistent throughout the JFrame. Is there a way to just have one mouselistener that covers the entire jframe?
Is there a way to disable the mouse listener in the textarea?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
public class test extends JFrame {
public test(){
setPreferredSize(new Dimension(600,400));
JPanel p = new JPanel();
p.setBackground(Color.blue);
p.setPreferredSize(new Dimension(600,200));
JTextArea t = new JTextArea();
t.setPreferredSize(new Dimension(600,200));
add(p,BorderLayout.NORTH);
add(t,BorderLayout.SOUTH);
pack();
MouseInput m = new MouseInput();
addMouseMotionListener(m);
t.addMouseMotionListener(m);
setVisible(true);
}
public static void main(String[] args){
new test();
}
public class MouseInput implements MouseMotionListener{
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
System.out.println(mx + "," + my);
}
}
}
Think of your mouse events like rain. They fall from the top of your component hierarchy down until something stops them.
Once stopped, they will no long notify other listeners lower in the hierarchy.
In you program you have and JPanel and JTextField sitting on top of another component (the content pane) sitting on a JLayeredPane sitting on top of the frame. Any one of these may be consuming the mouse event.
Try adding the MouseInput to your JPanel, p instead
Updated
This is an example of a global mouse listener (as suggested by #Hovercraft Full Of Eels, it WILL get hammered, as every mouse event will pass through it.
It also demonstrates how to translate a mouse point from it's local context to another context.
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class GloablMouseListener {
public static void main(String[] args) {
new GloablMouseListener();
}
public GloablMouseListener() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
JPanel panel = new JPanel();
panel.setBackground(Color.BLUE);
JTextArea ta = new JTextArea(10, 20);
add(panel, BorderLayout.NORTH);
add(new JScrollPane(ta), BorderLayout.SOUTH);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof MouseEvent) {
MouseEvent e = (MouseEvent) event;
System.out.println("Local point = " + e.getPoint());
Point p = e.getPoint();
Window window = SwingUtilities.getWindowAncestor(e.getComponent());
if (window != e.getSource() && window != null) {
p = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), window);
}
System.out.println("Global point = " + p);
}
}
}, AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}
The JTextArea has its own MouseListener/MouseMotionListener that grabs the mouse information before any underlying class with a MouseListener or motion listener can.
This may be fixable by using an AWTEventListener, but I have not tried this myself yet.
Edit
OK, I have tried this as a for instance:
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class Test2 extends JPanel {
JTextArea textarea = new JTextArea(15, 60);
public Test2() {
JPanel topPanel = new JPanel();
topPanel.setBackground(Color.blue);
setLayout(new GridLayout(0, 1));
add(topPanel);
add(new JScrollPane(textarea));
addMouseMotionListener(new MouseAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
int x = e.getX();
int y = e.getY();
System.out.printf("%20s [%03d, %03d]%n", "From MouseAdapter:", x, y);
}
});
long eventMask = AWTEvent.MOUSE_MOTION_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent awtEvent) {
MouseEvent mouseEvent = (MouseEvent) awtEvent;
Component component = (Component) awtEvent.getSource();
Point location = component.getLocationOnScreen();
Point test2Location = Test2.this.getLocationOnScreen();
// Normalized to find the mouse location relative to the main JPanel,
// the Test2 "this" JPanel.
int x = mouseEvent.getX() + location.x - test2Location.x;
int y = mouseEvent.getY() + location.y - test2Location.y;
System.out.printf("%20s [%03d, %03d]%n", "From AWTEvent:", x, y);
}
}, eventMask );
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Test2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Test2());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Try adding a MouseListener to your application's GlassPane.
See these following link. It includes a Java Web Start demo of something similar to what you want to do.
How to Use Root Panes
I am writing a small app that requires a ProgressBar to appear centred under the frame's TitleBar as is often seen in Mac OSX apps. I have two problems:
1. I have managed the positioning but I had to hard code the parent Frame's TitleBar height. Is there a 'soft' way to get the TitleBar's height?
In the Dialog's constructor:
Dimension dimensionParentFrame = parent.getSize();
Dimension dimensionDialog = getSize();
int x = parent.getX() + ((dimensionParentFrame.width - dimensionDialog.width)/2);
setLocation(x, parent.getY() + 22); // TODO HARD CODE WARNING TITLE HEIGHT
2. Even though the Dialog is modal, I can still click on the parent Frame and move it. How can I make the Dialog 'stick' to the parent Frame? That is, when the parent Frame is moved the Dialog moves with it as if attached.
Any help/pointers would be much appreciated.
Here is the code:
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ModalDialogDemoFrame extends JFrame
{
ModalDialogDemoFrame modalDialogDemo;
public ModalDialogDemoFrame()
{
modalDialogDemo = this;
setBounds(100, 100, 400, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton buttonDialog = new JButton("Open Dialog");
buttonDialog.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
// Create a Modal Dialog with this Frame as Parent.
ModalDialog modalDialog = new ModalDialog(modalDialogDemo, true);
modalDialog.setVisible(true);
}
});
getContentPane().add(buttonDialog, BorderLayout.CENTER);
}
/**
* #param args
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
ModalDialogDemoFrame window = new ModalDialogDemoFrame();
window.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
}
import java.awt.Dimension;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class ModalDialog extends JDialog
{
public ModalDialog(JFrame parent, boolean modal)
{
super(parent, modal);
Dimension dimensionParentFrame = parent.getSize();
setSize(new Dimension((parent == null) ? 300 : dimensionParentFrame.width / 2, 75));
Dimension dimensionDialog = getSize();
int x = parent.getX() + ((dimensionParentFrame.width - dimensionDialog.width)/2);
setLocation(x, parent.getY() + parent.getInsets().top);
setUndecorated(true);
setModal(modal);
setModalityType(ModalityType.APPLICATION_MODAL);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JButton buttonClose = new JButton("Close");
buttonClose.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dispose();
}
});
getContentPane().add(buttonClose, BorderLayout.CENTER);
}
}
int titleBarHeight = frame.getInsets().top;
Even though the Dialog is modal, I can still click on the parent Frame and move it.
Then you are doing something wrong because this should NOT happen.
Post your SSCCE that demonstrates the problem.
I have some set of JInternalFrame in a Jpanel. and the JPanel is gridlayout. I need to set only one JInternalFrame to be selected in the container (JPanel). I created the JInternalFrame instance dynamically and add to the panel. I still have the list of JInternalFrame but how to make only one to set selected.
As suggested in How to Use Internal Frames, "Usually, you add internal frames to a desktop pane." This allows you to use activateFrame() to indicate that a frame has focus. In this example, a javax.swing.Action is used to select frames from a menu via setSelected(). Additional discussion may be found in this Q&A.
Addendum: If you want to use a JPanel, perhaps to get a nice GridLayout, one aproach is to use an InternalFrameListener as shown below.
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
/** #see https://stackoverflow.com/questions/8389640 */
public class InternalGrid extends JPanel {
private final List<MyFrame> list = new ArrayList<MyFrame>();
public InternalGrid() {
super(new GridLayout(2, 2));
for (int i = 0; i < 4; i++) {
MyFrame f = new MyFrame("Frame", i);
list.add(f);
this.add(f);
}
}
private void display() {
JFrame f = new JFrame("InternalGrid");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new InternalGrid().display();
}
});
}
class MyFrame extends JInternalFrame {
MyFrame(String name, int i) {
super(name + String.valueOf(i), true, true, true, false);
this.pack();
this.setVisible(true);
this.setLayout(new FlowLayout());
this.add(new JLabel("Hi, I'm " + this.getTitle()));
this.addInternalFrameListener(new InternalFrameAdapter() {
#Override
public void internalFrameActivated(InternalFrameEvent e) {
for (MyFrame f : list) {
if (f != MyFrame.this) {
try {
f.setSelected(false);
} catch (PropertyVetoException ex) {
System.out.println(ex);
}
}
}
}
});
}
}
}