I want to code a little tool that simulates a deterministic, finite automaton (like JFLAP) for myself.
My JFrame is just blank. How can I let the user place buttons on left click? And how do I assign the right values to that button (like which function to call when pressed).
I know I can place a button with
JButton button = new JButton("Press me");
frame.add(button);
But I don't know how I could dynamically code that.
Any help is welcome. Also if you think it's stupid to solve my problem with buttons, I'd like to hear suggestions for improvement.
The following code will add a JButton to a "blank" JFrame every time the mouse is clicked inside the JFrame. The JButton will be placed where the mouse click occurred. The JButton text will be a number. Each JButton will display a different number.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class AdButton extends MouseAdapter implements Runnable {
private int counter;
private JFrame frame;
private JPanel contentPane;
public void mouseClicked(MouseEvent event) {
int x = event.getX();
int y = event.getY();
JButton button = new JButton(String.valueOf(++counter));
Dimension dim = button.getPreferredSize();
button.setBounds(x, y, dim.width, dim.height);
contentPane.add(button);
contentPane.revalidate();
contentPane.repaint();
}
#Override
public void run() {
showGui();
}
private void showGui() {
frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
contentPane = (JPanel) frame.getContentPane();
contentPane.setLayout(null);
contentPane.addMouseListener(this);
frame.setSize(400, 450);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new AdButton());
}
}
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 want to add a JPanel to a JLayeredPane when the user clicks enter, but the JPanel is not showing up.
If i add the JPanel to the JLayeredPane in the JFrame's constructor, everything is working correctly.
What do i have to do, that the JPanel is showing up, when the user clicks 'enter'?
Here's the code:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class Test extends javax.swing.JFrame {
public static void main(String[] args) {
Test test = new Test();
test.setSize(800, 500);
test.setVisible(true);
}
public Test() {
setLayout(new BorderLayout());
//LayeredPane on JFrame
JLayeredPane jlp = new JLayeredPane();
jlp.setLayout(new BorderLayout());
this.add(jlp, BorderLayout.CENTER);
//Adds a JPanel to the North
JPanel jPNorth = new JPanel();
jPNorth.setBackground(Color.RED);
jlp.add(jPNorth, BorderLayout.NORTH, JLayeredPane.DEFAULT_LAYER);
//Adds Enter Keybinding
InputMap key_input_map = jlp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
ActionMap key_action_map = jlp.getActionMap();
key_input_map.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false), "add_jpanel");
key_action_map.put("add_jpanel", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JPanel jPSouth = new JPanel();
jPSouth.setBackground(Color.YELLOW);
jlp.add(jPSouth, BorderLayout.SOUTH, JLayeredPane.DEFAULT_LAYER);
System.out.println("enter");
}
});
}
}
Thanks,
Jumagoro
You did everything correct, the solution is very simple. When you dynamically add swing Components to each other, you must to use component.repaint(); and component.revalidate(); to redraw the elements. Add the two commands after everything is added. So your actionPerformed method should be changed to the following:
public void actionPerformed(ActionEvent e) {
JPanel jPSouth = new JPanel();
jPSouth.setBackground(Color.YELLOW);
jlp.add(jPSouth, BorderLayout.SOUTH, JLayeredPane.DEFAULT_LAYER);
//Need these to here!
jlp.repaint();
jlp.revalidate();
System.out.println("enter");
}
What I want is like:
But the button must be clickable. Now with my SSCCE, this button cannot be clicked. But if I add the button out of this area, e.g. set the y of the bounds of this button to 0, it's no more behind the JTabbedPane's "tabs row", and thus can be clicked.
So:
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.JLayeredPane;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
public class MigLayoutWithJTabbedPaneButton extends JFrame {
public MigLayoutWithJTabbedPaneButton() {
begin();
}
private void begin() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(null);
JTabbedPane tabsPane = new JTabbedPane();
tabsPane.setBounds(20, 20, 300, 400);
panel.add(tabsPane);
JLayeredPane tab = new JLayeredPane();
tab.setLayout(new MigLayout("insets 2 2 2 2, fillx, debug", "[]5[]5[]", "[]5[]"));
JButton button1 = new JButton("In the grid");
JButton button2 = new JButton("Out of the grid");
ActionListener ls = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(MigLayoutWithJTabbedPaneButton.this, "This can be clicked. ");
}
};
button1.addActionListener(ls);
button2.addActionListener(ls);
tab.add(button1, "cell 0 0, grow");
tabsPane.addTab("This is a tab", tab);
button2.setBounds(200, 20, 80, 20);
panel.add(button2);
getContentPane().add(panel);
pack();
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutWithJTabbedPaneButton frame = new MigLayoutWithJTabbedPaneButton();
}
});
}
}
Why? it's not the desired behaviour. The "tabs row" should not block any elements if they are at the same height of the tabs, but without any actual tabs in front of them.
My colleague told me the reason.
It has nothing to do with the layout, but just the order of adding the components. It seems that the Z axis of Java Swing behaves in a nonintuitive way: from the top layer to the bottom layer, meaning that if you add component A first and then component B, A will block B if they are in the same place. I reread the Oracle DOC and am sure that it's not mentioned anywhere!
So to get the button to work, I must first add the button and then the JTabbedPane, so the blank space of the "tabs row" will be behind the button. How strange. Swing just sucks....
I need something really basic.
I tried this:
import java.*;
import javax.swing.*;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.event.ActionEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class thisthing
{
public static void main(String[]args)
{
boolean done = false;
while (!done)
{
JFrame frame = new JFrame();
JButton button= new JButton("Add Interest");
frame.add(button);
JButton button1 = new JButton("Other Button");
frame.add(button1);
class AddInterestListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.println("hello, I was pressed");
}
}
class OtherButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
System.out.println("The Other button was pressed");
}
}
ActionListener listener = new AddInterestListener();
button.addActionListener(listener);
ActionListener listener1 = new OtherButtonListener();
button1.addActionListener(listener1);
frame.setSize(100, 100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
}
But then my computer had trouble making two buttons on one window when I ran it, so it tried to make two windows. I really don't know how to describe it except to say that it was a mess and I did something wrong.
In the end I need to add 15 buttons in a triangle shape (the famous AP peg game project)..so is there any way I can also re-position the buttons and mess with their sizes?
You could either (recommended) use another layoutmanager (or define one on your own). Or (really NOT recommended and extremely ugly solution, but it works):
frame.setLayout(null);
JButton button = new JButton("Hello world");
button.setBounds(20 , 20 , 100 , 30);
frame.add(button);
this will position the button at the given location and with the given size. Alternatively you could use
button.setSize(100 , 30);
button.setLocation(20 , 20);
Note: without a layoutmanager, you can position your components freely, but they will by default have the bounds (0 , 0 , 0 , 0), so you will always have to set the position and size to get anything visible. I only provide this solution because you asked for it, you shouldn't use it though.
I am trying to create a piano program where you click the key and using an actionlistener is plays the note from the jfugue library. For some reason after about 18 clicks without changing anything the buttons stop working. I cut down the code to analyze why this might happen, thus only two notes.
Thanks in advance for any advice!
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JComponent;
import java.awt.Color;
import javax.swing.JLayeredPane;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.*;
import org.jfugue.*;
public class ChordPlayer2 extends JComponent{
public ChordPlayer2(){
final Player player = new Player();
JFrame frame = new JFrame();
JButton cButton, csharpButton;
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(null);
buttonPanel.setLocation(0, 0);
buttonPanel.setSize(1700, 1000);
csharpButton = new JButton("");
csharpButton.setLocation(100, 150);
csharpButton.setSize(100,520);
buttonPanel.add(csharpButton);
cButton = new JButton("");
cButton.setLocation(0, 150);
cButton.setSize(160, 800);
buttonPanel.add(cButton);
class cClicker implements ActionListener {
public void actionPerformed(ActionEvent event) {
player.play("C");
}
}
class csClicker implements ActionListener {
public void actionPerformed(ActionEvent event) {
player.play("C#");
}
}
ActionListener c = new cClicker();
cButton.addActionListener(c);
ActionListener cs = new csClicker();
csharpButton.addActionListener(cs);
buttonPanel.setOpaque(true);
//return buttonPanel;
frame.add(buttonPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1700, 1000);
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
//JFrame.setDefaultLookAndFeelDecorated(true);
ChordPlayer2 demo = new ChordPlayer2();
}
}
This is a known bug in JFugue:
https://code.google.com/p/jfugue/issues/detail?id=49
The most recent version is claimed to fix this:
https://code.google.com/p/jfugue/downloads/detail?name=jfugue-4.1.0-20120125.jar&can=2&q=