why is my variable increasing exponentially? - java

I have a piece of code that moves a rectangle whenever i press a button. it it set up so that the x or y coordinate decreases or increases by 1 pixel each time the key is pressed. however, i am noticing that if i press the same key more than once in a row, the 1 pixel compounds itself somehow , stacks may be a better word, and increases exponentially. is there anything in the code that you can see why it would do this?
public class drawingComponent extends JComponent implements KeyListener
{
Rectangle hello = new Rectangle(300, 100, 50, 50);
public void paintComponent (Graphics g)
{
Graphics2D g2 = (Graphics2D)g;
g2.setColor(new Color(255, 25, 0));
g2.setFont(new Font("monospace", Font.BOLD + Font.ITALIC, 30));
g2.drawString("nothing yet", 300, 320);
g2.fill(hello);
setFocusable(true);
requestFocus();
addKeyListener(this);
}
#Override
public void keyPressed (KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_W)
{
hello.y = hello.y - 1;
hello.setLocation(hello.x, hello.y);
repaint();
System.out.println(hello.y);
}
if (e.getKeyCode() == KeyEvent.VK_S)
{
hello.y = hello.y + 1;
hello.setLocation(hello.x, hello.y);
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_A)
{
hello.x = hello.x - 1;
hello.setLocation(hello.x, hello.y);
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_D)
{
hello.x = hello.x + 1;
hello.setLocation(hello.x, hello.y);
repaint();
}
}
#Override
public void keyReleased (KeyEvent e)
{
}
#Override
public void keyTyped (KeyEvent e)
{
// TODO Auto-generated method stub
}
}

You're adding your KeyListener on each repaint of your component:
public void paintComponent(Graphics g){
//..
addKeyListener(this); // adds another KeyListener
}
And every call of repaint(); adds another KeyListener that will do his job, if keyPressed is called. That means, you have one listener first, then two, then four, then sixteen and so on.
Don't do that. Add your listener once in the constructor or so.
The constructor can look like this:
public drawingComponent() {
// init other stuff
addKeyListener(this);
}

You are trying to overcome an inherent issue with an API by using hacks and workarounds which may or may not work on other systems or platforms.
Do not change the state of a component from within a paint method, painting should paint the current state, nothing else. By requesting focus within the paint method, you could be triggering another repaint request to be made, resulting in a vicious cycle which will consume your CPU cycles.
The core problem is (as highlighted by Tom), you're adding ANOTHER KeyListener everytime paint is called. Painting will occur, a lot, and usually without your knowledge or request.
Instead of fighting this problem, you should use the API which was designed to fix it, the key bindings API. This API will allow you to define the level of focus required to trigger the key events, the following example mimics the default behaviour of the KeyListener (as I don't know your other requirements), but has an option to allow the component to become focusable.
Some tips...
Always caller super.paintComponent before doing custom painting, this is easy to forget and can result in some seriously weird graphics glitches.
There's no need for paintComponent to be public, you never want anyone to ever call it.
You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others
As a simple example...
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.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
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 DrawingComponent());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class DrawingComponent extends JComponent {
Rectangle hello = new Rectangle(300, 100, 50, 50);
public DrawingComponent() {
setFocusable(true);
InputMap im = getInputMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "Move.up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "Move.down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "Move.left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "Move.right");
ActionMap am = getActionMap();
am.put("Move.up", new DeltaAction(0, -1));
am.put("Move.down", new DeltaAction(0, 1));
am.put("Move.left", new DeltaAction(-1, 0));
am.put("Move.right", new DeltaAction(1, 0));
addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
requestFocusInWindow();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(new Color(255, 25, 0));
g2.setFont(new Font("monospace", Font.BOLD + Font.ITALIC, 30));
g2.drawString("nothing yet", 300, 320);
g2.fill(hello);
}
public class DeltaAction extends AbstractAction {
private int xDelta;
private int yDelta;
public DeltaAction(int xDelta, int yDelta) {
this.xDelta = xDelta;
this.yDelta = yDelta;
}
#Override
public void actionPerformed(ActionEvent e) {
hello.x += xDelta;
hello.y += yDelta;
repaint();
}
}
}
}
"But why should I use the key bindings API" I hear you asking? Apart from providing you more flexibility and configurability (including setting the level of focus required to trigger the events, you could also change the keys which trigger the events more easily and or have a multiple set of keys - think the arrow keys as well), it can be used with other parts of the Swing API, including buttons.
A single Action can be applied to JMenuItems, JButtons and key bindings, no extra coding required...
See How to Use Key Bindings for more details

Related

Can't get paint function to update in simple pong game

I'm a relatively inexperienced Java programmer when it comes to graphics. I'm trying to make a simple pong game to learn more about how graphics are done in Java.
In the program, the left paddle (the only paddle thus far implemented) should move up 5 pixels when 'W' is pressed on the keyboard. According to the console, it is recognizing that the key is being pressed, and it is updating a variable that represents the y-coordinate for the left paddle accordingly. However, the paddle's location isn't actually being updated on the screen.
Help?
Game class:
import javax.swing.JFrame;
public class Game {
static int WIDTH = 500;
static int HEIGHT = 500;
public static void main(String[] args) {
window();
}
public static void window() {
JFrame frame = new JFrame();
frame.setSize(WIDTH, HEIGHT);
frame.setLocationRelativeTo(null);
frame.setAlwaysOnTop(true);
frame.setVisible(true);
frame.setResizable(false);
frame.add(new Panel());
frame.addKeyListener(new Panel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Panel class:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class Panel extends JPanel implements KeyListener {
int leftPaddlePos = 100;
public void paint(Graphics g) {
g.clearRect(0, 0, Game.WIDTH, Game.HEIGHT);
g.setColor(Color.black);
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
g.setColor(Color.white);
g.fillRect(75, leftPaddlePos, 15, 100);
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_W) {
System.out.println("W pressed");
leftPaddlePos = leftPaddlePos + 5;
System.out.println(leftPaddlePos);
}
}
#Override
public void keyReleased(KeyEvent e) {
}
}
public class Panel extends JPanel implements KeyListener {
Don't call your class Panel. There is an AWT class with that name so it is confusing. Your class name should be more descriptive. Maybe something like PongPanel.
public void paint(Graphics g) {
Don't override paint(...);
public void paintComponent(Graphics g) {
Custom painting in Swing is done by overriding paintComponent(...).
g.clearRect(0, 0, Game.WIDTH, Game.HEIGHT);
g.setColor(Color.black);
g.fillRect(0, 0, Game.WIDTH, Game.HEIGHT);
Don't use above code to paint the background of the panel. Instead, you just use:
super.paintComponent(g);
So in the constructor of your class you can invoke setBackground(...) to set the desired background color.
However, the paddle's location isn't actually being updated on the screen.
leftPaddlePos = leftPaddlePos + 5;
You update the position, but you haven't told the component that a property of the class has changed, so it doesn't know it needs to paint itself again.
You should not change the property of the class in the listener. Instead you should have a method like adjustLeftPaddlePosition(int value)
The method would be:
public void adjustLeftPaddlePostion(int value)
{
leftPaddlePos = leftPaddlePos + value;
repaint();
}
Then in the KeyListener you would use:
adjustLeftPaddlePosition(5);
Also, you should not be using a KeyListener. Instead you should be using "Key Bindings" Check out Motion Using the Keyboard for more information and working examples.

How to prevent the JPanel from being updated?

I'm creating a sort of paint application. The user can move a circle in a JPanel by pressing/dragging the mouse.
I have a JCheckBoxMenuItem in one of my JMenus:
JCheckBoxMenuItem checkitem = new JCheckBoxMenuItem("Draw mode",false);
When it is not activated, the circle can only be moved (by dragging/pressing) and the previous circle will be erased.
When it is activated, the circle can only be moved, but the previous circle will not be erased when dragging/pressing the mouse ( This works the same way as a paint program )
Shortened version of my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class GUI extends JFrame implements MouseListener, MouseMotionListener, ActionListener, ItemListener
{
JPanel mainPan, colorPan;
Color color = Color.BLACK;
JCheckBoxMenuItem checkitem;
boolean clear = true;
public GUI(String header)
{
maker();
mainPan.addMouseListener(this);
mainPan.addMouseMotionListener(this);
add(mainPan , BorderLayout.CENTER);
add(colorPan, BorderLayout.PAGE_END);
}
public void maker()
{
colorPan = new JPanel();
colorPan.setLayout(new GridLayout(1, 0));
mainPan = new JPanel(){
#Override
public void paintComponent(Graphics g)
{
//g.setColor(Color.WHITE);
//g.fillRect(0,0,getWidth(),getHeight());
if(clear)
super.paintComponent(g); //Do the same thing as above(Clear JPanel)
g.setColor(color);
g.fillOval(x,y,50,50); //x and y are integer variables that I use in my full program
}
};
checkitem = new JCheckBoxMenuItem("Draw mode",false);
//After adding this to a JMenu,
checkitem.addItemListener(this);
}
public void itemStateChanged(ItemEvent e)
{
if(e.getStateChange() == ItemEvent.SELECTED)
{
clear = false;
}
else
{
clear = true;
}
}
}
The below screenshot shows the output of my full program:
colorPan is the JPanel full of JButtons of different colors. The top of it is mainPan.
Right now, the "Draw mode" doesn't work as expected. I had always thought that super.paintComponent(g); was the one that clears/resets the screen when repaint() is called. But I removed that and was quite surprised to see the program behave the same way.
Basically, my problem is here:
if(clear)
super.paintComponent(g);
I need to prevent everything from being cleared when repaint() is called. How do I achieve what I want?
It is not in this code where changes should be made. And it is not paint method which should be changed. Paint paints whenever is required either by your or by system. When window is resized or moved or partially covered - it uses paint to paint picture again.
What you should really do is to stop updating coordinates for your painted oval. It could be done in mouse listener or in coordinates setter or, better, in control part which manages these coordinates. Your checkbox should control ability to change your model. It should not control painting.
There is commonly used pattern Model-View-Controller - look at it. Maybe it could look like overkill for such small application but even Swing itself is built on this pattern so you already follow it. Issues rise when you try to break it. So - don't.
You can't "prevent the JPanel from being updated;" paintComponent() will be called asynchronously, as required by the system. Instead, condition attributes of your view class in a way that allows your implementation of paintComponent() to render everything whenever it is called.
In the example below, the foreground color is changed with each mouse click and paintComponent() uses the revised setting. In the more elaborate example cited here, ClearAction clears the List<Node> and List<Edge> that define the graph's model. Absent a call to super.paintComponent(g), otherwise required for an opaque component, a call to fillRect() in paintComponent() cleans up any leftover selection artifacts.
public void actionPerformed(ActionEvent e) {
nodes.clear();
edges.clear();
repaint();
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
/** #see https://stackoverflow.com/a/5312702/230513 */
public class MouseDragTest extends JPanel {
private static final String TITLE = "Drag me!";
private static final Random r = new Random();
private static final int W = 640;
private static final int H = 480;
private Point textPt = new Point(W / 2, H / 2);
private Point mousePt;
private Color color = Color.black;
public MouseDragTest() {
this.setFont(new Font("Serif", Font.ITALIC + Font.BOLD, 32));
this.addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
mousePt = e.getPoint();
setColor(Color.getHSBColor(r.nextFloat(), 1, 1));
repaint();
}
});
this.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - mousePt.x;
int dy = e.getY() - mousePt.y;
textPt.setLocation(textPt.x + dx, textPt.y + dy);
mousePt = e.getPoint();
repaint();
}
});
}
public void setColor(Color color) {
this.color = color;
}
#Override
public Dimension getPreferredSize() {
return new Dimension(W, H);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
int w2 = g.getFontMetrics().stringWidth(TITLE) / 2;
g.drawString(TITLE, textPt.x - w2, textPt.y);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame(TITLE);
f.add(new MouseDragTest());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}

Make mouse events on JComponent after transform work?

Hello and sorry for my imperfect English.
I have a class MyNode (draws a rectangle) that extends JComponent. I have mouse listener for mouseEntered and mouseExited to change its color.
The big problem is that i need to work with transforms (the main app, not this SSCE, it is a graph (nodes&edges) drawer.)
I read about this problem already but I want to ask you how can i make it work. If I apply a scale(2,2) on my panel i have two main problems:
The mouse position doesn't correspond anymore to the drew MyNode. I know i can apply inverseTransform and this works just well, but I must search in all node collection of the panel and check the contains method with the inversed point (inefficient imo). (hope you get what i am saying here). How i can make the mouseEntered, mouseExited etc. work by itself in the new scaled system.
If I scale the panel, the MyNode paintComponent() doesn't apply its owner (Panel) transforms. The node is drew with its initial size.
I am very curious if this can be resolved, and I wait any other question to help you understand what I am looking for. It seems even hard to explain the problem, can't imagine the solution :)
This is a demo of my problem (you can run it):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class SSCE extends JPanel {
public SSCE() {
setLayout(null);
setBackground(Color.yellow);
setSize(new Dimension(500, 300));
setPreferredSize(new Dimension(500, 200));
add(new MyNode(0, 0));
setVisible(true);
}
#Override
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.scale(2, 2);
super.paintComponent(g2d);
paintComponents(g2d);
}
}
class MyNode extends JComponent {
private Color activeColor = Color.red;
public MyNode(int x, int y) {
this.setLocation(x, y);
this.setSize(50, 50);
this.addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
colorOnMouseHover();
}
#Override
public void mouseExited(MouseEvent e) {
colorOnMouseLeave();
}
});
}
private void colorOnMouseHover() {
this.activeColor = Color.blue;
repaint();
}
private void colorOnMouseLeave() {
this.activeColor = Color.red;
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(activeColor);
g.fillRect(0, 0, 50, 50);
}
}
class Run {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setSize(500, 200);
frame.add(new SSCE());
frame.setVisible(true);
}
}

Paint method not working on full screen - Java

I am trying to create a full screen with a paint method. I want "This is the day" in pink with a blue background to show up. The problem is, is that when I run my program, It shows up with what I painted on my screen with my toolbar and applications instead of showing up a blue background with "This is the day" in the middle in pink. Some code is below.
public static void main(String args[])
{
DisplayMode dm1 =
new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
RunScreen runProgram = new RunScreen();
runProgram.run(dm1);
}
public void run(DisplayMode dm)
{
getContentPane().setBackground(Color.BLUE);
setForeground(Color.PINK);
setFont(new Font("Arial", Font.PLAIN, 24));
FullScreen s = new FullScreen();
try
{
s.setFullScreen(dm, this);
try
{
Thread.sleep(5000);
}
catch (Exception e)
{
}
}
finally
{
s.restoreScreen();
}
}
#Override
public void paint(Graphics g)
{
g.drawString("This is the day", 200, 200);
}
Thread.sleep(5000);
Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling Thread.sleep(n) implement a Swing Timer for repeating tasks or a SwingWorker for long running tasks. See Concurrency in Swing for more details.
This seems to work just fine...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
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.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestFullScreen {
public static void main(String[] args) {
new TestFullScreen();
}
public TestFullScreen() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setUndecorated(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
device.setFullScreenWindow(frame);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
String text = "Hello";
FontMetrics fm = g.getFontMetrics();
int x = (getWidth() - fm.stringWidth(text)) / 2;
int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g.drawString(text, x, y);
}
}
}
Beware, the "window" that you request to be made into a full screen window may not be the actually window used by the system.
You should avoid overriding paint and use paintComponent instead. You should also avoid overriding paint of top level containers (like JFrame).
Check out Performing Custom Painting and Painting in AWT and Swing for more details...
To hide toolbar and etc. Use setUndecorated
runProgram.setUndecorated(true);
runProgram.run(dm1);
To show up a blue background with "This is the day" in the middle in pink, set the color in paint (or paintComponent)
g.setColor(Color.BLUE);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.PINK);
g.drawString("This is the day", 200, 200);
Second, you shouldn't involve with GUI out of the EDT (Event Dispatch Thread). You should do those thing like this:
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
setFont(new Font("Arial", Font.PLAIN, 24));
}
});
Third, you shouldn't overrides paint of top level containers. (I don't mean the #Override notation). You should do as Andrew Thompson mentioned:
Repaint method is not entered when the frame is full screen. So this way is useful for repainting for swing JFrame.
public void actionPerformed(ActionEvent arg0) {
if (getExtendedState() == 6) {//6 full-screen, 0 normal, -1 minimized
repaint();
} else {
repaint();
}
}

Java Swing Graphics - Why does the first-time rendering not work as expected?

I have a strange problem that probably stems from lack of understanding of how Swing works. When, for the first time since program start, I attempt to render the panel inside a window frame anew as soon as I press one of the alphabetic keys, the character in question is painted very briefly on the panel, before the panel turns white again.
On subsequent key strokes the program then behaves as expected: the panel re-renders with the character associated with the pressed key.
Since the character IS painted on the first key stroke, the fact, that it disappears immediately afterwards must mean the panel is rendered AGAIN, thus overriding the previous contents.
Here's the code:
// Main.java
public class Main {
public static void main(String[] args) {
new GlyphFrame(new GlyphPanel());
}
}
// ---------------------------------------------------
// GlyphFrame.java
import javax.swing.JFrame;
public class GlyphFrame extends JFrame {
private static final long serialVersionUID = -7754180294993638709L;
private final int WIDTH = 500;
private final int LENGTH = 400;
public GlyphFrame(GlyphPanel panel){
this.add(panel);
this.setSize(WIDTH, LENGTH);
this.setVisible(true);
}
}
// ---------------------------------------------------
// GlyphPanel.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class GlyphPanel extends JPanel {
private static final long serialVersionUID = -6330730323655696958L;
public GlyphPanel(){
this.setBackground(Color.WHITE);
this.setFocusable(true);
this.requestFocusInWindow();
this.setFont(new Font("Dialog", Font.PLAIN, 12));
this.addKeyListener(new GlyphKeyListener(this));
}
private void paintPanel(Graphics g, char c){
super.paintComponent(g);
g.drawString("" + c, 10, 10);
g.setColor(this.getBackground());
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.BLACK);
g.drawString("" + c, 10, 10);
}
private class GlyphKeyListener implements KeyListener{
private GlyphPanel panel;
private int i = 0;
public GlyphKeyListener(GlyphPanel panel){
this.panel = panel;
}
#Override
public void keyTyped(KeyEvent e) {}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() >= KeyEvent.VK_A && e.getKeyCode() <= KeyEvent.VK_Z){
System.out.println("Call number " + (++i));
panel.paintPanel(panel.getGraphics(), e.getKeyChar());
}
}
#Override
public void keyReleased(KeyEvent e) {}
}
}
EDIT: Thanks for answering. Now I understand how painting is supposed to work in Swing.
If I need the panel to redraw itself I simply call repaint() which makes the system call paintComponent(Graphics g). Thus, whatever I want to paint I put it in an overridden paintComponent() method. paintComponent() is never called directly. Only use repaint().
You shouldn't call paintPanel directly. swing manages painting itself. Instead of that you should do the following:
Override JComponent.paintComponent(Graphics g); It should use a field to retrieve the pressed character
On key press you should set the field and call JComponent.repaint();
That should work fine.

Categories