How to make a JPanel reset? - java

I have a simple game of pong where when the user clicks a JButton which is displayed on the JPanel it should reset the game. How can I do this? I was thinking just remove the JPanel and add a new one (the JPanel contains all of the necessary code/class references for the game) I tried writing this however, and it didn't work, nothing happens. Here is my code:
JFrame Class:
public class Window extends JFrame implements ActionListener {
static int length = 1000;
static int height = 1000;
Display display = new Display();
Window() {
setTitle("Program Display");
setSize(length + 22, height + 40);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton restart = new JButton("Start New Game");
add(display);
display.add(restart);
restart.addActionListener(this);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
remove(display);
Display display2 = new Display();
JButton restart = new JButton("Start New Game");
add(display2);
display2.add(restart);
restart.addActionListener(this);
revalidate();
repaint();
}
}
JPanel Class:
public class Display extends JPanel implements ActionListener {
int up = 0;
int down = 500;
double ballx = 500;
double bally = 500;
char ballDirection;
Rectangle border;
static Rectangle borderEast;
static Rectangle borderNorth;
static Rectangle borderSouth;
static Rectangle borderWest;
static boolean gameOver;
Timer timer;
Paddle p;
Ball b;
Display() {
p = new Paddle();
b = new Ball();
up = p.up;
down = p.down;
ballx = b.ballx;
bally = b.bally;
ballDirection = b.ballDirection;
initTimer();
b.startBall();
addKeyListener(p);
setFocusable(true);
}
public void initTimer() {
timer = new Timer(10, this);
timer.start();
}
public void setUpBorders(Graphics2D g2d) {
border = new Rectangle(0, 0, Window.length, Window.height);
borderEast = new Rectangle(Window.length, 0, 2, Window.height);
borderWest = new Rectangle(0, 0, 2, Window.height);
borderSouth = new Rectangle(0, Window.height, Window.length, 2);
borderNorth = new Rectangle(0, 0, Window.length, 2);
g2d.setColor(Color.RED);
g2d.draw(border);
}
public void paintPaddle(Graphics2D g2d) {
g2d.setColor(new Color(0, 130, 130));
g2d.fill(p.paddle);
}
public void paintBall(Graphics2D g2d) {
g2d.setColor(new Color(0, 130, 130));
g2d.fillOval((int) ballx, (int) bally, 20, 20);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(Color.BLACK);
Graphics2D g2d = (Graphics2D) g;
setUpBorders(g2d);
paintPaddle(g2d);
paintBall(g2d);
if(gameOver == true) {
Font custom = new Font("Dialog", Font.BOLD, 60);
g2d.setColor(Color.RED);
g2d.setFont(custom);
g2d.drawString("Game Over. Your score was: " + Ball.score + "!", 50, 500);
}
}
public void checkBorderHit() {
b.checkBorderHit();
p.checkBorderHit();
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
up = p.up;
down = p.down;
ballx = b.ballx;
bally = b.bally;
ballDirection = b.ballDirection;
b.moveBall();
checkBorderHit();
repaint();
}
}

You didn't say what exactly doesn't work, but you forgot to call revalidate() and repaint() after adding display2. If your problem was that after pressing the button nothing happens, this will probably solve it.
Edit:
We still can't run you code, because the Ball and Paddle class are missing (my mistake for not mentioning that), but try to set important variables like gameOver false when first "mentioning them" (I don't know the proper term, just do static boolean gameOver = false; instead of static boolean gameOver;). Do this in all other classes also. Sorry for not saying which variables you exactly must change, but I'm not saying anything I'm not 100% sure about without being able to test it :P (maybe a more experienced person can help you more)

Related

Using Action Listeners for buttons

Code: Java Sphere class
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
public class Sphere extends JPanel {
private boolean flashinglights = false;
private int x = 168;
private int y = 75;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (flashinglights) { //This is the flash option. Here it should change between grey and orange
g2.setColor(Color.ORANGE);
Ellipse2D.Double ball = new Ellipse2D.Double(x, y, 50, 50);
g2.draw(ball);
g2.fill(ball);
} else {
g2.setColor(Color.gray); //This should stay grey as it does now.
Ellipse2D.Double ball = new Ellipse2D.Double(x, y, 50, 50);
g2.draw(ball);
g2.fill(ball);
}
}
public void chooseflashinglights(){ //Ignore these methods
flashinglights = false;
}
public void choosesteady(){
flashinglights = true;
}
public void flickerorange(int d) { y = y + d; }
public void flickergrey(int d) { y = y + d; }
public static void main(String[] args) {
JFrame scFrame = new AnimationViewer();
scFrame.setTitle("Circle");
scFrame.setSize(400, 400);
scFrame.setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
scFrame.setVisible(true);
}
}
Animation Viewer Class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AnimationViewer extends JFrame {
JButton jbtFlash = new JButton("Flash");
JButton jbtSteady = new JButton("Steady");
JPanel bPanel = new JPanel();
Sphere sphPanel = new Sphere();
Timer timer;
public AnimationViewer() {
this.add(bPanel, BorderLayout.SOUTH);
bPanel.add(jbtFlash);
bPanel.setLayout(new GridLayout(1,2));
bPanel.add(jbtSteady);
this.add(sphPanel, BorderLayout.CENTER);
jbtSteady.addActionListener(new SteadyLights());
jbtFlash.addActionListener(new FlashingLights());
timer = new Timer(100, new TimerListener());
timer.start();
}
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
sphPanel.flickerorange(0);
sphPanel.flickergrey(0);
repaint();
}
}
class FlashingLights implements ActionListener{
public void actionPerformed(ActionEvent e){
sphPanel.chooseflashinglights();
}
}
class SteadyLights implements ActionListener{
public void actionPerformed(ActionEvent e){
sphPanel.choosesteady();
}
}
}
So right now there is a sphere that appears on the screen. There are two buttons showed below. Flash and Steady. On the steady button it has to stay one colour (orange) which it does not.
Now on Flash it has to change from Orange to grey every 100 milli seconds.
I know it has to be something to do with Action listeners but how exactly do I implement this?
You have a lot of extra code. I would do it like this. Write flashing logic in paintComponent method. Then create just one timer. On tick call the paintComponent method for every 100ms. On flash button click start the timer, on steady button click stop the timer and call paintComponent once.
Sphere class:
public class Sphere extends JPanel {
private boolean flashinglights = false;
private int x = 168;
private int y = 75;
private Color[] colors = new Color[] {Color.ORANGE, Color.GRAY };
private int colorIndex = 0;
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
if (!flashinglights) {
g2.setColor(Color.ORANGE);
Ellipse2D.Double ball = new Ellipse2D.Double(x, y, 50, 50);
g2.draw(ball);
g2.fill(ball);
} else {
if(colorIndex > colors.length - 1)
colorIndex = 0;
g2.setColor(colors[colorIndex++]);
Ellipse2D.Double ball = new Ellipse2D.Double(x, y, 50, 50);
g2.draw(ball);
g2.fill(ball);
}
}
public void chooseflashinglights(){ //Ignore these methods
flashinglights = true;
}
public void choosesteady(){
flashinglights = false;
}
public static void main(String[] args) {
JFrame scFrame = new AnimationViewer();
scFrame.setTitle("Circle");
scFrame.setSize(400, 400);
scFrame.setDefaultCloseOperation((JFrame.EXIT_ON_CLOSE));
scFrame.setVisible(true);
}
}
AnimationViewer class:
public class AnimationViewer extends JFrame {
JButton jbtFlash = new JButton("Flash");
JButton jbtSteady = new JButton("Steady");
JPanel bPanel = new JPanel();
Sphere sphPanel = new Sphere();
Timer timer;
public AnimationViewer() {
this.add(bPanel, BorderLayout.SOUTH);
bPanel.add(jbtFlash);
bPanel.setLayout(new GridLayout(1,2));
bPanel.add(jbtSteady);
this.add(sphPanel, BorderLayout.CENTER);
timer = new Timer(100, new TimerListener());
jbtSteady.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sphPanel.choosesteady();
timer.stop();
sphPanel.repaint();
}
});
jbtFlash.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sphPanel.chooseflashinglights();
timer.start();
}
});
}
class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
sphPanel.repaint();
}
}
}
I would do things a bit differently.
I'd have a field in my drawing JPanel class that indicates what color should be shown.
For instance, if there are only two colors that are swapped, I'd use a boolean field, and would swap it's value in my timer, and then base the color draw on its value.
The paintComponent method would use that field, the boolean, to decide which Color to use for g.setColor(...).
If many colors are drawn, the field could be a combination of an array of Color together with an int index into the array. Then I'd increment the index as needed, and use the index in paintComponent to decide which color to draw with.
I'd change that field in my Timer's ActionListener -- just a single call to change it, not your strange call to flicker orange and flicker gray.
I'd start the Timer with one button
I'd stop it with the other button. That's all the button's action listener would do, simply start or stop the timer.

How to use a method from an already to Cotainer put JLabel?

I have to programm a Shikaku-Game and I have no the problem that I can not use one of the setLine-Methods from the ViewIcon-Class in the mouseReleased-Method of the class MyMouseAdapter.
Do you know a way how to use one of the methods?
Thanks and Cheers,
Me
Class MouseMain and Class MyMouseAdapter:
class MouseMain extends JFrame{
Container cont;
public MouseMain () {
super("Test");
cont = getContentPane();
p1 = new defaultPaterns(2);
p1.setLayout(new GridLayout(2, 2, 1, 1));
for (int i = 0; i < gameSize; i++) {
for (int j = 0; j < gameSize; j++) {
JLabel label = new JLabel(new ViewIcon());
label.setName (j + ";" + i);
label.addMouseListener(new MyMouseAdapter());
p1.add(label);
myLabels[j][i] = label;
}
}
cont.add(p1, BorderLayout.CENTER );
JPanel p2 = new JPanel();
cont.add(p2, BorderLayout.SOUTH);
setVisible(true);
}
public class MyMouseAdapter extends MouseAdapter {
public void mouseEntered(MouseEvent e) {
lastEntered = e.getComponent();
}
public void mousePressed(MouseEvent e) {
mousePressed = e.getComponent();
coordPressed = new Coordinate(mousePressed.getName());
System.out.println("mousePressed " + mousePressed.getName());
}
public void mouseReleased(MouseEvent e) {
mouseReleased = lastEntered;
coordReleased = new Coordinate(mouseReleased.getName());
System.out.println("mouseReleased " + mouseReleased.getName());
if (mouseReleased.getName().equals("0;0")) {
mouseReleased.setForeground(Color.RED);
mouseReleased.repaint();
}
}
}
Class ViewIcon:
class ViewIcon extends JLabel implements Icon {
Graphics2D g2;
int width;
int height;
public void paintIcon(Component c, Graphics g, int x, int y) {
g2 = (Graphics2D) g;
width = c.getWidth();
height = c.getHeight();
g2.setColor(Color.LIGHT_GRAY);
g2.fillRect(0, 0, width, height);
}
public void setLeftLine() {
g2.setStroke (new BasicStroke (10));
g2.setColor(Color.RED);
g2.drawLine(0, 0, 0, height);
}
}
class ViewIcon extends JLabel implements Icon {
Don't extend JLabel. All your code is doing is implementing the Icon interface.
I can not use one of the setLine-Methods from the ViewIcon-Class
Custom painting should only be done in the paintIcon(...) method. You should NEVER invoke a painting method directly.
If you want to change the appearance of your painting then you need to set properties of the Icon. For example to paint the top line you rename and change your setTopLine(...) method to look something like:
public void setTopLinePainted(boolean topLinePainted)
{
this.topLinePainted = topLinePainted;
}
Then in the paintIcon(...) method you have code like:
g2.fillRect(0, 0, width, height);
if (topLinePainted)
{
g2.setStroke (new BasicStroke (10));
g2.setColor(Color.RED);
g2.drawLine(0, 0, width, 0);
}
Then in your mouseReleased(...) code you do something like:
JLabel label = (JLabel)lastEntered;
ViewIcon icon = (ViewIcon)label.getIcon();
icon.setTopLinePainted( true );
label.repaint();

When i add code to paintComponent() my gui disappears

In my code after i added code to paintComponent() when i run it, all the JLabel, textfields, and buttons disappear the textfields and buttons reappear when i click on them while the program is running but i still can't see any of the JLabels.
I hope it is something silly i have commented out the code in the paintComponent() method that seems to cause this error.
public class snowBoarding extends JFrame {
private JButton getReset() {
if (Reset == null) {
Reset = new JButton();
Reset.setBounds(new Rectangle(162, 411, 131, 39));
Reset.setFont(new Font("Dialog", Font.BOLD, 18));
Reset.setText("Reset");
Reset.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e){
textField_1.setText("0");
textField_2.setText("0");
textField_3.setText("0");
textField_4.setText("0");
textField_5.setText("0");
textField_6.setText("0");
textField_7.setText("0");
textField_8.setText("0");
textField_9.setText("0");
textField_10.setText("0");
textField_11.setText("0");
textField.setText("0");
total_1.setText("0");
total_2.setText("0");
Overall.setText("0");
DrawPanel.clear(DrawPanel.getGraphics());
DrawPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
}
});
}
return Reset;
}
public JButton getButton_calc_draw() {
if (Button_calc_draw == null) {
Button_calc_draw = new JButton();
Button_calc_draw.setBounds(303, 411, 131, 39);
Button_calc_draw.setFont(new Font ("Dialog", Font.BOLD, 18));
Button_calc_draw.setText("Draw");
Button_calc_draw.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
// Get values from the text fields
run_1[0] = Integer.parseInt(textField.getText());
run_1[1] = Integer.parseInt(textField_1.getText());
run_1[2] = Integer.parseInt(textField_2.getText());
run_1[3] = Integer.parseInt(textField_3.getText());
run_1[4] = Integer.parseInt(textField_4.getText());
run_1[5] = Integer.parseInt(textField_5.getText());
for (int i = 0; i < run_1.length; i++) {
temp[i] = run_1[i];
}
Arrays.sort(temp);
for (int i = 1; i < (temp.length -1) ; i++){
avg1+=temp[i];
}
avg1 = avg1/4;
run_2[0] = Integer.parseInt(textField_6.getText());
run_2[1] = Integer.parseInt(textField_7.getText());
run_2[2] = Integer.parseInt(textField_8.getText());
run_2[3] = Integer.parseInt(textField_9.getText());
run_2[4] = Integer.parseInt(textField_10.getText());
run_2[5] = Integer.parseInt(textField_11.getText());
for (int i = 0; i < run_2.length; i++) {
temp[i] = run_2[i];
}
Arrays.sort(temp);
for (int i = 1; i < (temp.length -1) ; i++){
avg2+=temp[i];
}
avg2 = avg2/4;
if (avg1 > avg2){
OverallScore = avg1;
}
else {
OverallScore = avg2;
}
total_1.setText(Integer.toString(avg1));
total_2.setText(Integer.toString(avg2));
Overall.setText(Integer.toString(OverallScore));
DrawPanel.repaint();
}
// Transfer the image from the BufferedImage to the JPanel to make it visible.
;
});
}
return Button_calc_draw;
}
}
});
}
return Reset;
}
private myJPanel getDrawPanel() {
if (DrawPanel == null) {
DrawPanel = new myJPanel();
DrawPanel.setLayout(new GridBagLayout());
DrawPanel.setBounds(new Rectangle(258, 39, 326, 361));
DrawPanel.setBackground(Color.white);
DrawPanel.setEnabled(true);
DrawPanel.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
//Instantiate the BufferedImage object and give it the same width
// and height as that of the drawing area JPanel
img = new BufferedImage(DrawPanel.getWidth(),
DrawPanel.getHeight(),
BufferedImage.TYPE_INT_RGB);
//Get its graphics context. A graphics context of a particular object allows us to draw on it.
g2dImg = (Graphics2D)img.getGraphics();
//Draw a filled white coloured rectangle on the entire area to clear it.
g2dImg.setPaint(Color.WHITE);
g2dImg.fill(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
}
return DrawPanel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
snowBoarding thisClass = new snowBoarding();
thisClass.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
thisClass.setVisible(true);
}
});
}
public snowBoarding() {
super();
setResizable(false);
getContentPane().setLayout(null);
initialize();
}
private void initialize() {
this.setSize(600, 500);
this.setContentPane(getJContentPane());
this.setTitle("Snowboarding Score Calculator");
this.setResizable(false);
this.setVisible(true);
}
}
class myJPanel extends JPanel {
BufferedImage img;
Graphics2D g2dImg;
private static final long serialVersionUID = 1L;
private Rectangle2D.Double rectangle;
public void paintComponent(Graphics g) {
//Must be called to draw the JPanel control.
// As a side effect, it also clears it.
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
rectangle = new Rectangle2D.Double(0, 260-score[0] * 2, 25, score[0] * 2);
g2D.setPaint(Color.blue);
g2D.fill(rectangle);
g2D.draw(rectangle);
}
protected void clear(Graphics g) {
super.paintComponent(g);
// Also clear the BufferedImage object by drawing a white coloured filled rectangle all over.
g2dImg.setPaint(Color.WHITE);
g2dImg.fill(new Rectangle2D.Double(0, 0, img.getWidth(), img.getHeight()));
}
}
edit: removing unnecessary code
i need the repaint to draw rectangles using the run_1 and the run_2 array as the x or y values after i click draw and the reset to return the painted image back to a white slate.
draw button --> draws the graph
reset button --> removes the graph so that a new graph can be created.
You shall not use g2dImg in paintComponent(), but g instead (the parameter received by method paintComponent()). More precisely, ((Grpahics2D)g) instead of g2dImg.
g2dImg doesn't seem to be initialized in your code posted here, maybe you have done it somewhere...
More generally, you shall always use the Graphics instance you received in paint methods (casting it to Graphics2D if needed). You shall not try to reuse/share/store instances of Graphics.
The same applies for the clear() method.
Here is an example of how to rewrite this paintComponent() method:
private boolean shallPaint = false;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (shallPaint) {
Graphics2D g2D = (Graphics2D) g;
rectangle = new Rectangle2D.Double(0, 260-score1 * 2, 25, score1 * 2);
g2D.setPaint(Color.blue);
g2D.fill(rectangle);
g2D.draw(rectangle);
}
}
public void setShallPaint(boolean pShallPaint) {
shallPaint = pShallPaint;
}
Then simply call myJPanel.repaint() to repaint it.
You shall replace, in your reset button:
DrawPanel.clear(DrawPanel.getGraphics());
with:
DrawPanel.setShallPaint(false);
DrawPanel.repaint();
And in Button_calc_draw:
DrawPanel.setShallPaint(true);
DrawPanel.repaint();

Click on icon in a JTextField and clear its content

I am trying to create a JTextField with an image and a hint. The function of the textfield is a search field to search some books. Now, I like to go a little bit further. I would like to give the image a function. For example, if I click on the image the text in the textfield should be cleared.
To achieve this implementation I created a new class and extended it with JTextField.
This is the code:
public class JSearchTextField extends JTextField implements FocusListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private String textWhenNotFocused;
private Icon icon;
private Insets dummyInsets;
private JTextField dummy;
public JSearchTextField() {
super();
Border border = UIManager.getBorder("TextField.border");
dummy = new JTextField("Suchen...");
this.dummyInsets = border.getBorderInsets(dummy);
icon = new ImageIcon(JSearchTextField.class.getResource("/images/clearsearch.png"));
this.addFocusListener(this);
}
public JSearchTextField(String textWhenNotFocused) {
this();
this.textWhenNotFocused = textWhenNotFocused;
}
public void setIcon(ImageIcon newIcon){
this.icon = newIcon;
}
public String getTextWhenNotFocused() {
return this.textWhenNotFocused;
}
public void setTextWhenNotFocused(String newText) {
this.textWhenNotFocused = newText;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
int textX = 2;
if(!this.hasFocus() && this.getText().equals("")) {
int height = this.getHeight();
Font prev = this.getFont();
Font italic = prev.deriveFont(Font.ITALIC);
Color prevColor = g.getColor();
g.setFont(italic);
g.setColor(UIManager.getColor("textInactiveText"));
int h = g.getFontMetrics().getHeight();
int textBottom = (height - h) / 2 + h - 4;
int x = this.getInsets().left;
Graphics2D g2d = (Graphics2D) g;
RenderingHints hints = g2d.getRenderingHints();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.drawString(textWhenNotFocused, x, textBottom);
g2d.setRenderingHints(hints);
g.setFont(prev);
g.setColor(prevColor);
} else {
int iconWidth = icon.getIconWidth();
int iconHeight = icon.getIconHeight();
int x = dummy.getWidth() + dummyInsets.right;
textX = x - 420;
int y = (this.getHeight() - iconHeight)/2;
icon.paintIcon(this, g, x, y);
}
setMargin(new Insets(2, textX, 2, 2));
}
#Override
public void focusGained(FocusEvent arg0) {
this.repaint();
}
#Override
public void focusLost(FocusEvent arg0) {
this.repaint();
}
}
And this is where I create the fields;
txtSearchBooks = new JSearchTextField("Buch suchen...");
Now back to my question. Do you have any idea how I can give the image a function where the text will be automatically cleared? I tried to implement a MouseListener and set the text of "txtSearchBooks" to null but it hasn't worked.
I hope I didn't go off in the wrong direction.
Sorry for the long post but I would really appreciate to get some advice.
A JTextField is a JComponent, meaning it is also a container for other components. You can use the add(Component c) method to add other components to it. BUT A JTextField won't show its added components unless you provide a LayoutManager to it. Then it behaves just like a normal JPanel.
I made a small example how you can manage what you need. The label is showed to the right, and clicking it will clear the field. You can use a button as well, instead of label.
Please note you don't need to create the Image object from scratch as I do, you can load it from a file. I create it this way so that the example doesn't rely on other files.
public class TextFieldWithLabel {
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JTextField textField = new JTextField("Search...");
textField.setLayout(new BorderLayout());
//creating dummy image...
Image image = new BufferedImage(25, 25, BufferedImage.TYPE_INT_RGB);
Graphics graphics = image.getGraphics();
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, 25, 25);
graphics.setColor(Color.RED);
graphics.fillRect(2, 11, 21, 3);
graphics.fillRect(11, 2, 3, 21);
JLabel label = new JLabel(new ImageIcon(image));
textField.add(label, BorderLayout.EAST);
label.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
textField.setText("");
}
});
frame.add(textField);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

How to "paint" on JLabels on a JPanel?

I have a set of JLabels, each containing a letter (via seText()), opaque and background set to white, on a JPanel with a GridLayout so the labels are forming a table.
I am doing a simple animation of highlighting certain rows and columns then there intersection. I can use the setBackground() of labels for this purpose, but thought I'd have more "choices" if a was able to use a Graphics object (maybe drawing a circle around intersection, then clearing it).
I tried to extend JLabel, or drawing on the JPanel directly(using getGraphics() in a method) but it didn't work, I think the drawing is behind the labels in this case. I can't figure out where should the "painting" code be placed in either case, nothing appeared on the screen.
in short, a method like the following, can be used to draw on top of labels?
should it be a JLabel or a JPanel method?
public void drawsomething() {
Graphics2D g2d = (Graphics2D) getGraphics();
g2d.fillRect(100, 100, 100, 100);
}
What if you override paintChildren() ?
protected void paintChildren(Graphics g) {
super.paintChildren(g);
//paint your lines here
}
You might want to try a JLayeredPane to paint your specific drawings on top of the existing JComponents
see example here http://docs.oracle.com/javase/tutorial/uiswing/components/layeredpane.html
I really don't know much about drawing stuff yet, but just created one small sample code for you to look at, hopefully you can get some information out of it. In order to paint on the JLabel you can use it's paintComponent(Graphics g) method.
A Sample Code :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DrawingOnJLabel extends JFrame
{
private CustomLabel label;
private int flag = 1;
private JPanel contentPane;
public DrawingOnJLabel()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
label = new CustomLabel(200, 200);
label.setLabelText("A");
label.setValues(50, 50, 100, 100, 240, 60);
final JButton button = new JButton("CLEAR");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
if (flag == 1)
{
label.setFlag(flag);
flag = 0;
button.setText("REPAINT");
contentPane.revalidate();
contentPane.repaint();
}
else if (flag == 0)
{
label.setFlag(flag);
flag = 1;
button.setText("CLEAR");
contentPane.revalidate();
contentPane.repaint();
}
}
});
}
});
contentPane.add(label);
add(contentPane, BorderLayout.CENTER);
add(button, BorderLayout.PAGE_END);
setSize(300, 300);
setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new DrawingOnJLabel();
}
});
}
}
class CustomLabel extends JLabel
{
private int sizeX;
private int sizeY;
private int x, y, width, height, startAngle, arcAngle;
private int flag = 0;
private String text;
public CustomLabel(int sX, int sY)
{
sizeX = sX;
sizeY = sY;
}
// Simply call this or any set method to paint on JLabel.
public void setValues(int x, int y, int width, int height, int startAngle, int arcAngle)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.startAngle = startAngle;
this.arcAngle = arcAngle;
repaint();
}
public void setFlag(int value)
{
flag = value;
repaint();
}
public Dimension getPreferredSize()
{
return (new Dimension(sizeX, sizeY));
}
public void setLabelText(String text)
{
super.setText(text);
this.text = text;
flag = 0;
repaint();
}
public void paintComponent(Graphics g)
{
if (flag == 0)
{
g.setColor(Color.RED);
g.drawString(text, 20, 20);
g.setColor(Color.BLUE);
g.drawOval(x, y, width, height);
g.fillOval(x + 20, y + 20, 15, 15);
g.fillOval(x + 65, y + 20, 15, 15);
g.fillRect(x + 40, y + 40, 5, 20);
g.drawArc(x + 20, y + 30, 55, 55, startAngle, arcAngle);
}
else if (flag == 1)
{
g.clearRect(x, y, width, height);
}
}
}
Use paintComponent(Graphics g) instead of paint(Graphics g). That will paint over the GUI

Categories