I am trying to move an image up and down by using arrow keys.I have used ASCII values to check which key is pressed, but the handler for keyPressed is not getting called. I checked by applying a breakpoint but nothing happens.
package com.google.play;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class ShootingBubble extends JPanel implements ActionListener,KeyListener {
int y=250;
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 200, 300, 400);
g.fillRect(0, 200, 300, 400);
g.setColor(Color.GRAY);
g.drawRect(800, 200, 300, 400);
g.fillRect(800, 200, 300, 400);
g.setColor(Color.BLACK);
g.drawLine(1000,200, 350, 200);
g.setColor(Color.BLACK);
g.drawOval(295, 190, 20, 20);
g.fillOval(295, 190, 20, 20);
g.setColor(Color.BLACK);
g.drawLine(0,190, 300, 190);
g.setColor(Color.BLACK);
g.drawLine(310,190, 310, y);
ImageIcon ic=new ImageIcon("C:\\Users\\acer\\Desktop\\mario.gif");
ic.paintIcon(this, g, 295, y);//moving image with help of y variable
ic.paintIcon(this, g, 0, 150);
ic.paintIcon(this, g, 40, 150);
ic.paintIcon(this, g, 80, 150);
ic.paintIcon(this, g, 120, 150);
ImageIcon ic1=new ImageIcon("C:\\Users\\acer\\Desktop\\index.jpg");
ic1.paintIcon(this, g, 320, 130);
}
public ShootingBubble() {
setBackground(Color.WHITE);
setFocusTraversalKeysEnabled(false);
}
void init(){
}
#Override
public void keyReleased(KeyEvent e) {
System.out.println("c");
}
#Override
public void keyTyped(KeyEvent e) {
System.out.println("d");
}
public static void main(String[] args) {
ShootingBubble st=new ShootingBubble();
JFrame jf=new JFrame();
jf.setSize(1000, 600);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.getContentPane().add(st);
}
#Override
public void actionPerformed(ActionEvent arg0) {
}
#Override
public void keyPressed(KeyEvent arg0) {
if(arg0.getKeyCode()==38){
y-=2;//updating image position in vertically upward direction
}
if(arg0.getKeyCode()==40)
{
y=y+2;//updating image position in vertically downward direction
}
System.out.println("Key Pressed "+arg0.getKeyCode()+ " "+arg0.getKeyChar());
repaint();;
}
}
Several problems, not all related to the KeyListener:
Don't do I/O in the paintComponent() method. The painting methods are for painting only. Swing will determine when the component needs to be repainted and you don't want to continually read the image over and over. Read the image in your constructor.
All components should be added to the frame BEFORE the frame.setVisible(...) method is invoked. This will make sure the layout manager is invoked on all components.
Don't use "magic numbers". I have no idea what "38" and "40" are. How do you even know what they are? If you copied that code from a tutorial then dump the tutorial! Instead you should use KeyEvent.VK_???
Even if you add the KeyListener to the frame, the code probably won't work, because KeyEvents are only dispatched to the component with focus and I don't know the frame will always have focus. Really the panel should have focus since it is the component doing the painting.
Don't use a KeyListener. Swing was designed to by used with Key Bindings. See Motion With the Keyboard for more information and examples.
You have to register the keylistener.
add jf.addKeyListener(this); to your main method.
Related
I have just started with Graphics in java, and I'm already stuck. I have tried to set the color of the JPanel to red but nothing seems to work! Any help is highly appreciated.
JFrame class:
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Color;
public class redBoxFrame{
public static void main(String[]args){
JFrame f = new JFrame();
f.setSize(400, 200);
f.setTitle("A red box");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new redBoxPanel();
p.setBackground(Color.RED);
f.add(p);
f.setVisible(true);
}
}
JPanel class:
import java.awt.Graphics;
import javax.swing.JPanel;
import java.awt.Color;
public class redBoxPanel extends JPanel {
public void paintComponent(Graphics g){
g.fillRect(0, 0, 100, 100);
g.setColor(Color.RED);
}
}
As you can see I have both tried to declare the color in the JFrame class and in the JPanel class but none of them seem to work.
Thank you!
Everyone here seems to miss the fact that the colour should be set before drawing.
I'll set the main background to BLUE for demo purposes.
public static void main(String[] args) {
//...
JPanel p = new redBoxPanel();
// BLUE bg. This covers the whole panel.
p.setBackground(Color.BLUE);
//...
}
And now for the red box!
public static class redBoxPanel extends JPanel {
#Override public void paintComponent(Graphics g) {
// You need to call the superclass' paintComponent() so that the
// setBackground() you called in main() is painted.
super.paintComponent(g);
// You need to set the colour BEFORE drawing your rect
g.setColor(Color.RED);
// Now that we have a colour, perform the drawing
g.fillRect(0, 0, 100, 100);
// More, for fun
g.setColor(Color.GREEN);
g.drawLine(0, 0, 100, 100);
}
}
I think you you are missing super.paintComponent(g); in your painComponent method.
I Believe that the solution is working however you are, like you said in your question, setting the background in the JFrame class and the JPanel class.
if you remove the setBackground from the JFrame class you should see only the rectangle that you are drawing. Please try the below solution and let us know if it works.
JFrame class:
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Color;
public class redBoxFrame{
public static void main(String[]args){
JFrame f = new JFrame();
f.setSize(400, 200);
f.setTitle("A red box");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new redBoxPanel();
f.add(p);
f.setVisible(true);
}
}
JPanel class:
import java.awt.Graphics;
import javax.swing.JPanel;
import java.awt.Color;
public class redBoxPanel extends JPanel {
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(0, 0, 100, 100);
g.setColor(Color.RED);
}
}
I have a JButton in a JPanel that has graphics, but the button won't show as it is in the layer BELOW the graphics.
I've already read this : Put JLabel in front of Graphics 2D Rectangle in JPanel
But the answers tell me not to use the NullLayoutManager.
Is there any way to do it with the NullLayoutManager, because I need to specifically position my JButton in my JPanel?
If this is not possible, are there any other ways I can position a JComponent at a position x, y? I've also googled that and NullLayoutManager is what the world wide web gives me.
Code:
JPanel p = new JPanel(){
#Override
public void paintComponent(Graphics gr){
Graphics2D g = (Graphics2D) gr;
g.setColor(Color.BLACK);
g.fillRect(0, 0, 800, 800);
g.setFont(titlefont);
g.setColor(Color.WHITE);
g.drawString("dont steal my game idea plz", 25, 100);
g.drawImage(bi, 138, 70, null);
repaint();
}
};
p.setLayout(null);
JButton b = new JButton("PLAY");
b.setLocation(100, 200);
b.setFont(ufont);
f.add(p);
p.add(b);
Is there any way to do it with the NullLayoutManager, because I need to specifically position my JButton in my JPanel?
The answer is "yes", but do you understand what the layout managers actually do? How they work and the role they fill in order to replace them and take over the requirements of their functionality?
null layouts are just a bad idea, there are so many things that can wrong with them it's mind numbing just trying to think about it. If none of the stock layout managers do what you want, maybe consider using MigLayout or some other layout manager, possibly even writing your own, at least this way, you will still be able to work within the API, which has been designed to work around layout managers.
There are a couple of other issues, first, you're painting your image AFTER the paint the text, this could cause some issues if the two overlap. Second, you're breaking the paint chain by not calling super.paintComponent, this could result in some unexpected and unwanted results. Third, you don't need to fill the component, use setBackground and let the super.paintComponent deal with it.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class DownWithNullLayouts {
public static void main(String[] args) {
new DownWithNullLayouts();
}
public DownWithNullLayouts() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private Font titlefont;
private BufferedImage bi;
public TestPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(30, 0, 0, 0);
add(new JButton("Play"), gbc);
try {
bi = ImageIO.read(...);
} catch (IOException ex) {
ex.printStackTrace();
}
titlefont = UIManager.getFont("Label.font");
setBackground(Color.BLACK);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int x = (getWidth() - bi.getWidth()) / 2;
int y = (getHeight()- bi.getHeight()) / 2;
g2d.drawImage(bi, x, y, this);
g2d.setFont(titlefont);
g2d.setColor(Color.WHITE);
g2d.drawString("dont steal my game idea plz", 25, 100);
g2d.dispose();
}
}
}
Take a closer look at Painting in AWT and Swing and Performing Custom Painting for more details
hi guys i have wird problem i have here my GUI class is working good at begining just by showing loggin screen. but i have second class called DataLayer that is responsible for reading from files and creating objets with infromaton.
the problem is that when i try to create new DataLayer() in GUI class the panel doesn show until i resize screen and even after that the keylistener doesn't work.
`package View;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JPanel;
import dto.DataLayer;
import dto.ProductDTO;
public class GUI extends JPanel {
private DataLayer dt;
private ComponentAbstract korzen;
private GUI self;
public GUI() {
this.setFocusable(true);
this.dt=new DataLayer();`
self=this;
this.stworz_PanelLogowania();
this.addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
korzen.tryPressKey(e);
repaint();
}
});
this.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
korzen.tryClick(e.getX(), e.getY());
repaint();
}
});
this.repaint();
}
#Override
protected void paintComponent(Graphics g ) {
super.paintComponent(g);
korzen.repaint();
System.out.println("omatko");
korzen.draw((Graphics2D)g);
}
private void zmien_panel(ComponentAbstract newkorzen){
korzen=newkorzen;
self.repaint();
}
private void stworz_PanelLogowania(){
LinearPanel lp=new LinearPanel(220, 10, 300, 300);
lp.setOrientarion(Orientation.VERTICAL);
LinearPanel labels_panel=new LinearPanel(220,0,50,80);
labels_panel.setOrientarion(Orientation.VERTICAL);
labels_panel.addComponent(new Label(0, 0, 350, 40, "Witamy w castorama APP"));
lp.setPadding(6);
LinearPanel textpanel1=new LinearPanel(0, 0, 350, 80);
textpanel1.setPadding(0);
textpanel1.addComponent(new Label(0,0,350,40,"Login:"));
textpanel1.addComponent(new TextBox(0, 0, 350, 40));
LinearPanel textpanel2=new LinearPanel(0, 0, 35, 80);
textpanel2.setPadding(0);
textpanel2.addComponent(new Label(0,0,350,40,"Hasło:"));
textpanel2.addComponent(new TextBox(0, 0, 350, 40));
lp.addComponent(labels_panel);
lp.addComponent(textpanel1);
lp.addComponent(textpanel2);
LinearPanel buttons_panel=new LinearPanel(00, 00, 350, 40);
buttons_panel.setOrientarion(Orientation.HORIZONTAL);
buttons_panel.addComponent(new Button(170,40,"Zaloguj"){
#Override
public void onClick() {
TextBox tlogin=(TextBox)korzen.getComponent(1).getComponent(1);
TextBox tpass=(TextBox)korzen.getComponent(2).getComponent(1);
if(dt.autoryzacja_uzytkownika(tlogin.getText(), tpass.getText())){
System.out.println("Puszczamy typa");
}
}
});
buttons_panel.addComponent(new Button(170,40,"Wyjdz"){
#Override
public void onClick() {
System.exit(0);
}
});
lp.addComponent(buttons_panel);
korzen=lp;
System.out.println("kuniec");
}
private void stworz_panelGlowny(){
LinearPanel glowny=new LinearPanel(220,0,50,80);
}
}
the problem is that when i try to create new DataLayer() in GUI class the panel doesn show until i resize screen
When you add (or remove) components from a visible GUI the basic code is:
panel.add(...);
panel.revalidate(); // to invoke the layout manager
panel.repaint(); // to paint the components.
even after that the keylistener doesn't work.
Probably because some other component has focus and KeyEvents area only dispatched to the component with focus. Try using the requestFocusInWindow() method on the panel.
panel.requestFocus
I'm sure this is a simple answer, but I can't figure it out.
I am trying to make a basic shape that I can control in a window. Obviously it will be more involved when the whole project is complete, but I am working on the early steps still. I am using WindowBuilder to make the layout, and have a JPanel and a JButton. The JPanel draws a rectangle, and has a method to move it. The JButton calles that moving command. And that's it. The problem is in the repaint. The shape keeps all old versions of itself, and the button makes weird copies of itself. All these go away when I resize the window, which I thought was the same as calling repaint. Again, I'm sure is something simple I am missing. Below are my 2 classes.
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class Drawing {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Drawing window = new Drawing();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public Drawing() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);
drawpanel panel = new drawpanel();
panel.setBounds(58, 68, 318, 182);
frame.getContentPane().add(panel);
JButton btnMove = new JButton("move");
btnMove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
panel.moves();
}
});
btnMove.setBounds(169, 34, 89, 23);
frame.getContentPane().add(btnMove);
}
}
^ This one, besides the buttonListener, was autocreated by WindowBuilder.
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class drawpanel extends JPanel {
int x = 50, y = 50;
int sizeX = 50, sizeY = 50;
public void paintComponent( Graphics g) {
super.paintComponents(g);
g.setColor(Color.BLACK);
g.drawRect(x, y, sizeX, sizeY);
}
public void moves() {
x +=5;
repaint();
}
}
^ This one has my drawing of the shape and the moving/repainting method. It was written mostly from other examples I found on this site.
Thanks to any help in advanced.
public void paintComponent(Graphics g) {
super.paintComponents(g); // wrong method! (Should not be PLURAL)
Should be:
public void paintComponent(Graphics g) {
super.paintComponent(g); // correct method!
I'm trying to learn how to draw a shape, and be able to a) draw it, "freeze" the process, draw it in the color of the background, and then re-draw it in the original color and b) draw a shape and change its color. All I have so far is (for blinking):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Carlight extends JPanel{
Thread th=new Thread();
public void paintComponent (Graphics g){
super.paintComponents(g);
g.setColor(Color.yellow);
g.fillOval(25, 25, 10, 10);
try{
th.sleep(10);
}catch(InterruptedException e){}
repaint();
g.setColor(Color.yellow);
g.fillOval(25, 25, 10, 10);
try{
th.sleep(10);
}catch(InterruptedException e){}
repaint();
g.setColor(Color.yellow);
g.fillOval(25, 25, 10, 10);
}
public Carlight(){
JFrame frame=new JFrame();
frame.setTitle("Carlights");
frame.add(this);
frame.setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100,150);
frame.setVisible(true);
}
public static void main(String[] args){
new Carlight();
}
}
How do I make this code work and how do I get a shape to change color?
import java.awt.Color;
import java.awt.Graphics;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class carlight extends JPanel
{
private Color lastColor = Color.YELLOW;
// For telling the panel to be repainted at regular intervals
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
#Override
public void paintComponent(Graphics g)
{
super.paintComponents(g);
if(lastColor.equals(Color.YELLOW))
{
lastColor = Color.GREEN;
}
else
{
lastColor = Color.YELLOW;
}
g.setColor(lastColor);
g.fillOval(25, 25, 10, 10);
}
public carlight()
{
JFrame frame = new JFrame();
frame.setTitle("Carlights");
frame.add(this);
frame.setBackground(Color.black);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(100, 150);
frame.setVisible(true);
service.scheduleAtFixedRate(new Runnable()
{
public void run()
{
repaint();
}
}, 0, 1, TimeUnit.SECONDS);
}
public static void main(String[] args)
{
new carlight();
}
}
Ok,
Don't put sleep calls during a paintComponent call. It means you are
forcing the UI to hang/stall. This is very bad.
I have created a ScheduledExecutorService for regularly calling the repaint method.
The paint method changes the color of the lastColor. Most of the time you would be looking at some sort of model to find out of the state of it to choose which color you should be using.
If the problem is you aren't meant to change the color, but instead it is an off/on situation, you should have a boolean representing state and only draw the circle if it is on.