I'm trying to move around jframe on the window through an event triggered from an external jpanel class, my code is below, but the doesn't achieve this. Instead the panel is the one that's moving around.
What am I doing wrong here? I am new programming in general.
package casuls_app;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Titlebar extends JPanel {
public Titlebar() {
btnClose =new JButton("X");
btnClose.setFocusable(false);
btnClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
closeButtonPressed(e);
}
}
);
controlBox =new JPanel(new GridLayout(1,1));
controlBox.setPreferredSize(new Dimension(150,40));
controlBox.add(btnClose);
controlBox.setBackground(new Color(255,255,255));
setLayout(new BorderLayout());
add(controlBox,BorderLayout.EAST);
setPreferredSize(new Dimension(0,40));
setBackground(new Color(60, 173, 205));
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
mousePressedOnTitlebar(e);
}
}
);
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
mouseDraggedOnTitlebar(e);
}
}
);
}
private void mousePressedOnTitlebar(MouseEvent e) {
posX= e.getX();
posY=e.getY();
}
private void mouseDraggedOnTitlebar(MouseEvent e) {
setLocation(e.getXOnScreen() -posX, e.getYOnScreen() -posY);
}
private void closeButtonPressed(ActionEvent e){
System.exit(0);
}
//Variables declaration
private int posX,posY;
private JButton btnClose;
private JPanel controlBox;
}
setLocation() sets the location of your JPanel (because your class extends JPanel).
If you have a reference to the JFrame, you can call the setLocation method on that object.
frame.setLocation(x, y);
If you don't have the reference, then you can follow this post which accesses the frame via SwingUtilities:
JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
Related
I'm currently trying to create a GUI for a game. I have a JFrame with a first panel with multiples button. After a click I'm supposed to change the panel. It works I created the first class which is a Frame
public class FirstWindow extends JFrame implements ActionListener
this class contains buttons which make us change panels. For this I created the panels in different classes which extends JPanel. It worked but I am blocked because once in the second panels I still have to refer to other panels but I no longer have access to my initial JFrame.
To illustrate: This is how I switch from different JPanel. The "this" refers to the frame which I can't use in the other class
public void actionPerformed(ActionEvent e) {
if ( "START".equals(e.getActionCommand())){
this.setContentPane(new PanelHello());
this.invalidate();
this.validate();
}else if ("EXIT".equals((e.getActionCommand()))) {
this.dispose();
this.invalidate();
this.validate();
}else if (!( usernameText.getText().equals(""))){
this.setContentPane(new PanelHello());
this.invalidate();
this.validate();public void actionPerformed(ActionEvent e) {
if ( "START".equals(e.getActionCommand())){
this.setContentPane(new PanelHello());
this.invalidate();
this.validate();
}else if ("EXIT".equals((e.getActionCommand()))) {
this.dispose();
this.invalidate();
this.validate();
}else if (!( usernameText.getText().equals(""))){
this.setContentPane(new PanelHello());
this.invalidate();
this.validate();
CardLayout
The CardLayout layout manager is an extremely useful layout manager, which can be used to switch between different containers.
For me, one of its limiting factors is the need to, generally, have every container you want to switch to, instantiated and added. This can make it "heavy", in terms of memory usage and difficult when it comes to passing information between panels - as its hard abstract the workflow, not impossible, just problematic.
One of the nice features, is till automatically determine the required size of the UI based all the other containers.
See How to Use CardLayout
Custom navigation
One of the things I often finding myself needing to do, is have some kind none-linear progression through the UI, and needing the ability to effectively pass information back and forward to different containers.
The can be accomplished through the use the delegation, observer pattern and dependency injection.
The basic principle here is, you might have a number of navigation controllers, each one managing a particular workflow, independently of all the others. This kind of separation simplifies the needs of the application and makes it easier to move things around, should the need to be, as any one workflow isn't coupled to another.
Another aspect, which isn't demonstrated here, is the ability to return information to the navigation controller, for example, if you have a login/register workflow, the workflow could end by returning an instance of the "user" to the controller which would then be able to make determinations about which workflow they needed to go through next (admin/moderator/basic/etc)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MasterPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MasterPane extends JPanel {
private MenuPane menuPane;
public MasterPane() {
setLayout(new BorderLayout());
presentMenu();
}
protected void presentMenu() {
removeAll();
if (menuPane == null) {
menuPane = new MenuPane(new MenuPane.NavigationListener() {
#Override
public void presentRedPane(MenuPane source) {
RedPane redPane = new RedPane(new ReturnNavigationListener<RedPane>() {
#Override
public void returnFrom(RedPane source) {
presentMenu();
}
});
present(redPane);
}
#Override
public void presentGreenPane(MenuPane source) {
GreenPane greenPane = new GreenPane(new ReturnNavigationListener<GreenPane>() {
#Override
public void returnFrom(GreenPane source) {
presentMenu();
}
});
present(greenPane);
}
#Override
public void presentBluePane(MenuPane source) {
BluePane bluePane = new BluePane(new ReturnNavigationListener<BluePane>() {
#Override
public void returnFrom(BluePane source) {
presentMenu();
}
});
present(bluePane);
}
});
}
add(menuPane);
revalidate();
repaint();
}
protected void present(JPanel panel) {
removeAll();
add(panel);
revalidate();
repaint();
}
}
public class MenuPane extends JPanel {
public static interface NavigationListener {
public void presentRedPane(MenuPane source);
public void presentGreenPane(MenuPane source);
public void presentBluePane(MenuPane source);
}
private NavigationListener navigationListener;
public MenuPane(NavigationListener navigationListener) {
this.navigationListener = navigationListener;
setBorder(new EmptyBorder(16, 16, 16, 16));
setLayout(new GridBagLayout());
JButton red = new JButton("Red");
red.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getNavigationListener().presentRedPane(MenuPane.this);
}
});
JButton green = new JButton("Green");
green.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getNavigationListener().presentGreenPane(MenuPane.this);
}
});
JButton blue = new JButton("Blue");
blue.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getNavigationListener().presentBluePane(MenuPane.this);
}
});
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
add(red, gbc);
add(green, gbc);
add(blue, gbc);
}
protected NavigationListener getNavigationListener() {
return navigationListener;
}
}
public interface ReturnNavigationListener<T> {
public void returnFrom(T source);
}
public class RedPane extends JPanel {
private ReturnNavigationListener<RedPane> navigationListener;
public RedPane(ReturnNavigationListener<RedPane> navigationListener) {
this.navigationListener = navigationListener;
setBackground(Color.RED);
setLayout(new BorderLayout());
add(new JLabel("Roses are red", JLabel.CENTER));
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getReturnNavigationListener().returnFrom(RedPane.this);
}
});
add(back, BorderLayout.SOUTH);
}
public ReturnNavigationListener<RedPane> getReturnNavigationListener() {
return navigationListener;
}
}
public class BluePane extends JPanel {
private ReturnNavigationListener<BluePane> navigationListener;
public BluePane(ReturnNavigationListener<BluePane> navigationListener) {
this.navigationListener = navigationListener;
setBackground(Color.BLUE);
setLayout(new BorderLayout());
add(new JLabel("Violets are blue", JLabel.CENTER));
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getReturnNavigationListener().returnFrom(BluePane.this);
}
});
add(back, BorderLayout.SOUTH);
}
public ReturnNavigationListener<BluePane> getReturnNavigationListener() {
return navigationListener;
}
}
public class GreenPane extends JPanel {
private ReturnNavigationListener<GreenPane> navigationListener;
public GreenPane(ReturnNavigationListener<GreenPane> navigationListener) {
this.navigationListener = navigationListener;
setBackground(Color.GREEN);
setLayout(new BorderLayout());
add(new JLabel("Kermit is green", JLabel.CENTER));
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getReturnNavigationListener().returnFrom(GreenPane.this);
}
});
add(back, BorderLayout.SOUTH);
}
public ReturnNavigationListener<GreenPane> getReturnNavigationListener() {
return navigationListener;
}
}
}
I am trying to set a new text into a button when you press on it. However it does not seem to work, I am doing something wrong, and I do not know what...
EDIT -----I attach the code for easier comprehension of what I mean
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GrowAndShrinkSquareGUItest {
JFrame frame;
SquareDrawPanel bigGreen;
SquareDrawPanel smallGreen;
JButton button;
growAndShrinkListener listener;
public class SquareDrawPanel extends JPanel {
int width;
int height;
SquareDrawPanel(int w, int h) {
width = w;
height = h;
}
public void paintComponent(Graphics g) {
g.setColor(Color.green);
g.fillRect(frame.getWidth() / 2 - (width / 2), frame.getHeight()
/ 2 - (height / 2) - 15, width, height);
}
}
public class growAndShrinkListener implements ActionListener {
// JButton button;
growAndShrinkListener(JButton button) {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
button.setText("Unselect all");
}
}
public static void main(String[] args) {
GrowAndShrinkSquareGUItest test = new GrowAndShrinkSquareGUItest();
test.go();
}
private void createPanels() {
bigGreen = new SquareDrawPanel(400, 400);
smallGreen = new SquareDrawPanel(100, 100);
}
private void drawPanel(JPanel panel) {
frame.add(panel);
panel.setVisible(true);
frame.add(panel, BorderLayout.CENTER);
}
private void createListenerButton() {
listener = new growAndShrinkListener(button);
}
private void loop(){}
public void go() {
frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createPanels();
drawPanel(smallGreen);
createListenerButton();
frame.setVisible(true);
}
}
It is because you use the button variable that is not defined in the scope of actionPerformed method. Java variables have scope and they are available inside curly braces where they're defined. The actionPerformed method is out of the curly braces of growAndShrinkListener method. The fixed code:
public class growAndShrinkListener implements ActionListener {
growAndShrinkListener(JButton button) {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if(source instanceof JButton) {
button = (JButton) source;
button.setText("Click to shrink square");
}
}
}
Alternatively, you can use a private variable:
public class growAndShrinkListener implements ActionListener {
private JButton button;
growAndShrinkListener() {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
button.setText("Click to shrink square");
}
}
Note: You should not overwrite the content of the argument in the constructor. The argument that you got is not a "pointer" to the callee's variable, but just a simple reference to that. If you overwrite, then the content will be lost for you and calle will not know that.
change like this..
public class YourSuperClass{
private JButton button;
public YourSuperClass(){
// your logics
button = new JButton();
button.addActionListener(new GrowAndShrinkListener(button));
frame.add(button, BorderLayout.NORTH);
}
class GrowAndShrinkListener implements ActionListener {
GrowAndShrinkListener(JButton button) {
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button){
button.setText("Click to shrink square");
}
}
}
}
Try This :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class frame extends JFrame
{
JButton b;
public frame()
{
setLayout(new BorderLayout());
b=new JButton("Press");
add(b,BorderLayout.SOUTH);
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
b.setText("Clicked");
}
});
}
public static void main (String[] args) {
frame f=new frame();
f.setExtendedState(MAXIMIZED_BOTH);
f.setVisible(true);
}
}
How do I put a button on the border that surrounds the frame like this cog:
_"Is the a short example anywhere? "
Yea, here... This very basic. You need to do alot more to it. You'll notice I have to add a MouseMotionListener to the JPanel that acts as the top frame border, because when you remove the decoration from the frame, you're also taking away that functionality. So the MouseMotionListener makes the frame draggable again.
You would also have to implement resizing if you wished. I already implemented the Systemexit()` when you press the image. Test it out. You need to provide your own image.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class UndecoratedExample {
static JFrame frame = new JFrame();
static class MainPanel extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
static class BorderPanel extends JPanel {
JLabel stackLabel;
int pX, pY;
public BorderPanel() {
ImageIcon icon = new ImageIcon(getClass().getResource(
"/resources/stackoverflow1.png"));
stackLabel = new JLabel();
stackLabel.setIcon(icon);
setBackground(Color.black);
setLayout(new FlowLayout(FlowLayout.RIGHT));
add(stackLabel);
stackLabel.addMouseListener(new MouseAdapter() {
public void mouseReleased(MouseEvent e) {
System.exit(0);
}
});
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
// Get x,y and store them
pX = me.getX();
pY = me.getY();
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent me) {
frame.setLocation(frame.getLocation().x + me.getX() - pX,
frame.getLocation().y + me.getY() - pY);
}
});
}
}
static class OutsidePanel extends JPanel {
public OutsidePanel() {
setLayout(new BorderLayout());
add(new MainPanel(), BorderLayout.CENTER);
add(new BorderPanel(), BorderLayout.PAGE_START);
setBorder(new LineBorder(Color.BLACK, 5));
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.setUndecorated(true);
frame.add(new OutsidePanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
When I add a MouseListener/FocusListener to a JPanel which has a BorderLayout and JComponents in it, I can't catch mouse or focus events. Is there any way to catch a JPanel's mouse and focus events which has a BorderLayout?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Application extends JFrame{
public Application(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jPanel = new JPanel(new BorderLayout());
jPanel.add(new JButton("Button"));
jPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
System.out.println("mouseExited");
}
});
// if border is set then listener works if not does not
// jPanel.setBorder(new LineBorder(Color.black, 1));
setLayout(new FlowLayout());
add(jPanel);
setSize(400, 400);
setVisible(true);
}
public static void main(String[]args){
new Application().setVisible(true);
}
}
As said, just a simple mistake. Because JFrame is given a FlowLayout, the JPanel occupies the area required for JButton only. You can test that by adding a Border to the JPanel.
Now it works,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Application extends JFrame {
private static final long serialVersionUID = 1L;
public Application() {
JPanel jPanel = new JPanel();
jPanel.setLayout(new FlowLayout());
jPanel.add(new JButton("Button"));
jPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseExited(MouseEvent e) {
System.out.println("mouseExited");
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
add(jPanel);
setSize(400, 400);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Application().setVisible(true);
}
});
}
}
The following Code prints the corresponding Events to StdOut.
JFrame frame = new JFrame();
JPanel panel = new JPanel(new BorderLayout());
JPanel innerPanel = new JPanel();
innerPanel.setSize(200,200);
panel.add(innerPanel);
panel.addMouseListener(new MouseListener() {
public void mouseReleased(MouseEvent e) {
System.out.println("MouseReleased");
}
public void mousePressed(MouseEvent e) {
System.out.println("MousePressed");
}
public void mouseExited(MouseEvent e) {
System.out.println("MouseExited");
}
public void mouseEntered(MouseEvent e) {
System.out.println("MouseEntered");
}
public void mouseClicked(MouseEvent e) {
System.out.println("MouseClicked");
}
});
frame.setContentPane(panel);
frame.setVisible(true);`
I am using the following code:
class ButtonPanel extends JPanel implements ActionListener
{
public ButtonPanel()
{
yellowButton=new JButton("Yellow");
blueButton=new JButton("Blue");
redButton=new JButton("Red");
add(yellowButton);
add(blueButton);
add(redButton);
yellowButton.addActionListener(this);
blueButton.addActionListener(this);
redButton.addActionListener(this);
}
public void actionPerformed(ActionEvent evt)
{
Object source=evt.getSource();
Color color=getBackground();
if(source==yellowButton) color=Color.yellow;
else if (source==blueButton) color=Color.blue;
else if(source==redButton) color=Color.red;
setBackground(color);
repaint();
}
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;
}
class ButtonFrame extends JFrame
{
public ButtonFrame()
{
setTitle("ButtonTest");
setSize(400,400);
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
});
Container contentPane=getContentPane();
contentPane.add(new ButtonPanel());
}
}
public class ButtonTest
{
public static void main(String args[])
{
JFrame frame=new ButtonFrame();
frame.show();
}
}
In actionperformed() I want to modify my panel and add some more component, is there any way to do this?
Yes.
Just call add() for the panel and then revalidate() and repaint();
but in actionperformed() i want to modify my panel and want to add some more component... Is there any way to do this....
Yes, you can add the components to the JPanel or "this" via the add(...) method, and you'll need to call revalidate() and then sometimes repaint() (especially if you also remove components) on the JPanel (this). But before you do this, if you haven't already done so, I think that you'll want to read the tutorials on using the layout managers so you can add components that are well situated.
hmmm I hard to comment anything, there are lots of mistakes, please start with this code
import java.awt.Color;
import java.awt.Dimension;
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.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ButtonPanel extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private JButton yellowButton;
private JButton blueButton;
private JButton redButton;
public ButtonPanel() {
yellowButton = new JButton("Yellow");
yellowButton.addActionListener(this);
blueButton = new JButton("Blue");
blueButton.addActionListener(this);
redButton = new JButton("Red");
redButton.addActionListener(this);
add(yellowButton);
add(blueButton);
add(redButton);
setPreferredSize(new Dimension(400, 400));
}
#Override
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
Color color = getBackground();
if (source == yellowButton) {
color = Color.yellow;
} else if (source == blueButton) {
color = Color.blue;
} else if (source == redButton) {
color = Color.red;
}
setBackground(color);
revalidate();
repaint();
}
public static void main(String args[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("ButtonTest");
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.add(new ButtonPanel());
frame.pack();
frame.setVisible(true);
}
});
}
}