So, I've been studying GUI's and event handling, and I make this code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class drawing extends JComponent {
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.draw(new Rectangle(100, 100, 100, 100));
}
}
class TwoButtons {
public static void main(String[] args) {
TwoButtons two = new TwoButtons();
two.go();
}
JButton button1 = new JButton("button 1");
JButton button2 = new JButton("button 2");
drawing D = new drawing();
JFrame frame = new JFrame("title");
void go() {
button1.addActionListener(new button1Action());
button2.addActionListener(new button2Action());
frame.add(BorderLayout.SOUTH, button1);
frame.add(BorderLayout.NORTH, button2);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(900, 900);
frame.setVisible(true);
}
class button1Action implements ActionListener {
public void actionPerformed(ActionEvent ev) {
frame.add(D);
}
}
class button2Action implements ActionListener {
public void actionPerformed(ActionEvent ev) {
button2.setText("action 2");
}
}
}
So this code generates two buttons at SOUTH and another at NORTH of JFrame.
It should display a square as soon as user clicks button1, but it displays a Square after both button1 and button2 are clicked (first button1 and then button2).
Why is this happening? and how to fix it?
Swing is lazy. When dynamically updating the UI, you need to instruct it when you want it to perform and update pass, for example...
class button1Action implements ActionListener {
public void actionPerformed(ActionEvent ev) {
frame.add(D);
frame.revalidate();
frame.repaint();
}
}
This triggers a layout and paint pass after D is added to the frame
Related
So, I want to draw a ball whenever the user presses JButton. My problem is that the ball is not visible after I call revalidate() and repaint(). Am I forgetting something?
Here is my code, I have another class for the queue and stack that's why I extended Queueue. My buttons are visible and I know they work when I press them, it's jst that the ball doesn't show up on the screen. Earlier I tried to have my void paintComponent in my ActionListener but it would not work. I then wanted to just call the method but because of the Graphics g parameter it would not work as well. So I saw similar issue where someone suggested to use boolean
public class Main extends Queueue {
static boolean clicked = false;
public void paintComponent(Graphics g) {
if(clicked) {
g.setColor(Color.BLACK);
g.fillOval(60, 60, 15, 15);
}
}
public static void main (String[] args) {
Queueue qq = new Queueue();
JFrame f = new JFrame();
JPanel p = new JPanel();
JButton b1 = new JButton("Queue");
JButton b2 = new JButton("Stack");
JButton b3 = new JButton("Ball");
f.setSize(700, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
p.setBackground(Color.RED);
p.add(b1);
p.add(b2);
p.add(b3);
f.add(p);
f.setVisible(true);
b1.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent arg0) {
qq.Q();
}
});
b2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
qq.S();
}
});
b3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
clicked = true;
f.revalidate();
f.repaint();
}
});
You had some syntax errors which I corrected. I also trimmed it down to more clearly demonstrate the procedure. Here is a working version that just paints the ball.
public class Main extends JPanel {
static boolean clicked = false;
public static void main(String[] args) {
JFrame f = new JFrame();
Main m = new Main();
JButton b3 = new JButton("Ball");
f.setSize(700, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(m);
m.add(b3);
f.setVisible(true);
b3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
clicked = true;
f.repaint();
}
});
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (clicked) {
g.setColor(Color.BLACK);
g.fillOval(60, 60, 15, 15);
}
}
}
Your class should extend JPanel
Add it to the JFrame.
Add the JButton to Main instance
and in paintComponent call super.paintComponent(g) first.
Check out The Java Tutorials for more information on how to paint.
In response to your comments, the following should work. The main issue is that you need to have the paintComponent inside a JPanel, not as a method in Queueue.
public class Main extends Queueue {
static boolean clicked = false;
public static void main(String[] args) {
JFrame f = new JFrame();
Main m = new Main();
JPanel panel = new JPanel() {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (clicked) {
g.setColor(Color.BLACK);
g.fillOval(60, 60, 15, 15);
}
}
};
JButton b3 = new JButton("Ball");
f.setSize(700, 500);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(panel);
panel.add(b3);
f.setVisible(true);
b3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
clicked = true;
f.repaint();
}
});
}
}
I want to use 2 buttons on the same JFrame to do different task each. One to change the label on the right and one to change the color of the circle in the middle. (The random changing color is on another class.)
For some unknown reason the program doesn't seem to recognize the inner classes which exists inside the main class (class TwoButtons). I am pretty new to java and I cannot find what I am doing wrong.... Could you please help me to resolve my problem?
package twoButtonsPackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TwoButtons {
JFrame frame;
JLabel label;
public static void main(String[] args) {
TwoButtons gui = new TwoButtons();
gui.go();
}
public void go(){
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton labelButton = new JButton("Change label");
labelButton.addActionListener(new LabelListener());
JButton colorButton = new JButton("Change cirle");
colorButton.addActionListener(new ColorListener());
label = new JLabel("I'm a labele");
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().add(BorderLayout.WEST, labelButton);
frame.getContentPane().add(BorderLayout.EAST, label);
frame.setSize(300, 300);
frame.setVisible(true);
class LabelListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
label.setText("Ouch!");
}
}
class ColorListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
}
}
}
I get an error on
labelButton.addActionListener(new LabelListener());
and on
colorButton.addActionListener(new ColorListener());
It says on both occasions that both LabelListener and ColorListener cannot resolved as a type.
Thank you very much in advance..!!
You need to move the classes LabelListener and ColorListener out of the public void go() Method
class LabelListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
label.setText("Ouch!");
}
}
and
class ColorListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
}
In java, you cannot define classes (just like variables, in methods) in methods after you use them, so, instead try defining the classes ColorListener and LabelListener within the class TwoButtons, instead of defining them in the go method, like so: (This is generally better practice)
package twoButtonsPackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TwoButtons {
JFrame frame;
JLabel label;
public static void main(String[] args) {
TwoButtons gui = new TwoButtons();
gui.go();
}
public void go(){
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton labelButton = new JButton("Change label");
labelButton.addActionListener(new LabelListener());
JButton colorButton = new JButton("Change cirle");
colorButton.addActionListener(new ColorListener());
label = new JLabel("I'm a labele");
MyDrawPanel drawPanel = new MyDrawPanel();
frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.getContentPane().add(BorderLayout.WEST, labelButton);
frame.getContentPane().add(BorderLayout.EAST, label);
frame.setSize(300, 300);
frame.setVisible(true);
}
class LabelListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
label.setText("Ouch!");
}
}
class ColorListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
}
}
Given a JFrame I am drawing lines on it by handling MouseListener. Now I had added a button to choose a color from Color chooser . I want that after selecting a color all lines that i draw become of that choose color.
Here is my code I had tried adding code to ButtonListener but can't get any success.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class myJPanelstd extends JPanel implements MouseMotionListener
{
JButton bmessage;
JPanel p1;
JButton changeColor;
public myJPanelstd(){
setBackground(Color.pink);
setLayout(new BorderLayout());
p1 = new JPanel();
p1.setLayout(new GridLayout(3,3));
bmessage = new JButton();
changeColor= new JButton("CHANGE COLOR");
p1.add(bmessage);
p1.add(changeColor);
add(p1,"South");
changeColor.addActionListener(new ButtonListener());
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent evt)
{
Point pt = evt.getPoint();
String sx = "x = " + pt.getX();
String sy = "y = " + pt.getY();
bmessage.setText("you are doing fine");
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Color c = JColorChooser.showDialog(null, "Choose a Color", sampleText.getForeground());
//if (c != null)
//sampleText.setForeground(c);
}
}
public void mouseDragged(MouseEvent evt)
{
bmessage.setText("Nice Drawing!");
Point pt = evt.getPoint();
Graphics gg = getGraphics();
gg.setColor(Color.RED);
gg.fillRect(pt.x,pt.y,5,5);
getGraphics().setColor(Color.RED);
getGraphics().fillRect(pt.x,pt.y,5,5);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.blue);
Image myImage = Toolkit.getDefaultToolkit().getImage("images/fred.jpg");
g.drawImage(myImage, 0, 0, this);
g.setColor(Color.yellow);
g.drawString("Draw on Me", 250,150);
}
}
You need to store all painted elements and repaint them in paintComponent(), otherwise they will disappear when you minimalize/resize/cover window and uncover/ etc.
For example every line you are creating store in ArrayList and repaint them in a loop at the beginning of paintComponent(), then when you change color, all lines will be painted in new color.
Don't forget to repaint() after color change
Simple pseudo code - just to see the idea - it won't compile
class A extends JPanel
{
ArrayList<Shape> shapes;
public A()
{
shapes = new ArrayList<Shape>();
}
public void afterMouseRelease();
{
//paint the shape
shapes.add(yourNewShape); // store it for later
}
public void paintComponen(Graphics g)
{
super.paintComponent();
setColor()
for(Shape s : shapes)
{
// paint it again
}
// rest of painting
}
}
I used Shape class from java.awt.Shape, and Graphics2D in my app some time ago.
Use JColorChooser.showDailog(-,-); to choose color under your action listener
Refer sample color picker using Java swing
// ColorPicker.java
// A quick test of the JColorChooser dialog.
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ColorPicker extends JFrame {
public ColorPicker() {
super("JColorChooser Test Frame");
setSize(200, 100);
final Container contentPane = getContentPane();
final JButton go = new JButton("Show JColorChooser");
go.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Color c;
c = JColorChooser.showDialog(
((Component)e.getSource()).getParent(),
"Demo", Color.blue);
contentPane.setBackground(c);
}
});
contentPane.add(go, BorderLayout.SOUTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String args[]) {
ColorPicker cp = new ColorPicker();
cp.setVisible(true);
}
}
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);
}
}
I've made two buttons in frame .I want to know how to display different images on clicking different buttons?
is there another way out or i have to make panel?I am at beginner stage
package prac;
import java.awt.*;
import java.awt.event.*;
public class b extends Frame implements ActionListener{
String msg;
Button one,two;
b()
{ setSize(1000,500);
setVisible(true);
setLayout(new FlowLayout(FlowLayout.LEFT));
one=new Button("1");
two=new Button("2");
add(one);
add(two);
one.addActionListener(this);
two.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
msg=e.getActionCommand();
if(msg.equals("1"))
{
msg="Pressed 1";
}
else
msg="pressed 2";
repaint();
}
public void paint(Graphics g)
{
g.drawString(msg,100,300);
}
public static void main(String s[])
{
new b();
}
}
Use JLabel and change the icon when button is clicked.
Some points:
call setVisible(true) in the end after adding all the component.
use JFrame#pack() method that automatically fit the components in the JFrame based on component's preferred dimension instead of calling JFrame#setSize() method.
sample code:
final JLabel jlabel = new JLabel();
add(jlabel);
final Image image1 = ImageIO.read(new File("resources/1.png"));
final Image image2 = ImageIO.read(new File("resources/2.png"));
JPanel panel = new JPanel();
JButton jbutton1 = new JButton("Show first image");
jbutton1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
jlabel.setIcon(new ImageIcon(image1));
}
});
JButton jbutton2 = new JButton("Show second image");
jbutton2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
jlabel.setIcon(new ImageIcon(image2));
}
});
panel.add(jbutton1);
panel.add(jbutton2);
add(panel, BorderLayout.NORTH);