Glasspane does not work, java - java

I have been working on a little java application, and I wanted to add a waiting graphics on the glasspane of the rootpane of the application, here is the classes:
public class WaitPanel extends JPanel {
public WaitPanel() {
this.setLayout(new BorderLayout());
JLabel label = new JLabel(new ImageIcon("spin.gif"));
this.setLayout(new BorderLayout());
this.add(label, BorderLayout.CENTER);
this.setOpaque(false);
this.setLayout(new GridBagLayout());
this.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
me.consume();
Toolkit.getDefaultToolkit().beep();
}
});
}
public void paintComponent(Graphics g) {
g.setColor(new Color(0, 0, 0, 140));
g.fillRect(0, 0, getWidth(), getHeight());
}}
and the main class :
public class NewJFrame extends JFrame {
public NewJFrame() {
JButton button =new JButton("Click");
getContentPane().setLayout(new FlowLayout());
this.getContentPane().add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getRootPane().setGlassPane(new WaitPanel());
getRootPane().getGlassPane().setVisible(true);
}
});
}
but when I change the button action to :
getRootPane().setGlassPane(new WaitPanel());
getRootPane().getGlassPane().setVisible(true);
Scanner sc=new Scanner(System.in);
String s=sc.next();
getRootPane().getGlassPane().setVisible(false);
It does not work.

Your problem (one of them) is that your code freezes the Swing event thread with its use of a Scanner based on System.in, and in so doing prevents the GUI from updating its graphics, including it's glass pane. Solution -- don't do that. If you want to block the GUI or pause it, use a Swing Timer, or a JOptionPane.
For instance, you could change
getRootPane().setGlassPane(new WaitPanel());
getRootPane().getGlassPane().setVisible(true);
Scanner sc=new Scanner(System.in);
String s=sc.next();
getRootPane().getGlassPane().setVisible(false);
to something like this:
getRootPane().setGlassPane(new WaitPanel());
getRootPane().getGlassPane().setVisible(true);
int delay = 4 * 1000; // 4 second delay
new javax.swing.Timer(delay, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
getRootPane().getGlassPane().setVisible(false);
((javax.swing.Timer) e).stop();
}
}).start();

Related

Press JButton to draw a ball, the ball is not visible

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();
}
});
}
}

graphics not displaying after appropriate event

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

How do I change what's being displayed in Java Swing?

I don't really know how to word this question, but I can explain what I'm trying to do.
I have my program drawing a basic menu with a background image and 3 buttons along the bottom. I want to make it so that when I press one of the buttons, the menu and the background image change to a different scene. Like pressing play to start a game or pressing options to go to an option menu.
This is my code for the primary menu:
private final void initUI() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
add(panel);
panel.add(Box.createVerticalGlue());
JPanel bottom = new JPanel();
bottom.setAlignmentX(1f);
bottom.setLayout(new BoxLayout(bottom, BoxLayout.X_AXIS));
JButton plyBtn = new JButton("Play");
plyBtn.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent event){
GameFrame_Test1 game1 = new GameFrame_Test1();
game1.setVisible(true);
}
});
JButton opBtn = new JButton("Options");
JButton quitButton = new JButton("Exit");
quitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.exit(0);
}
});
bottom.add(plyBtn);
bottom.add(Box.createRigidArea(new Dimension(100, 0)));
bottom.add(opBtn);
bottom.add(Box.createRigidArea(new Dimension(100, 0)));
bottom.add(quitButton);
bottom.add(Box.createRigidArea(new Dimension(100, 0)));
panel.add(new GraphicTest_1());
panel.add(bottom);
panel.add(Box.createRigidArea(new Dimension(0,15)));
setTitle("Justice GUI");
setSize(1280, 720);
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DisplayFrame ex = new DisplayFrame();
ex.setVisible(true);
}
});
}
This is my code for the frame I want to change to so far:
class GameFrame_Test1 extends JPanel{
private Image mshi;
public GameFrame_Test1() {
loadImage();
setSurfaceSize();
}
private void loadImage() {
mshi = new ImageIcon("content/Placeholder_Map.png").getImage();
}
private void setSurfaceSize() {
Dimension d = new Dimension();
d.width = mshi.getWidth(null);
d.height = mshi.getHeight(null);
setPreferredSize(d);
}
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(mshi, 0, 0, null);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
I am very new to Java Swing, and this is a test program for me to learn how to use it. I have looked online for a solution, but not being able to word my question makes it hard. Thanks to anyone who can help!
I want to make it so that when I press one of the buttons, the menu and the background image change to a different scene.
You should be using a Card Layout as the layout manager of the content panel. Then you can swap a different panel on the frame when a button is clicked.
Check out the section from the Swing tutorial on How to Use CardLayout for more information and working examples.

how to paint images on clicking button in frame?

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);

drawing on new thread (canvas is good but not working on jpanel correctly)

I was drawing my game on Canvas, all was god, but I changed it into a JPanel, but now its not working correctly, here are the codes, you can just copy them and you'll see where is the problem (I have a menu and after clicking on the button it should create new thread and there i want to draw, the problem in JPanel is that the button is able to see, its blinking and i can press it, in canvas it was fine, there wasn't any button). I solved it, that after clicking on the button I setted him unvisible (button.setVisible(false)), but these codes are just examples and in my game I have more buttons, so its not practical because I need them to see after the game ends. I think I just forgot an important method in JPanel, thx for help, codes:
//Main class representing menu
public class Sandbox extends JFrame{
Panel p = new Panel();
public static void main(String[] args) {
new Sandbox();
}
public Sandbox() {
setLayout(null);
setPreferredSize(new Dimension(200, 200));
setDefaultCloseOperation(EXIT_ON_CLOSE);
setResizable(false);
final JButton but = new JButton("Button");
but.setBounds(0, 0, 50, 50);
but.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
p.start();
}
});
add(p);
add(but);
pack();
setVisible(true);
}
}
//Drawing on Canvas -> working well
public class Panel extends Canvas implements Runnable {
Thread t;
public Panel() {
setSize(new Dimension(200, 200));
setVisible(false);
}
public void start() {
t = new Thread(this);
t.start();
setVisible(true);
}
public void draw() {
BufferStrategy b = getBufferStrategy();
if(b == null) {
createBufferStrategy(3);
return;
}
Graphics g = b.getDrawGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, 200, 200);
g.dispose();
b.show();
}
#Override
public void run() {
while(!t.isInterrupted()) {
try {
draw();
t.sleep(200);
} catch (InterruptedException ex) {}
}
}
}
//Drawing on JPanel -> here i can press the button after first click on it
public class Panel extends JPanel implements Runnable {
Thread t;
public Panel() {
setSize(new Dimension(200, 200));
setVisible(false);
}
public void start() {
t = new Thread(this);
t.start();
setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 200, 200);
}
#Override
public void run() {
while(!t.isInterrupted()) {
try {
repaint();
t.sleep(200);
} catch (InterruptedException ex) {}
}
}
}
Not sure I understand exactly what you are trying to do but you do have a couple of problems:
the setVisible(true) method should be invoked AFTER you have added all the components to the frame and packed the frame.
by default the content pane of a JFrame uses a BorderLayout. You code is adding two components to the CENTER of the BorderLayout, but a BorderLayout only allows you to add one component to the CENTER, so only the last component added will be displayed.

Categories

Resources