How do I make separate buttons do separate things? - java

I have a button in a simple application I'm making which will increment a variable by one once pressed. This is it's code:
public class GUI implements ActionListener {
int clicks = 0;
int autoClickLevel = 0;
JLabel label;
JFrame frame;
JPanel panel;
public GUI() {
JButton button = new JButton("Click me!");
button.addActionListener(this);
panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(60, 100, 30, 100));
panel.setLayout(new GridLayout(0, 1));
panel.add(button);
frame.add(panel, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
public static void main(String[] args) {
new GUI();
}
#Override
public void actionPerformed(ActionEvent e) {
clicks++;
}
I would like to know how to make a separate button (which I have already made, and it shows up; JButton button2 = new JButton("Click me too!");) which changes a separate variable. button2.addActionListener(this); [plus different ways of doing it,] instead increments the clicks variable instead of a separate clicks2 variable.
My code is a bit of a mess regarding this, and this second button's script doesn't work at all. I'm also fairly new to Java so I'm not much good at figuring out this either. What's a good way to make the second button increment the other variable?

Have different ActionListeners. You can do this like this:
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// do something
}
});
Or you could define the ActionListener as its own class.

Related

JPanel won't update

I've hit a problem in getting a JPanel to update.
My simple program uses a custom JPanel which displays a label and a textfield. A Jbutton on the main panel is used to replace the JPanel with a new JPanel. The initial panel shows up fine but when the button is pressed the panel is not updated with a new MyPanel. I can tell that a new object is being created as count is being incremented.
public class SwingTest extends JFrame{
private JPanel mp;
private JPanel vp;
private JButton button;
public static void main(String[] args) {
SwingTest st = new SwingTest();
}
public SwingTest() {
vp = new MyPanel();
mp = new JPanel(new BorderLayout());
mp.add(vp, BorderLayout.CENTER);
button = new JButton("Change");
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
vp = new MyPanel();
vp.revalidate();
}
});
mp.add(button, BorderLayout.SOUTH);
this.add(mp);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setSize(250, 150);
pack();
setVisible(true);
}
}
and my custom panel....
public class MyPanel extends JPanel{
private JLabel label;
private JTextField tf;
static int count = 0;
public MyPanel(){
count++;
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
setPreferredSize(new Dimension(400, 200));
c.gridx = 0;
c.gridy = 0;
label = new JLabel(String.valueOf(count));
tf = new JTextField(10);
add(label,c);
c.gridx = 1;
add(tf, c);
}
}
You state:
A Jbutton on the main panel is used to replace the JPanel with a new JPanel.
And yet this code:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent ae) {
vp = new MyPanel();
vp.revalidate();
}
});
and yet this code does not do this at all. All it does is change the JPanel referenced by the vp variable, but has absolutely no effect on the JPanel that is being displayed by the GUI, which suggests that you're confusing reference variable with reference or object. To change the JPanel that is displayed, you must do exactly this: add the new JPanel into the container JPanel into the BorderLayout.CENTER (default) position, then call revalidate() and repaint() on the container.
e.g.,
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
// vp = new MyPanel();
// vp.revalidate();
mp.remove(vp); // remove the original MyPanel from the GUI
vp = new MyPanel(); // create a new one
mp.add(vp, BorderLayout.CENTER); // add it to the container
// ask the container to layout and display the new component
mp.revalidate();
mp.repaint();
}
});
Or better still -- use a CardLayout to swap views.
Or better still -- simply clear the value held by the JTextField.
For more on the distinction between reference variable and object, please check out Jon Skeet's answer to this question: What is the difference between a variable, object, and reference?

How do I add actions to buttons?

I want my buttons to print to the console when I click them. Here's my code. Im looking to make a basic app using this code, and I was wondering how to make the buttons have actions. For the first time, I just want to start with the console for the first time, but later possibly display images?
public static void main(String[] args) {
JFrame frame = new JFrame("GUI");
frame.setSize(320, 300);
frame.setBackground(Color.WHITE);
frame.setVisible(true);
JPanel panel = new JPanel();
panel.setSize(50,50);
JLabel label = new JLabel();
frame.add(panel);
panel.add(label);
label.setText("Welcome to Team 1389!");
Container contentPane = getContentPane();
contentPane.setBackground(Color.blue);
contentPane.setLayout(new FlowLayout());
JButton button = new JButton("MATCHES");
button.setSize(100, 30);
button.setLocation(95, 45);
button.addActionListener(null);
button.setVisible(true);
frame.add(button);
JButton button2 = new JButton("PIT TEAM");
button2.setSize(100, 30);
button2.setLocation(95, 100);
button2.setVisible(true);
frame.add(button2);
JButton button3 = new JButton("SCOUTING");
button3.setSize(100, 30);
button3.setLocation(95, 150);
button3.setVisible(true);
frame.add(button3);
}
private static Container getContentPane() {
// TODO Auto-generated method stub
return null;
}
}
You can look at this tutorial on Oracle's website, it explains things well:
Use an ActionListener. They are interfaces so you will need to add unimplemented methods where the event is handled:
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
//do stuff..
}
});
You can also create the listener separately before adding it if you desire to do so:
ActionListener listener = new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
//do stuff..
}
};
button.addActionListener(listener);

Action listener does not seem to be firing

I'm new in Java programming language and I try to write a simple code
public class TextPanel extends JPanel {
private JTextArea textArea;
public TextPanel() {
textArea = new JTextArea();
setLayout(new BorderLayout());
setVisible(true);
add(new JScrollPane(textArea), BorderLayout.CENTER);
}
public String getTextAreaText() {
String text = textArea.getText();
return text;
}
}
And I added an action listener to star button (startBtn) but when I run the program nothing is shown in console even if i put a System.out.println(textPanel.getTextAreaText()) in actionPerformed() method (code below).
public class Toolbar extends JPanel {
private JButton startBtn;
private JButton stopBtn;
private TextPanel textPanel;
public Toolbar() {
startBtn = new JButton("Start");
stopBtn = new JButton("Stop");
textPanel = new TextPanel();
setLayout(new FlowLayout(FlowLayout.LEFT));
add(startBtn);
add(stopBtn);
startBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println(textPanel.getTextAreaText());
}
});
}
}
I need help to fix this.
Java programs require a public static main method to run. Your code does not have this, and so there is no start point for your program.
Swing GUI's require that components be placed in a top-level window such as a JFrame and that this window be displayed for the components to be seen. Your code does not have this.
You will want to read the Java and Swing tutorials as all of this is very well explained there, complete with sample code.
For decent resources, please check out the info section of your Java and Swing tags:
Java info
Swing info
So consider adding a main method that creates your JFrame and adds components to the JFrame, something like:
private static void createAndShowGui() {
JFrame frame = new JFrame("My JFrame");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// add your components to your JFrame here
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
// the main method which Java uses as the starting point for your program
public static void main(String[] args) {
// let's call our Swing GUI in a thread-safe manner
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
Edit
Your code also shows possible variable shadowing. You create a TextPanel object inside of your Toolbar class, but you add this TextPanel to nothing. This suggests that you may have a TextPanel object elsewhere that is being displayed (and we can only guess because it appears that you're not showing enough code for us to know for sure). If so, then pressing your start button will get the text from a non-displayed Toolbar's JTextArea. Instead consider passing a TextPanel reference into Toolbar, something like this:
class Toolbar extends JPanel {
private JButton startBtn;
private JButton stopBtn;
private TextPanel textPanel;
public Toolbar() {
startBtn = new JButton("Start");
stopBtn = new JButton("Stop");
// textPanel = new TextPanel(); // *** note change
setLayout(new FlowLayout(FlowLayout.LEFT));
add(startBtn);
add(stopBtn);
startBtn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
if (textPanel != null) {
System.out.println(textPanel.getTextAreaText());
}
}
});
}
// **** note this method ****
public void setTextPanel(TextPanel textPanel) {
this.textPanel = textPanel;
}
}
And then when creating your objects, pass in your reference:
private static void createAndShowGui() {
Toolbar toolBar = new Toolbar();
TextPanel textPanel = new TextPanel();
toolBar.setTextPanel(textPanel); // ****** passing in my reference *******
JFrame frame = new JFrame("Add New Lines");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(textPanel);
frame.getContentPane().add(toolBar, BorderLayout.PAGE_START);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}

Alter JComponent from a Listener/Event

I'm building a Swing program and I want to be able to use a button to change certain features (Font, ForeGround Color, BackGround Color, etc.) of JComponents (JLabel, JButton).
I can do this without a problem if the components have all been explicitly declared and defined, but I cannot figure out how to do it if they are implicitly built using generic methods.
Below is the gist of what I have so far, minus some unimportant details. When styleButton1 and 2 are clicked, I want to refresh or rebuild the JFrame such that the new values for features/style (in this example, Font) are used for the components (testButton1 and 2), by changing currentFont and then repainting.
I'm not getting any errors with this, but frame and components are not being rebuilt/refreshed, i.e., nothing happens when the style buttons are clicked.
Any ideas on how to make this work? Or any other approaches I can use to get the desired effect?
//imports
public class GuiTesting extends JFrame {
public static void main(String[] args) {
frame = new GuiTesting();
frame.setVisible(true);
}
static JFrame frame;
static Font standardFont = new Font("Arial", Font.BOLD, 10);
static Font secondFont = new Font("Times New Roman", Font.PLAIN, 10);
static Font currentFont = standardFont;
public GuiTesting() {
setTitle("GUI Testing");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
JPanel mainPanel = new JPanel();
getContentPane().add(mainPanel);
mainPanel.add(basicButton("Button1"));
mainPanel.add(basicButton("Button2"));
mainPanel.add(style1Button("Style 1"));
mainPanel.add(style2Button("Style 2"));
}
public static JButton basicButton(String title) {
JButton button = new JButton(title);
button.setPreferredSize(new Dimension(80, 30));
button.setFont(currentFont);
return button;
}
public static JButton style1Button(String title) {
JButton button = new JButton(title);
button.setPreferredSize(new Dimension(80, 30));
button.setFont(standardFont);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
currentFont = standardFont;
frame.repaint();
}
});
return button;
}
public static JButton style2Button(String title) {
JButton button = new JButton(title);
button.setPreferredSize(new Dimension(80, 30));
button.setFont(secondFont);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
currentFont = secondFont;
frame.repaint();
}
});
return button;
}
}
You can store components, which need to refresh style in a list :
private static List<JComponent> components = new ArrayList<JComponent>();
add then in your basicButton() method add new component to refreshing components:components.add(button);
And then in ActionListener you can execute next lines for refreshing style:
for(JComponent c : components){
c.setFont(currentFont);
}
Or you can pass components directly to ActionListener like next :
JButton b1;
JButton b2;
mainPanel.add(b1 = basicButton("Button1"));
mainPanel.add(b2 = basicButton("Button2"));
mainPanel.add(style1Button("Style 1",b1,b2));
and style1Button() code:
public static JButton style1Button(String title,final JComponent... components) {
JButton button = new JButton(title);
button.setPreferredSize(new Dimension(80, 30));
button.setFont(standardFont);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
currentFont = standardFont;
for(JComponent c : components){
c.setFont(currentFont);
}
frame.repaint();
}
});
return button;
}
Create a styleOne method in your JComponent class that sets all of the values you need. It will have access to all fields of your class. Inside the action listener call this method.
Also, don't create your buttons statically like that. Create them within the constructor directly. If you want to override the look of the buttons do it within an init method or constructor. Or, better yet, subclass JButton.

Cannot access JPanel in public()

Recently I've attempted to make a simple program that would require moving a button across the screen several times, but in order to do this I have to be able to access the JPanel from certain parts of the code which I don't seem to be able to do, or find an alternative method. Here is a small program that should pinpoint the problems I'm having.
public class ButtonMover extends JFrame
{
public static void main(String[] args) {
new ButtonMover();
}
JButton actionButton;
public ButtonMover() {
JPanel buttonMoverPanel = new JPanel();
buttonMoverPanel.setLayout(new GridBagLayout());
this.add(buttonMoverPanel);
this.setSize(500,500);
this.setResizable(true);
this.setVisible(true);
JButton actionButton = new JButton("Testing Button");
buttonMoverPanel.add(actionButton);
ClickListener c = new ClickListener();
actionButton.addActionListener(c);
}
private class ClickListener
implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == actionButton)
buttonMoverPanel.add(new JLabel("Testing Label"));
//insert code to move button here
}
}
}
The |buttonMoverPanel.add(new JLabel("Testing Label"));| line is the only part that doesn't work, because I seem unable to make a reference to buttonMoverPanel from that area. While it doesn't actually cause any errors, it prevents actionButton from doing anything.
If you need to access a variable, here your buttonMoverPanel, then don't hide it by declaring it in a method or constructor making it only visible in that method or constructor. No, declare it in the class so that it is visible throughout the class.
So again, one improvement for this code is to declare the buttonMoverPanel in the class just the same as you're currently doing with your actionButton JButton.
Edit: you're shadowing your actionButton variable -- you're re-declaring it in the constructor, so that the button added to the GUI is not referred to by the actionButton class field. Don't re-declare it in the class.
In other words the line indicated creates a completely new actionButton variable, one that is only visible in the constructor:
JButton actionButton;
JPanel buttonMoverPanel = new JPanel();
public ButtonMover() {
buttonMoverPanel.setLayout(new GridBagLayout());
this.add(buttonMoverPanel);
this.setSize(500, 500);
this.setResizable(true);
this.setVisible(true);
JButton actionButton = new JButton("Testing Button"); // ****** here
The solution is to not re-declare the variable to rather to use the class field:
JButton actionButton;
JPanel buttonMoverPanel = new JPanel();
public ButtonMover() {
buttonMoverPanel.setLayout(new GridBagLayout());
this.add(buttonMoverPanel);
this.setSize(500, 500);
this.setResizable(true);
this.setVisible(true);
actionButton = new JButton("Testing Button"); // ****** Note the difference???
make buttonMoverPanel as class lavel variable as below..
public class ButtonMover extends JFrame
{
public static void main(String[] args) {
new ButtonMover();
}
JButton actionButton;
JPanel buttonMoverPanel ;
public ButtonMover() {
buttonMoverPanel = new JPanel();
buttonMoverPanel.setLayout(new GridBagLayout());
this.add(buttonMoverPanel);
this.setSize(500,500);
this.setResizable(true);
this.setVisible(true);
JButton actionButton = new JButton("Testing Button");
buttonMoverPanel.add(actionButton);
ClickListener c = new ClickListener();
actionButton.addActionListener(c);
}
private class ClickListener
implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == actionButton)
buttonMoverPanel.add(new JLabel("Testing Label"));
//insert code to move button here
}
}
}

Categories

Resources