Calling #Override on paintComponent() when state changes - java

How do I override a paintComponent method with response to a state change?
Error message: void is an invalid type for the variable paintComponent
public class MyContainer extends Container {
public void paintComponent(Graphics m){
m.drawArc(100,100,100,100,100,100);
m.setColor(Color.green);
m.fillArc(100,100,100,100,100,100);
}
public static void main(String[] args){
Container y = new Container();
JFrame x = new JFrame();
JPanel gg = new JPanel();
x.add(y);
x.setTitle(" Shape Changer");
x.setBounds(100,50,500,300);
x.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
x.getContentPane().add(new ContentPanel());
x.getContentPane().add(new ContnetPanel());
x.setContentPane(new ContnetPanel());
x.setVisible(true);
}
static class ContentPanel extends JPanel{
private Graphics g;
private JPanel ss;
public void paint(Graphics g){
g.drawArc(100,100,100,100,100,100);
g.fillRect(100, 100,100,100);
}
public ContentPanel(){
}
}
static class ContnetPanel extends JPanel implements ActionListener, ChangeListener{
JComboBox comboerbox;
class appres {
public void paint(Graphics h){
h.drawRect(100,100,100,100);
h.setColor(Color.red);
h.fillRect(100,100,100,100);
}
}
public ContnetPanel(){
comboerbox = new JComboBox();
comboerbox.addItem("Red Square");
comboerbox.addItem("Blue Square");
comboerbox.addItem("Green Square");
comboerbox.setSelectedIndex(1);
add(comboerbox);
setLayout(new GridLayout(2,1));
}
#Override
protected void paintComponent(Graphics h){
super.paintComponent(h);
h.drawArc(100,100,100,100,100,100);
h.setColor(Color.blue);
h.fillArc(100,100,100,100,100,100);
repaint();
}
int yy = 0;
public void actionPerformed(ActionEvent evt){
switch(comboerbox.getSelectedIndex()){
case 0:yy=0;
case 1: yy=1;
case 2: yy=2;
}
}
//evt.getSource()==comboerbox
public void stateChanged(ChangeEvent evt){
if(evt.getSource()==comboerbox){
#Override
protected void paintComponent(Graphics h){
super.paintComponent(h);
h.drawArc(100,100,100,100,100,100);
h.setColor(Color.blue);
h.fillArc(100,100,100,100,100,100);
repaint();
}
}
else
{
System.out.println("DONE");
}
}
}
}
Of course, the paintComponent method isn't a variable. How would I override paintComponent here? Or is a better way to change the shape with response to state change? That would be great too!
Thanks in advance, love you guys!

In your last question: How do I make the superclass go beyond just the content pane? you were given a link to the Swing tutorial for some Swing basics.
Well there is also a section on Custom Painting for you to read. You can then download the example and play with it to understand how painting works.
Basically the Container class doesn't have a paintComponent() method so you should not be trying to do custom painting in that class.
If you want to change a painting property, then you need to add a method to your class to change the state of the property and then invoke repaint() on itself.
So from the tutorial example in Step 3 you can see how the moveSquare(...) method changes the state of the class and then invokes repaint().
Note you should never invoke repaint() in the paintComponent() method since this will cause the painting to be continually rescheduled.

Related

Why using an if statement inside a paintComponent(Graphics g) method invalidates all code inside the method?

I'm trying to create a JFrame object which contains a JPanel object. Inside the JPanel object there are 3 JButtons that when clicked, are intended to change the background color of the JPanel.
I also want to draw an image which size equals the one of the JPanel object to give the impression of a background image but as you may imagine I want it to be drown only the first time, when the user hasn't clicked any buttons yet. Once a button is clicked I intend to call the repaint() method inherited from the Component class which in my understanding should make a call to the paintComponent(Graphics g).
Given the fact I want the image to be drawn only when the user hasn't clicked any buttons, inside the paintComponent(Graphics g) I'm trying to use an if statement so when the paintComponent(Graphics g) method is called the second time by the repaint() method, it will execute inside an else statement and simply call the super.paintComponent(Graphics g) method that in my understanding, should paint it without the image. The problem is that as soon as I put the if statement inside the paintComponent method it seems to invalidate the entire code inside the method.
Any suggestions or explanation on why is this happening would be appreciated.
The code is below:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class PruebaEventosSelf {
public static void main(String[] args) {
// TODO Auto-generated method stub
MarcoBotonSelf marco=new MarcoBotonSelf();
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class MarcoBotonSelf extends JFrame{
public MarcoBotonSelf() {
setExtendedState(MarcoBotonSelf.MAXIMIZED_BOTH);
setTitle("National Aeronautics and Space Administration NASA");
Image image=Toolkit.getDefaultToolkit().getImage("C:\\Users\\wagne\\OneDrive\\Desktop\\Nasa.png");
setIconImage(image);
LaminaBoton lamina=new LaminaBoton();
add(lamina);
setVisible(true);
}
}
class LaminaBoton extends JPanel implements ActionListener {
JButton botonAzul=new JButton("Blue");
JButton botonNegro=new JButton("Black");
JButton botonGris=new JButton("Gris");
boolean repaint=false;
public LaminaBoton() {
botonAzul.addActionListener(this);
add(botonAzul, Container.CENTER_ALIGNMENT);
botonNegro.addActionListener(this);
add(botonNegro, Container.LEFT_ALIGNMENT);
botonGris.addActionListener(this);
add(botonGris, Container.CENTER_ALIGNMENT);
}
public void paintComponent(Graphics g) {
if(repaint) {
super.paintComponent(g);
}else {
Image imagen=Toolkit.getDefaultToolkit().getImage("C:\\Users\\wagne\\OneDrive\\Desktop\\NASA.jpg");
g.drawImage(imagen, 0, 0, this);
}
}
public void actionPerformed(ActionEvent e) {
Object pulsado=e.getSource();
if (pulsado==botonAzul){
repaint=true;
repaint();
this.setBackground(Color.blue);
System.out.println("Blue is working!");
}else if(pulsado==botonNegro) {
System.out.println("Black is working!");
setBackground(Color.BLACK);
}else {
System.out.println("Gray is working!");
setBackground(Color.DARK_GRAY);
}
}
}
HERE'S ANOTHER WAY I TRIED:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class PruebaEventosSelf {
public static void main(String[] args) {
// TODO Auto-generated method stub
MarcoBotonSelf marco=new MarcoBotonSelf();
marco.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class MarcoBotonSelf extends JFrame{
public MarcoBotonSelf() {
setExtendedState(MarcoBotonSelf.MAXIMIZED_BOTH);
setTitle("National Aeronautics and Space Administration NASA");
Image image=Toolkit.getDefaultToolkit().getImage("C:\\Users\\wagne\\OneDrive\\Desktop\\Nasa.png");
setIconImage(image);
LaminaBoton lamina=new LaminaBoton();
add(lamina);
setVisible(true);
}
}
class LaminaBoton extends JPanel implements ActionListener {
JButton botonAzul=new JButton("Blue");
JButton botonNegro=new JButton("Black");
JButton botonGris=new JButton("Gris");
boolean repaint=false;
public LaminaBoton() {
botonAzul.addActionListener(this);
add(botonAzul, Container.CENTER_ALIGNMENT);
botonNegro.addActionListener(this);
add(botonNegro, Container.LEFT_ALIGNMENT);
botonGris.addActionListener(this);
add(botonGris, Container.CENTER_ALIGNMENT);
}
public void paintComponent(Graphics g) {
Image imagen=Toolkit.getDefaultToolkit().getImage("C:\\Users\\wagne\\OneDrive\\Desktop\\NASA.jpg");
g.drawImage(imagen, 0, 0, this);
if (repaint) super.paintComponent(g);
}
public void actionPerformed(ActionEvent e) {
Object pulsado=e.getSource();
if (pulsado==botonAzul){
repaint=true;
repaint();
this.setBackground(Color.blue);
System.out.println("Blue is working!");
}else if(pulsado==botonNegro) {
System.out.println("Black is working!");
setBackground(Color.BLACK);
}else {
System.out.println("Gray is working!");
setBackground(Color.DARK_GRAY);
}
}
}
I've tried another 4 different ways but they all seem to lead to the same result of the image not being drown not even if the use hasn't clicked any buttons.
Your paintComponent() method should ALWAYS call super.paintCompnent(g); as the first statement in the method. Then it should draw the image only if the repaint variable is false.
It would be better - and more logically readable - to call that variable paintImage and set it initially to true, then the button listener sets it to false, and the paintComponent() method draws the image only if paintImage is true.

Repaint function messes up the whole frame

I have a problem when trying to draw some elements using paint method in Swing.
As title says, my whole frame collapses and does some weird repeating.
I made a separate JPanel so I can manipulate drawn shapes:
public class PanelPovrsina extends JPanel{
private ArrayList<Oblik> listaOblika;
public PanelPovrsina() {
// svi oblici
this.listaOblika = new ArrayList<Oblik>();
this.listaOblika.add(new Kvadrat(new Tacka(50, 50), 50, "zuta", "crvena"));
this.setBackground(Color.WHITE);
this.setVisible(true);
}
public void paint(Graphics g) {
if(this.listaOblika.isEmpty()) return;
Iterator<Oblik> it = this.listaOblika.iterator();
while(it.hasNext()) {
it.next().crtajUBoji(g);
}
repaint(); // this causes problems!
}
public ArrayList<Oblik> getListaOblika() {
return this.listaOblika;
}
}
Here is the frame with this code:
And here it is without repaint method:
No, I know repaint method is essential in order to dynamically add shapes and actually draw, but I can't make this work correctly.
Also, as you can see from the code above, background of panel is set to white, but my frame would'n render it.
Hope there is enough information to solve my problem, if not, I will add code of my JFrame!
Thank you!
You should never override the paint method, as it handles a number of other things behind the scenes. You should override paintComponent instead.
As #Joe C answered, I should have been using paintComponent method, not paint! Working code:
public class PanelPovrsina extends JPanel{
private ArrayList<Oblik> listaOblika;
public PanelPovrsina() {
// svi oblici
this.listaOblika = new ArrayList<Oblik>();
this.listaOblika.add(new Kvadrat(new Tacka(50, 50), 50, "zuta", "crvena"));
this.setBackground(Color.PINK);
this.setVisible(true);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (Oblik obl : this.listaOblika) {
obl.crtajUBoji(g);
}
repaint();
}
public ArrayList<Oblik> getListaOblika() {
return this.listaOblika;
}
}

JFrame paint does not overriding

to execute flow chart Symbols.
But JFrame paint method is not working for this method.
package floating;
import designs.*; //mydesings for executing flow chart Symbols
import java.awt.*;
import javax.swing.*;
public class Test extends JFrame
{
boolean START,PASS; //for using
int SPEED=1;
JSlider jSlider1 = new javax.swing.JSlider();
JSeparator js=new JSeparator();
JToggleButton jToggleButton1 = new javax.swing.JToggleButton("START");
JToggleButton jToggleButton2 = new javax.swing.JToggleButton("PASS");
Test(String a)
{
JFrame jf=new JFrame(a);
Dimension dim=Toolkit.getDefaultToolkit().getScreenSize();
jf.setSize(dim.width,dim.height-30);
jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
jToggleButton1.setLocation((dim.width/2)+30,25);
jToggleButton1.setSize(100,30);
jToggleButton1.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jToggleButton1ItemStateChanged(evt);
}
});
jToggleButton2.setLocation((dim.width/2)+50+100,25);
jToggleButton2.setSize(100,30);
jToggleButton2.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
jToggleButton2ItemStateChanged(evt);
}
});
js.setOrientation(SwingConstants.VERTICAL);
js.setForeground(Color.red);
js.setLocation(dim.width/2,0);
js.setPreferredSize(dim);
js.setSize(10,dim.height);
jf.add(js);
jSlider1.setLocation(dim.width-300,20);
jSlider1.setSize(250,50);
jSlider1.setToolTipText("Set to Seconds");
jSlider1.setMinimum(1);jSlider1.setMaximum(5);jSlider1.setMajorTickSpacing(1);
jSlider1.setMinorTickSpacing(1);jSlider1.setValue(1);
jSlider1.setPaintLabels(true);
jSlider1.setPaintTicks(true);
jSlider1.setPaintTrack(true);
jSlider1.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) {
jSlider1MouseClicked(evt);
}
});
jf.add(jSlider1);
jf.add(jToggleButton1);
jf.add(jToggleButton2);
jf.setLayout(null);
jf.setVisible(true);
}
public void jToggleButton1ItemStateChanged(java.awt.event.ItemEvent evt)
{
if(jToggleButton1.getActionCommand()=="START")
{
System.out.printf(jToggleButton1.getText());
jToggleButton1.setText("STOP");
this.START=true;
System.out.println(this.START);
}
else
{
System.out.printf(jToggleButton1.getText());
jToggleButton1.setText("START");
this.START=false;
System.out.println(this.START);
}
}
public void jToggleButton2ItemStateChanged(java.awt.event.ItemEvent evt)
{
if( jToggleButton2.getActionCommand()=="PASS")
{
System.out.printf(jToggleButton2.getText());
jToggleButton2.setText("RESUME");
this.PASS=true;
System.out.println(" "+this.PASS);
}
else
{
System.out.printf(jToggleButton2.getText());
jToggleButton2.setText("PASS");
this.PASS=false;
System.out.println( " " +this.PASS);
}
}
private void jSlider1MouseClicked(java.awt.event.MouseEvent evt)
{
this.SPEED=jSlider1.getValue();
System.out.println(SPEED);
}
#Override
public void paint(Graphics g) //testing paint method
{
super.paint(g);
g.drawLine(10, 20, 50, 70);
repaint();
}
public static void main(String args[])
{
Test a=new Test("Test");
}
}
Test class extends JFrame. So if you want to have overridden paint method to work, you have to create an object of Test class. And make it setVisible(true)
In stead, you are creating another JFrame object in Test's constructor. Don't create it. The object of Test itself is a JFrame. Add all components to Test object in stead of JFrame object (jF).
Hope this helps.
Don't invoke repaint() from a painting method. This will cause an infinite loop.
Custom painting is done by overriding the paintComponent() method of a JPanel (or JComponent) and then you add the panel to the frame. Read the section from the Swing tutorial on Custom Painting for more information and examples. Start with the example from the tutorial and make changes so your class is better designed.
Don't use "==" for string comparisons. Use the equals(...) method.
Also, in the future, post a proper SSCCE when you ask a question. Your question is about painting so most of the code you posted is unrelated to the question.

No keyboard input working KeyAdapter

I wrote some application and wanted to add some keyboard input to it.
My main class extends a JPanel so i could add the keyAdapter into the constructor.
The keyAdapter is a new class called "InputAdapter" extending keyadapter with it's keyPressed() and keyReleased() method. on click or release the console should print some string, e.g. here "Test"
I don't know why, but the console won't print any text. Also, when I tell it to turn a sprites visibility to false nothing happens as well.
So i guess the KeyAdapter isn't working properly, so could someone take a closer look into my codelines?
i guess this issue has nothing to do with the other implemented classes i wrote because when removing them, the issue with the non working keyboard input remains.
package com.ochs.game;
public class Game extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 3;
public boolean isRunning;
public Game() {
addKeyListener(new InputAdapter());
setFocusable(true);
requestFocus();
start();
}
public void start() {
isRunning = true;
new Thread(this).start();
}
public void stop() {
isRunning = false;
}
public void run() {
init();
while(isRunning) {
update();
repaint();
try {
Thread.sleep(5);
} catch (InterruptedException e) {
System.out.println("Thread sleep failed.");
}
}
}
public void init() {
}
public void update() {
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
}
public static void main(String[] args) {
Game gameComponent = new Game();
Dimension size = new Dimension(WIDTH*SCALE, HEIGHT*SCALE);
JFrame frame = new JFrame("Invaders");
frame.setVisible(true);
frame.setSize(size);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(gameComponent);
}
public class InputAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent arg0) {
System.out.println("Test");
}
#Override
public void keyReleased(KeyEvent arg0) {
System.out.println("Test");
}
}
}
Your code works for me:
java version "1.6.0_27"
OpenJDK Runtime Environment (IcedTea6 1.12.6) (6b27-1.12.6-1ubuntu0.12.04.2)
OpenJDK Client VM (build 20.0-b12, mixed mode, sharing)
Tip 1 - You should override paintComponent(Graphics g) i guess, not paint()
public void paintComponent(Graphics g){
super.paintComponent(g);
//...
}
Tip 2 - Use addNotify() on your JPanel:
public void addNotify(){
super.addNotify();
//start from here
new Thread(this).start();
}
Tip 3 - Launch your app this way, from the EDT Thread (see What does SwingUtilities.invokeLater do?)
SwingUtilities.invokeLater(new Runnable() {
public void run(){
//your code
}
});
Hope it helps!
There are many possible reasons why this might not work. KeyListener is very fussy. It requires that the component that is registered to not only be focusable, but have focus.
Even though your component seems to both these things, if, for some reason, focus is grabbed by another component, the KeyListener will stop working.
You should use requestFocusInWindow and requestFocus is unreliable, but a better solution would be to use Key bindings, which has the ability to over come all that messiness with focus...
You should avoid overriding paint and use paintComponent instead, check out Performing Custom Painting for more details.
Mixing threads with Swing is tricky, you will also want to be sure that you are not violating the single thread rules of Swing when you are updating the your state. Check out Concurrency in Swing for more details
Your basic code design is old AWT painting code. I echo everything MadProgrammer says for a better Swing design.
In addition:
there is no need for an empty init() method. Get rid of the method and the call to the method.
same for the update() method.
The big problem with the posted code is that you add the panel to the frame AFTER the frame is visible. You should always add components to the frame before making the frame visible:
JFrame frame = new JFrame("Invaders");
frame.add(gameComponent);
...
frame.setVisible(true);
Don't take the easy way out and just make the above change. Write code for a Swing program not an AWT program.

Unable to call the repaint in applet from child frame

I have made an applet name ParentApplet.java whose task is to create a child frame
Child frame coding is defined in ChildFrame.java
ParentApplet.java
public class ParentApplet extends Applet {
ChildFrame frame;
private static int time = 0;
#Override
public void start() {
frame.setVisible(true);
}
#Override
public void stop() {
frame.setVisible(false);
}
#Override
public void init() {
frame = new ChildFrame("Child");
this.setSize(400, 400);
}
#Override
public void paint(Graphics g) {
g.drawString("Child's Info : " + (++time), 50, 100);
g.drawString(frame.getMessage(), 400, 100);
System.out.println(frame.getMessage().isEmpty() ? "Empty" : frame.getMessage());
}
}
ChildFrame.java
public class ChildFrame extends Frame {
private String mess = "";
public ChildFrame(String title) {
super(title);
addMouseListener(new MyMouseAdapter(this));
addWindowListener(new MyWindowAdapter(this));
setSize(300, 500);
}
public String getMessage() {
return mess;
}
public void setMessage(String mess) {
this.mess = mess;
(new ParentApplet()).repaint();
System.out.println("Click");
}
}
MyMouseAdapter.java
public class MyMouseAdapter extends MouseAdapter {
ChildFrame frame;
public MyMouseAdapter(ChildFrame frame) {
this.frame = frame;
}
#Override
public void mouseClicked(MouseEvent e) {
frame.setMessage("Mouse Cliked in Child");
}
}
MyWindowAdapter.java
public class MyWindowAdapter extends WindowAdapter {
ChildFrame frame;
public MyWindowAdapter(ChildFrame frame) {
this.frame = frame;
}
#Override
public void windowClosing(WindowEvent we) {
frame.setVisible(false);
}
}
Now i am unable to reach the paint method again even after calling the repaint method from the ChildFrame class. Please suggest me whether i have done something wrong or some thing i need to understand.
Thanks in advance
Gagandeep Singh
The answer to your question is basically "you don't do that".
The Applet's paint() method is responsible for painting the contents of the actual applet component-- i.e. the visible component that appears in the web page. Your ChildFrame should then have a separate paint() method to paint itself (or in fact, would usually have a Canvas added to it, and that Canvas in turn has its own paint() method).
(Remember that in Java a "Frame" is effectively a "window"-- i.e. a standalone window that opens separately to the web page.)
You can call repaint() on whatever component from wherever you like. This will eventually lead to that component's paint() method being called. In your particular example, you shouldn't call "new ParentApplet()" -- you don't want to call repaint() on some randomly created new applet, but rather on the single already existing one. So change this by passing a reference to your applet into the constructor of ChildFrame which ChildFrame can then hold as an instance variable and re-use when needed:
public class ChildFrame extends Frame {
private String mess = "";
private final ParentApplet parentApplet;
public ChildFrame(ParentApplet applet, String title) {
super(title);
this.parentApplet = applet;
addMouseListener(new MyMouseAdapter(this));
addWindowListener(new MyWindowAdapter(this));
setSize(300, 500);
}
...
public void setMessage(String mess) {
this.mess = mess;
parentApplet.repaint();
}
}
I must admit that so far, it's not immediately obvious why you would have a setMessage() on a separate frame whose purpose is to set the message displayed in the applet. Why not put the setMessage() method on the applet in that case? But maybe you have another reason for doing it your way that isn't apparent so far.

Categories

Resources