I have a reference to a JPanel that is stored inside a JFrame. I tried attaching a ComponentAdaptor to the JPanel, but when I move the JFrame, it is not getting called. Any ideas on how I can detect when the JPanel moves on the screen if all I have is a reference to the JPanel and not the JFrame?
This is my adaptor:
private class Listener extends ComponentAdapter {
#Override
public void componentMoved(ComponentEvent e) {
if (e.getComponent().equals(target)) {
targetMoved();
} else {
stickyMoved();
}
}
}
I think AncestorListener is what your looking for.
The JPanel does not move, but the frame that contains it does. You can use an AncestorListener on the panel, instead of ComponentListener to be notified when such events happen on any parent components.
private class Listener implements AncestorAdapter {
#Override
public void ancestorMoved(ComponentEvent e) {
if (e.getComponent().equals(target)) {
targetMoved();
} else {
stickyMoved();
}
}
}
how I can detect when the JPanel moves on the screen if all I have is a reference to the JPanel and not the JFrame?
You can get a reference to the JFrame by using:
SwingUtilities.windowForComponent( panel );
Of course you won't know which frame until the panel has actually been added to the frame. You can use an AncestorListener as demonstrated in Dialog Focus to know when the panel is actually visible.
Then you can add your ComponentListener to the frame.
Related
How to layout the JComponents by resolution of JPanel or JFrame?
Hello, I'm new to java coding and I'm having problem layoutting components
in JPanel.
Is there Good way to reset the size and location of components whenever Frame's resolution changes?
here is my code.
public class TestPanel extends JPanel{
private GameBoard SuperFrame;
/*SuperFrame is JFrame where this Panel attach to..*/
public TestPanel(GameBoard SuperFrame) {
.....
this.SuperFrame=SuperFrame;
this.setLayout(null);
.......
add(new Maximizebutton());
........
}
private class MaxmizeButton extends MYUI{
/*MYUI is abstract class which extends JComponent, and it inherits
preferredSize,preferredLocation and abstract void method revalidateSize ...*/
JButton maxButton;
public MaxmizeButton (){
preferredSize = new Dimension(SuperFrame.getWidth()/10,SuperFrame.getHeight()/10);
/*This is my crude solution about setting the size of Component
by resolution of SuperFrame(JFrame) :( */
preferredLocation = new Point();
/*Is there good way to set or calculate the location of this component? */
this.setSize(preferredSize);
this.setLocation(preferredLocation);
maxButton = new JButton("최대화");
maxButton.setSize(preferredSize);
maxButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SuperFrame.MaxmizeFrame();
/*MaximizeFrame method maximizes the SuperFrame..*/
}
});
add(maxButton,0);
}
#Override
void revalidateSize() {
/*whenever resolution of SuperFrame changes this method will be called
and should change the size and location of Components Ideally..*/
preferredSize = new Dimension(SuperFrame.getWidth()/10,SuperFrame.getHeight()/10);
preferredLocation = new Point();
this.setSize(preferredSize);
this.setLocation(preferredLocation);
maxButton.setSize(preferredSize);
}
}
}
I want to resize all Components in Panel by resolution of JFrame.
But couldn't found good solution for that.
I'd like to be able to switch between two possible JPanels in my frame by selecting a certain JMenuItem. What I tried so far:
Action listener in my JMenuBar class:
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(fullList))
gui.switchToFullList();
else if (e.getSource().equals(history))
gui.switchToHistory();
}
In GUI class:
void switchToFullList() {
remove(history);
add(fullList);
}
void switchToHistory() {
remove(fullList);
add(history);
}
where history and fullList are JPanels.
This doesn't seem to modify my frame in any way.
If you want to show one Panel and hide another, they both should ba childreen of your Frame, then you can acces those Panels by: frame.JpanelName.
Example of removing history and adding fullList:
frame.remove(frame.history);
frame.getContentPane().add(frame.fullList);
frame.validate();
frame.repaint();
I have a subclass of JFrame that uses a class extended from JPanel
public class HelloWorld extends JPanel implements KeyListener
I add an object of HelloWorld to the frame - app.add(helloWorld);. Now, when I press any keyboard key non of the KeyListener methods gets called and it seems that helloWorld doesn't have window focus. I have tried also to invoke helloWorld.requestFocusInWindow(); but still doesn't respond.
How can I make it respond to key press?
Did you set that KeyListener for your HelloWorld panel would be that panel itself? Also you probably need to set that panel focusable. I tested it by this code and it seems to work as it should
class HelloWorld extends JPanel implements KeyListener{
public void keyTyped(KeyEvent e) {
System.out.println("keyTyped: "+e);
}
public void keyPressed(KeyEvent e) {
System.out.println("keyPressed: "+e);
}
public void keyReleased(KeyEvent e) {
System.out.println("keyReleased: "+e);
}
}
class MyFrame extends JFrame {
public MyFrame() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(200,200);
HelloWorld helloWorld=new HelloWorld();
helloWorld.addKeyListener(helloWorld);
helloWorld.setFocusable(true);
add(helloWorld);
setVisible(true);
}
public static void main(String[] args) {
new MyFrame();
}
}
JPanel is not Focusable by default. That is, it can not respond to focus related events, meaning that it can not respond to the keyevents.
I would suggest trying to setFocusable on the pane to true and trying again. Make sure you click the panel first to make sure it receives focus.
Understand though, you WILL get strange focus traversal issues, as the panel will now receive input focus as the user navigates through your forms, making it seem like the focus has been lost some where.
Also, KeyListeners tend to be unreliable in this kind of situation (due to the way that the focus manager works).
simple you have to add
addKeylistener(new HelloWorld());
add this in MyFrame method;
HelloWorld() helloWorld = new HelloWorld();
this.addKeyListener(helloWorld);
Im making a game and Im having it so that when the user presses "I" in the game, the game panel is set to invisible while it adds the Inventory panel to the JFrame. Then when the user exits the Inventory it will remove the Inventory JPanel and then set back the game JPanel to visible.
Now this all sounds good, but whenever it removes the Inventory JPanel and goes back to the game JPanel, the KeyListener stops working. I even set back the setFocusable(true) property back on the game JPanel after I remove the Inventory JPanel but it still doesn't make the KeyListener work.
Here is my code for the game Jpanel:
package javavideogame;
public class Game extends JPanel implements ActionListener, Runnable
{
public Game(MainCharacter character)
{
TAdapter a = new TAdapter();
addKeyListener(a);
setFocusable(true);
setDoubleBuffered(true);
setFocusTraversalKeysEnabled(false);
}
public void getInventoryScreen()
{
Main.inv = new Inventory();
Main.inv.sayHello();
Main.mainGame.getContentPane().add(Main.inv);
Main.game.setVisible(false);
Main.mainGame.validate();
}
public void closeInventory()
{
Main.inv.setFocusable(false);
Main.mainGame.remove(Main.inv);
Main.game.setVisible(true);
Main.game.setFocusable(true);
}
public class TAdapter extends KeyAdapter
{
public void keyPressed(KeyEvent e)
{
character.keyPressed(e);
}
public void keyReleased(KeyEvent e)
{
character.keyReleased(e);
}
}
}
And here is the Inventory code:
package javavideogame;
public class Inventory extends JPanel implements KeyListener
{
public Inventory()
{
setBackground(Color.RED);
addKeyListener(this);
setFocusable(true);
}
public void keyPressed(KeyEvent e)
{
int key = e.getKeyCode();
if(key == KeyEvent.VK_I)
{
Main.game.closeInventory();
}
}
public void keyReleased(KeyEvent e)
{
}
public void keyTyped(KeyEvent e)
{
}
}
And yes im having a hard time getting the code thing on here to work right :)
But is there something i can easily put into the code so that the KeyListener will actually work right once it goes back to the game JPanel?
I even set back the setFocusable(true) property back on the game JPanel after I remove the Inventory JPanel
Key events only go the the component that has focus. You need to invoke:
panel.requestFocusInWindow();
after swapping the panels to make sure the panel has focus again.
However, a better approach is to use Key Bindings itead of a KeyListener.
You could skip working with adding and removing panels to the content pane and just set the visibility. Then you should also skip setting the focusable property (KeyEvents won't be passed to an invisible component anyway) and your key listeners should be preserved and come into effect again when the component becomes visible.
How can we create a main JFrame with background image and a JFrame inside the main JFrame with Java Swing?
I believe you are looking for internal frames.
For the background image bit, sublass JPanel, override its paintComponent() method, and blit your image there. Then set an instance of that panel as your JFrame's content pane.
public class BackgroundPanel extends JPanel {
private BufferedImage bgImg;
public BackgroundPanel() {
try {
bgImg = ImageIO.read(BackgroundPanel.class.getResourceAsStream(
"mybackgroundimage.png"));
} catch (IOException ex) {
System.err.println("Could not load background image!");
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bgImg != null) {
g.drawImage(bgImg, 0, 0, null);
}
}
}
public class MyJFrame extends JFrame {
public MyJFrame() {
setContentPane(new BackgroundPanel());
}
}
It is hard to know what you are meaning with
a JFrame inside the main JFrame
Have a read about what a JFrame really is. Maybe you want a dialog window in your application, or maybe an internal window. Or maybe just another panel.
To get an background image in a JFrame, I recommend that you simply add a JPanel with a backround image to the JFrame:s contentpane.
Based on my understanding, you won't need to nest a JFrame inside another JFrame and I don't think it is good design to do so too. What you can do is nest JPanels instead.
You will mainly need to know about these two classes:
JPanel ->
http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JPanel.html
Graphics ->
http://java.sun.com/javase/6/docs/api/java/awt/Graphics.html