Related
I have two panels. One of them is GamePanel and the other one is ControlPanel. When I press the launch button (which is added in the ControlPanel) the ball starts moving until it hits something. I have score, time and level labels in the ControlPanel and I expect them to update during the game but they don't.
ControlPanel
import java.awt.*;
import javax.swing.*;
public class ControlPanel extends JPanel {
public static JLabel timeValue, scoreValue, levelValue;
public static JButton launch;
public static Timer timer;
ControlPanel() {
this.setLayout(null);
this.setBounds(0, 600, 1200, 200);
}
public void addUnits() {
launch = new JButton("Launch");
launch.setBounds(450, 70, 90, 65);
launch.addChangeListener(new ChangeListener() {
int start = 0;
public void stateChanged(ChangeEvent e) {
if (ControlPanel.launch.getModel().isPressed()) {
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
timeValue.setText(++start + " sec");
}
};
timer = new Timer(1000, taskPerformer);
timer.setRepeats(true);
timer.start();
GamePanel.ball.moveBall();
}
}
});
add(launch);
JLabel timeLabel = new JLabel("Time");
timeLabel.setBounds(615, 70, 90, 25);
add(timeLabel);
timeValue = new JLabel("0 sec");
timeValue.setBounds(690, 70, 90, 25);
add(timeValue);
JLabel scoreLabel = new JLabel("Score");
scoreLabel.setBounds(605, 110, 90, 25);
add(scoreLabel);
scoreValue = new JLabel(String.valueOf(Score.score));
scoreValue.setBounds(690, 110, 90, 25);
add(scoreValue);
JLabel levelLabel = new JLabel("Level");
levelLabel.setBounds(800, 110, 90, 25);
add(levelLabel);
levelValue = new JLabel(String.valueOf(GamePanel.status));
levelValue.setBounds(860, 110, 90, 25);
add(levelValue);
}
}
This is my moveBall method
public void moveBall() {
// calculate move
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
// initiate move
if(hit()) {
ControlPanel.timer.stop();
level = getLevel() + 1;
score = // calculate score;
timer.stop();
ControlPanel.levelValue.setText(String.valueOf(level));
ControlPanel.scoreValue.setText(String.valueOf(score));
ControlPanel.levelValue.revalidate();
ControlPanel.scoreValue.revalidate();
ControlPanel.levelValue.repaint();
ControlPanel.scoreValue.repaint();
}
paintingComponent.repaint();
}
};
timer = new Timer(10, taskPerformer);
timer.start();
}
I am trying to make a program to java and i have the common problem with flickering. I have try many things to eliminate but all the same. while the oval that i paint is moving the japplet is flickering. i need your help to solve this problem. here is my code:
import java.awt.Color;
public class all extends JApplet implements Runnable {
double x=0;
double y=0;
int m=0;
int n=0;
int f=30;
int μ=0;
Thread kinisi;
JPanel panel;
JFrame frame;
private boolean running = false;
private JTextField textField1;
private JTextField textField2;
Image backGround;
JPanel panel_3;
Image bf = createImage(m, n);
private Graphics doubleg;
private Image i;
public void init() {
this.setSize(800, 700);
}
public all() {
getContentPane().setLayout(null);
JButton btnNewButton = new JButton("Start");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
String b=textField2.getText();
String z =textField1.getText();
if (textField1.getText().equals("") ||
textField2.getText().equals("")){
JOptionPane.showMessageDialog(
new JFrame(),
"Δωστε τιμή για το φ και το μ!",
"ERROR",JOptionPane.ERROR_MESSAGE);
} else{
f = Integer.parseInt(b);
μ = Integer.parseInt(z);
Start(); }
}
});
btnNewButton.setBounds(469, 168, 89, 23);
getContentPane().add(btnNewButton);
JButton btnStop = new JButton("Pause");
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pause();
}
});
btnStop.setBounds(588, 168, 89, 23);
getContentPane().add(btnStop);
JButton btnReset = new JButton("Reset");
btnReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Reset();
}
});
btnReset.setBounds(701, 168, 89, 23);
getContentPane().add(btnReset);
JLabel label = new JLabel("\u03BC");
label.setHorizontalAlignment(SwingConstants.CENTER);
label.setBounds(549, 63, 46, 14);
getContentPane().add(label);
textField1 = new JTextField();
textField1.setBounds(529, 101, 86, 20);
getContentPane().add(textField1);
textField1.setColumns(10);
JLabel label_1 = new JLabel("\u03C6");
label_1.setHorizontalAlignment(SwingConstants.CENTER);
label_1.setBounds(681, 63, 46, 14);
getContentPane().add(label_1);
textField2 = new JTextField();
textField2.setBounds(667, 101, 86, 20);
getContentPane().add(textField2);
textField2.setColumns(10);
JButton btnNewButton_1 = new JButton("");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
JOptionPane.showMessageDialog(
new JFrame(),
"Οδηγίες προγράμματος","Οδηγίες",
JOptionPane.INFORMATION_MESSAGE);
}
});
btnNewButton_1.setIcon(
new ImageIcon(all.class.getResource("/Images/info.png")));
btnNewButton_1.setBounds(732, 5, 39, 35);
getContentPane().add(btnNewButton_1);
JLabel label_2 = new JLabel("");
label_2.setIcon(
new ImageIcon(all.class.getResource("/Images/earth.jpg")));
label_2.setBounds(-20, 0, 820, 361);
getContentPane().add(label_2);
JPanel panel_1 = new JPanel();
panel_1.setBorder(
new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel_1.setBounds(10, 372, 369, 290);
getContentPane().add(panel_1);
JPanel panel_2 = new JPanel();
panel_2.setBorder(
new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
panel_2.setBounds(408, 372, 369, 290);
getContentPane().add(panel_2);
}
public void paint(Graphics g){
super.paint(g);
g.drawLine(0,f,350,200);
g.drawLine(0,200,350,200);
g.drawOval(m,n,40,40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
//Graphics2D g2d = (Graphics2D) g;
g.drawLine(460,400,460,650);
g.drawLine(20, 620, 350, 620);
g.drawLine(50,400,50,650);
g.drawLine(430, 620, 760, 620);
}
public void Start() {
kinisi = new Thread(this);
kinisi.start();
running = true;
}
public void run() {
while (running) {
if (x < 340){
double l = 200-f;
double k = l/350;
double y=k*x+f-30;
x= x+1;
m = (int) x;
n = (int) y;
repaint();
try {
Thread.sleep(μ);
} catch (InterruptedException ie) {}
}
}
}
public void update(Graphics g) {
if(i==null){
i=createImage(800,700);
doubleg = i.getGraphics();
}
doubleg.setColor(getBackground());
doubleg.fillRect(0,0,800,700);
doubleg.setColor(getForeground());
paint(doubleg);
g.drawImage(i,0,0,this);
}
public void paint1(Graphics g){
g.drawLine(0, f ,350, 200);
g.drawOval(m, n, 40, 40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
}
public void pause() {
if (kinisi != null) {
running = false;
}
}
public boolean Reset() {
if (kinisi != null) {
running = false;
kinisi.interrupt();
kinisi = null;
x=0;
y=0;
f=30;
m=0;
n=0;
repaint();
textField1.setText("");
textField2.setText("");
}
Graphics g = getGraphics();
g.drawOval(m,n,40,40);
Color brown=new Color(137,66,0);
g.setColor(brown);
g.fillOval(m, n, 40, 40);
return false;
}
public static void main(String[] args) {
JFrame frame = new JFrame("FISIKI");
frame.getContentPane().add(new all());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.setVisible(true);
frame.setResizable(false);
}
}
Thank you very much and sorry for my english are not very good!
There are a number of things that jump out at me.
You're extending from JApplet, but are adding it to a JFrame
You're mixing components with you custom painting
Not using layout managers.
Using getGraphics.
Firstly...
You should never override paint of a top level container (like JApplet). There are many reasons and you've found one. Top level containers are not double buffered. Instead, you should be creating a custom component (by extending something like JPanel) and overriding it's paintComponent method...
Secondly
Decided how you application is going to be. Is it an applet or application? If you follow the first point, then it really doesn't matter, as you only simply need to add the panel to the top level container.
Thirdly
I would create a panel that did the custom painting. Then I would create separate containers for all the fields and other parts of the application. This will allow you to separate the areas of responsibility. It would also allow you to use layout managers ;)
Fourthly
Use layout managers. The layout manager API has being designed to solve one of this most annoying aspects of GUI design, you're asking for a lot of trouble and work you decided to discard it - IMHO.
Fifthly
getGraphics should never be used. Apart from the fact that it can return null, it is only a snap shot of what is currently on the screen. As soon as the RepaintManager decides to perform a repaint, anything rendered to it will be lost. You should use paintComponent to update the state of your custom pane.
I am doing a project for class and was cleaning up my indentation etc and have done something to my code. I cannot see the forest for the trees and could use some help. I am getting a cannot find symbol error when I compile. Here is the code.
public class TrafficLights extends JFrame implements ItemListener
{
private JRadioButton jrbRed;
private JRadioButton jrbYellow;
private JRadioButton jrbGreen;
private ButtonGroup btg = new ButtonGroup();
private TrafficLights.Light light = new TrafficLights.Light();
// ^ error 1 is here ^ error 2 is here
public static void main(String[] args)
{
TrafficLights frame = new TrafficLights();
frame.setDefaultCloseOperation(3);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public TrafficLights()
{
setTitle("Traffic Light Signal");
JPanel p1 = new JPanel();
p1.setLayout(new FlowLayout(1));
p1.add(this.light);
JPanel p2 = new JPanel();
p2.setLayout(new FlowLayout());
p2.add(this.jrbRed = new JRadioButton("Red"));
p2.add(this.jrbYellow = new JRadioButton("Yellow"));
p2.add(this.jrbGreen = new JRadioButton("Green"));
this.jrbRed.setMnemonic('R');
this.jrbYellow.setMnemonic('Y');
this.jrbGreen.setMnemonic('G');
this.btg.add(this.jrbRed);
this.btg.add(this.jrbYellow);
this.btg.add(this.jrbGreen);
setLayout(new BorderLayout());
add(p1, "Center");
add(p2, "South");
this.jrbRed.addItemListener(this);
this.jrbYellow.addItemListener(this);
this.jrbGreen.addItemListener(this);
this.jrbGreen.setSelected(true);
this.light.turnOnGreen();
}
public void itemStateChanged(ItemEvent e)
{
if (this.jrbRed.isSelected())
{
this.light.turnOnRed();
}
if (this.jrbYellow.isSelected())
{
this.light.turnOnYellow();
}
if (this.jrbGreen.isSelected())
{
this.light.turnOnGreen();
}
class Light extends JPanel
{
private boolean red;
private boolean yellow;
private boolean green;
public Light()
{ }
public void turnOnRed()
{
this.red = true;
this.yellow = false;
this.green = false;
repaint();
}
public void turnOnYellow()
{
this.red = false;
this.yellow = true;
this.green = false;
repaint();
}
public void turnOnGreen()
{
this.red = false;
this.yellow = false;
this.green = true;
repaint();
}
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (this.red)
{
g.setColor(Color.red);
g.fillOval(10, 10, 20, 20);
g.setColor(Color.black);
g.drawOval(10, 35, 20, 20);
g.drawOval(10, 60, 20, 20);
g.drawRect(5, 5, 30, 80);
}
else if (this.yellow)
{
g.setColor(Color.yellow);
g.fillOval(10, 35, 20, 20);
g.setColor(Color.black);
g.drawRect(5, 5, 30, 80);
g.drawOval(10, 10, 20, 20);
g.drawOval(10, 60, 20, 20);
}
else if (this.green)
{
g.setColor(Color.green);
g.fillOval(10, 60, 20, 20);
g.setColor(Color.black);
g.drawRect(5, 5, 30, 80);
g.drawOval(10, 10, 20, 20);
g.drawOval(10, 35, 20, 20);
}
else
{
g.setColor(Color.black);
g.drawRect(5, 5, 30, 80);
g.drawOval(10, 10, 20, 20);
g.drawOval(10, 35, 20, 20);
g.drawOval(10, 60, 20, 20);
}
}
public Dimension getPreferredSize()
{
return new Dimension(100, 100);
}
}
}
}
This is the problem - I've indented the code to make it clearer...
public void itemStateChanged(ItemEvent e)
{
if (this.jrbRed.isSelected())
{
this.light.turnOnRed();
}
if (this.jrbYellow.isSelected())
{
this.light.turnOnYellow();
}
if (this.jrbGreen.isSelected())
{
this.light.turnOnGreen();
}
class Light extends JPanel
{
private boolean red;
private boolean yellow;
private boolean green;
...
You're currently declaring the Light class within the itemStateChanged method. I don't think you meant to do that.
Additionally, I would question whether you really need Light to be an inner or nested class itself. I would suggest making it a top-level class - at least to start with. It'll be easier to navigate that way, apart from anything else.
I'd also strongly suggest trying to keep on top of your indentation at all times. If the rest of your code is already nicely indented, it's easier to see when something goes wrong. IDEs such as Eclipse are able to indent all your code for you at the touch of a button - I would advise you to use that feature heavily.
I created a menu with some options to choose. One of those options is "Play with computer" which starts the game.
JButton ai = new JButton("Play with computer");
ai.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
GameBoard play = new GameBoard();
hi.dispose(); //jframe
}
});
And then comes GameBoard:
#SuppressWarnings("serial")
public class GameBoard extends Canvas {
private Image dbi;
private Graphics db;
private JFrame okno;
Rectangle aiPaddle = new Rectangle(10, 590, 10, 50);
Rectangle pPaddle = new Rectangle(10, 100, 10, 50);
Rectangle ball = new Rectangle(560, 10, 10, 10);
Player p = new Player(this);
Ai a = new Ai(this);
Ball b = new Ball(this);
GameBoard() {
okno = new JFrame();
okno.setTitle("Pink Ponk");
okno.setSize(600, 300);
okno.getContentPane().setBackground(Color.black);
okno.setResizable(false);
okno.setVisible(true);
okno.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addKeyListener(p);
}
public static void main(String[] args) {
GameBoard gra = new GameBoard();
gra.okno.add(gra);
}
#Override
public void update(Graphics g) {
dbi = createImage(10, 50);
db = dbi.getGraphics();
paint(db);
g.clearRect(0, 0, 600, 300);
g.setColor(Color.white);
g.drawRect(p.getX(), p.getY(), 10, 50);
g.fillRect(p.getX(), p.getY(), 10, 50);
g.drawOval(b.getX(), b.getY(), 10, 10);
g.fillOval(b.getX(), b.getY(), 10, 10);
g.drawRect(a.getX(), a.getY(), 10, 50);
g.fillRect(a.getX(), a.getY(), 10, 50);
}
#Override
public void paint(Graphics g) {
pPaddle = new Rectangle(p.getX(), p.getY(), 10, 50);
aiPaddle = new Rectangle(a.getX(), a.getY(), 10, 50);
ball = new Rectangle(b.getX(), b.getY(), 10, 10);
g.clearRect(0, 0, 600, 300);
g.setColor(Color.white);
g.drawRect(p.getX(), p.getY(), 10, 50);
g.fillRect(p.getX(), p.getY(), 10, 50);
g.drawOval(b.getX(), b.getY(), 10, 10);
g.fillOval(b.getX(), b.getY(), 10, 10);
g.drawRect(a.getX(), a.getY(), 10, 50);
g.fillRect(a.getX(), a.getY(), 10, 50);
}
}
I'm sure it should work, but it does not. I'm getting black screen, without any rectangles or ovals. Threads from other classes are working, because I'm still losing the game. :)
The GameBoard constructor, which is the only thing you call when your start button is pressed, creates a new frame, sets its background, and makes it visible. But it doens't add any component to the frame. You probably need to add
okno.add(this);
Note that it's not really the responsibility of the constructor of your Canvas to display a frame and add itself to this frame, though. I would move the frame creation outside of the constructor. Let the constructor do what it's supposed to do: construct the object.
How can I make it so that the progress bar slowly goes down with the time limit?
class GamePanel extends JPanel implements MouseListener, ActionListener
{
private JButton quit;
private JButton q;
private Font loadFont;
public GamePanel()
{
setBackground(Color.blue); // sets background color
this.setLayout(null);
quit = new JButton("Quit");
quit.addActionListener(this);
quit.setBounds(550, 700, 100, 30);
this.add(quit);
q = new JButton("Questions");
q.addActionListener(this);
q.setBounds(100, 100, 120, 30);
this.add(q);
loadFont = new Font("Serif", Font.PLAIN, 30);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.black);
g.fillRect(80, 100, 610, 560);
g.setColor(Color.white);
g.fillRect(90, 110, 110, 100);// 1st column
g.fillRect(90, 220, 110, 100);//
g.fillRect(90, 330, 110, 100);//
g.fillRect(90, 440, 110, 100);//
g.fillRect(90, 550, 110, 100);//
g.fillRect(210, 110, 110, 100);// 2nd column
g.fillRect(210, 220, 110, 100);//
g.fillRect(210, 330, 110, 100);//
g.fillRect(210, 440, 110, 100);//
g.fillRect(210, 550, 110, 100);//
g.fillRect(330, 110, 110, 100);// 3rd column
g.fillRect(330, 220, 110, 100);//
g.fillRect(330, 330, 110, 100);//
g.fillRect(330, 440, 110, 100);//
g.fillRect(330, 550, 110, 100);//
g.fillRect(450, 110, 110, 100);// 4th column
g.fillRect(450, 220, 110, 100);//
g.fillRect(450, 330, 110, 100);//
g.fillRect(450, 440, 110, 100);//
g.fillRect(450, 550, 110, 100);//
g.fillRect(570, 110, 110, 100);// 5th column
g.fillRect(570, 220, 110, 100);//
g.fillRect(570, 330, 110, 100);//
g.fillRect(570, 440, 110, 100);//
g.fillRect(570, 550, 110, 100);//
g.setColor(Color.green);
g.setFont(loadFont);
g.drawString(input + ":", 100, 710);
}
public void actionPerformed(ActionEvent e)
{
String order = e.getActionCommand();
if(order.equals("Quit"))
cards.show(c, "Introduction");
if(order.equals("Questions"))
cards.show(c, "Questions");
}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
class QuestionPanel extends JPanel implements ActionListener
{
private long startTime, elapsedTime;
private Timer timer;
private int countdown;
private Font loadFont;
public QuestionPanel()
{
setBackground(Color.pink); // sets background color
this.setLayout(null); // moved into constructor from ActionPerformed: only change layout in constructor
startTime = 0;
elapsedTime = 0;
countdown = 590;
loadFont = new Font("Segoe Script", Font.BOLD, 20);
if(timer == null)
{// use the biggest value possible that provides your desired time keeping precision (usually no less than 15 on Windows)
timer = new Timer(100, this);
startTime = System.currentTimeMillis(); // gets start time in milliseconds
timer.start();
}
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.fillRect(100, 100, 600, 25);
g.setColor(Color.green);
g.fillRect(105, 105, countdown, 15);
g.setColor(Color.black);
g.setFont(loadFont);
g.drawString("" + ((System.currentTimeMillis() - startTime) / 1000.0), 100, 80); // display remaining time
}
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
elapsedTime = System.currentTimeMillis() - startTime;
if(elapsedTime < (5000))
{
countdown--;
repaint();
}
else
{
timer.stop();
if(timer == null)
{
timer = new Timer(500, this);
timer.start();
}
}
if(elapsedTime >= (5000)) // can't use == here because of limited precision of system clock
cards.show(c, "Correct!");
}
}
class AnswerPanel extends JPanel implements ActionListener
{
private JButton revert;
public AnswerPanel()
{
setBackground(Color.yellow); // sets background color
this.setLayout(null);
revert = new JButton("Back");
revert.addActionListener(this);
revert.setBounds(340, 700, 100, 30);
this.add(revert);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e)
{
String directive = e.getActionCommand();
if(directive.equals("Back"))
cards.show(c, "Start");
}
}
class FailPanel extends JPanel implements ActionListener
{
private JButton turnaround;
public FailPanel()
{
setBackground(Color.green); // sets background color
this.setLayout(null);
turnaround = new JButton("Back");
turnaround.addActionListener(this);
turnaround.setBounds(340, 700, 100, 30);
this.add(turnaround);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
}
public void actionPerformed(ActionEvent e)
{
String bidding = e.getActionCommand();
if(bidding.equals("Back"))
cards.show(c, "Start");
}
}
}// end of the entire program
Sorry, I still could not find the motivation to actually read your code, but just threw together this example based on the question. See if it gives you some ideas.
Note that it is an SSCCE and uses just 40 lines of code in all.
import java.awt.event.*;
import javax.swing.*;
class CountDownProgressBar {
Timer timer;
JProgressBar progressBar;
CountDownProgressBar() {
progressBar = new JProgressBar(JProgressBar.VERTICAL, 0, 10);
progressBar.setValue(10);
ActionListener listener = new ActionListener() {
int counter = 10;
public void actionPerformed(ActionEvent ae) {
counter--;
progressBar.setValue(counter);
if (counter<1) {
JOptionPane.showMessageDialog(null, "Kaboom!");
timer.stop();
}
}
};
timer = new Timer(1000, listener);
timer.start();
JOptionPane.showMessageDialog(null, progressBar);
}
public static void main(String[] args) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
CountDownProgressBar cdpb = new CountDownProgressBar();
}
});
}
}
From the looks of it, all of this code is within a big Java file? That is a bad idea.
You should have a good reason to define a class as an inner class, and from the looks of it, you do not have one for QuestionPanel and others.
As for the problem, your paintComponent method is called every time your counter is updated, which is right now roughly once every 0.1 seconds, yet you only tick by 1 pixel on each update, so by the end of 5 seconds, you've cut off 10*5 pixels (50). What you should do is update the progress bar by a different mechanism, such as a calculating the current time processed:
long processed = System.currentTimeMillis() - startTime;
double percent = Math.max(0, 1 - processed / 5000.0);
int width = (int)(590 * percent);
That is definitely too much information, and a very broad question. I'd say at most you only need to include the code for the class where the timer is, and the class where the progress bar gets drawn.
From skimming the code, I'm guessing you're using a rectangle to draw the progress bar. Based on that, one way you could go about it would be using a variable to store the width of the bar, and every time the timer ticks, decrease the width of the bar by a set amount. Then just set the width of the rectangle drawn to the value stored in the variable.