Hi I am new to java and I thought I'd try produce a game where the user actually tries solving the 8 queens problem themselves. However, It increases in difficulty starting 8 rooks, up to 14 bishops then 8 queens.
I have created the chessboard successfully. I have a problem with my mouselistener... each square on the board is a button and when clicked my intention is that that square will change colour to indicate its been clicked, then all squares that cant be clicked on again will also change to indicate squares out of the game.
When the square is clicked it doesn't seem to perform any action.
Sorry, I know its trivial.
Thanks.
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class rooks extends JFrame implements MouseListener{
private final int BOARD_SIZE = 8;
private final int BOARD_SIZE_COLS = 8;
private final int BOARD_SIZE_ROWS = 8;
// private JTextField bottom = new JTextField("") ");
// private JLabel bannerl = new JLabel("The game");
// private JButton queens = new JButton(" Play Queens ");
private JButton rooks = new JButton(" Play Rooks ");
// private JButton bishops = new JButton(" Play Knights ");
private JButton[][] cboard = new JButton[BOARD_SIZE][BOARD_SIZE];
private JTextArea bottomtextarea = new JTextArea();
// constructor creating the chessboard
public rooks(){
this.setSize(500, 500);
this.setTitle("rooks");
// this.setIconImage();
// create JPanels and add JComponents
JPanel main = new JPanel(new BorderLayout());
this.setContentPane(main);
JPanel north = new JPanel();
north.setLayout(new GridLayout(1,3));
main.add(north, BorderLayout.NORTH);
// north.add(queens);
north.add(rooks);
// north.add(bishops);
JPanel south = new JPanel();
main.add(south, BorderLayout.SOUTH);
south.add(bottomtextarea);
bottomtextarea.setEditable(false);
bottomtextarea.setVisible(true);
// create grid (actual chessboard) and initialise each button with no char
JPanel chessBoard = new JPanel(new GridLayout(BOARD_SIZE, BOARD_SIZE));
main.add(chessBoard, BorderLayout.CENTER);
for (int i=0; i<BOARD_SIZE_ROWS; i++){
for(int j=0; j<BOARD_SIZE_COLS; j++){
cboard[i][j] = new JButton("");
chessBoard.add(cboard[i][j]);
// as it loops add colour to the board, if (i+j=even then white, otherwise black)
if ((i + j) % 2 == 0) {
cboard[i][j].setBackground(Color.black);
}
else {
cboard[i][j].setBackground(Color.white);
}
}
}
cboard[7][7].addMouseListener(this);
this.setResizable(false);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void mousePressed(MouseEvent e){
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
System.out.print("it has been clicked");
}
void saySomething(String eventDescription, MouseEvent e) {
}
}
Your code is working. I run it and when i click on the 7-7 square, (which is the one in the bottom right corner) i get the message: "it has been clicked".
Since you have added the mouse listener to only this square the code is behaving as expected.
But there are some things you should refactor:
Why do you define BOARD_SIZE, BOARD_SIZE_COLS, BOARD_SIZE_ROWS? If you only use quadratic game boards you only need BOARD_SIZE and if not then you dont need BOARD_SIZE.
Its convention to write the first letter of your classes in upper case. So it is Rooks instead of rooks
You need to add your listener to every square of the board instead of to only one
This should be enough to start with.
You are adding a MouseListener to the last button only, the JButton at cboard[7][7].
Why use a MouseListener and not an ActionListener for JButtons? This makes no sense.
Why not add an ActionListener to all JButtons inside of the for loop?
Related
I'm new to Swing and I'm trying to figure something out. I'm having difficulty explaining what I'm trying to do and I can't find anything online so I wrote a program demonstrating what I want to have happen. I use a CardLayout here:
import java.awt.event.*;
import java.io.*;
import java.awt.*;
import javax.swing.*;
public class Test extends JFrame implements ActionListener {
private CardLayout crd;
private int currentCard;
// Buttons
private JButton twoToCardOne;
private JButton threeToCardOne;
private JButton toCardTwo;
private JButton toCardThree;
// Container
private Container cPane;
// Panels
private JPanel cardOne;
private JPanel cardTwo;
private JPanel cardThree;
public Test() {
currentCard = 1;
cPane = getContentPane();
crd = new CardLayout();
cPane.setLayout(crd);
// Create buttons
twoToCardOne = new JButton("To Card One");
threeToCardOne = new JButton("To Card One");
toCardTwo = new JButton("To Card Two");
toCardThree = new JButton("To Card Three");
twoToCardOne.addActionListener(this);
threeToCardOne.addActionListener(this);
toCardTwo.addActionListener(this);
toCardThree.addActionListener(this);
// Create Panel (Card One)
cardOne = new JPanel();
cardOne.add(toCardTwo);
cardOne.add(toCardThree);
// Create Panel (Card Two)
cardTwo = new JPanel();
cardTwo.add(twoToCardOne);
// Create Panel (Card Three)
cardThree = new JPanel();
cardThree.add(threeToCardOne);
// Add Panels
cPane.add(cardOne);
cPane.add(cardTwo);
cPane.add(cardThree);
}
#Override
public void actionPerformed(ActionEvent e){
int target = 0;
if (e.getSource() == toCardThree){target = 3;}
else if (e.getSource() == toCardTwo){target = 2;}
else {target = 1;}
while (currentCard != target){
crd.next(cPane);
if (currentCard < 3){++currentCard;}
else {currentCard = 1;}
}
}
public static void main(String[] args){
Test test = new Test();
test.setSize(800, 500);
test.setVisible(true);
test.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
So, what I have here are buttons on various panels that all connect to the CardLayout. So, there are different buttons on the different panels that will move me panels when clicked on.
I have two questions/worries here:
If I wanted to make each JPanel its own class, how would I make this work? Since the buttons will be in a different class, I would no longer be able to control the CardLayout with actionPerformed.
My plan is to make this a hockey program where clicking on a button will take you to the player's profile with their stats and my plan was to have each individual player be a panel. This means that I will have A LOT of panels and buttons and I was wondering if there would be a better way to go about doing this. The only thing I've found online is to use CardLayout but this seems like it would not be a very optimal way of doing this.
Any help is much appreciated!
Note: Again, I'm very new to Swing so apologies if what I'm trying to explain is confusing or if I got something completely wrong.
I wanted to create a simple TicTacToe game in java by myself.
But currently I´m struggling with the first issue..
The GUI only displays the Gamefield itself (the "grid") OR the invisble buttons (when you click on them, it displays a X or O)
But never both of them?
I need the gamefield Image as the background and on that the buttons.. But I cant get it working.. I already tried using a third JPanel as the "main" panel with a FlowLayout and added the two other panels onto it.
I created some simple icons and a backround grid in paint.. icons are 200x200 and the grid 600x600 (same as my frame size)
"X-icon" : https://i.stack.imgur.com/tGlZM.png
"O-icon" : https://i.stack.imgur.com/mnoQd.png
"Background" : https://i.stack.imgur.com/BF5yW.png
I Hope anyone can help me out :)
import java.util.ArrayList;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class TicTacToe implements ActionListener{
ArrayList<JButton> buttons = new ArrayList<JButton>();
JFrame frame;
JPanel gamefield;
JPanel background;
JLabel backgroundLabel;
ImageIcon backgroundImage = new ImageIcon("C:\\Users\\adnan\\Programmieren\\Games\\TicTacToe\\field.png");
ImageIcon iconX = new ImageIcon("C:\\Users\\adnan\\Programmieren\\Games\\TicTacToe\\iconX.png");
ImageIcon iconO = new ImageIcon("C:\\Users\\adnan\\Programmieren\\Games\\TicTacToe\\iconO.png");
int player = 1;
void createGameField(){
background = new JPanel();
background.setPreferredSize(frame.getSize());
backgroundLabel = new JLabel(backgroundImage);
backgroundLabel.setSize(frame.getSize());
background.add(backgroundLabel);
gamefield = new JPanel();
gamefield.setLayout( new GridLayout(3,3,25,25));
createButtons();
frame.add(background);
frame.add(gamefield);
}
void createButtons(){
for(int index = 0; index<=9; index++){
buttons.add(new JButton());
if(index!=0){
buttons.get(index).setOpaque(false);
buttons.get(index).setContentAreaFilled(false);
buttons.get(index).setBorderPainted(false);
gamefield.add(buttons.get(index));
buttons.get(index).addActionListener(this);
}
}
}
public void actionPerformed(ActionEvent e){
if(e.getSource() instanceof JButton){
if(player==1){
System.out.println( ((JButton) e.getSource()).getText() + "was clicked by player "+player);
((JButton) e.getSource()).setEnabled(false);
((JButton) e.getSource()).setIcon(iconX);
player++;
}
else{
System.out.println( ((JButton) e.getSource()).getText() + "was clicked by player "+player);
((JButton) e.getSource()).setEnabled(false);
((JButton) e.getSource()).setIcon(iconO);
player--;
}
}
}
public TicTacToe(){
frame = new JFrame();
createGameField();
frame.setSize(600,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setTitle("TicTacToe");
frame.setResizable(false);
}
public static void main(String[] args) {
TicTacToe newGame = new TicTacToe();
}
}
A FlowLayout will ensure your components will be rendered side by side.
Instead, on the panel that hosts all your UI elements, override paintComponent() so it fills the background with your image. The component will still render it's children (the UI elements) on top of that.
Another chance would be to stack components on top of each other. The lower one would render your image, the upper one the UI - and do not forget to set opaque=false to the UI.
so I'm working on a game, the specifics of which don't matter much, but I'm using a board made with an 11x11 2d array of JPanels, then using JLabels as "pieces". I'd like to add a MouseListener to the panels, ex: When panels[10][5] is clicked; panels[10][5].add(redCircle). My issue is just a lack of knowledge about the syntax and use of mouselisteners in general, as my teacher doesn't teach much and I've been having a bit of trouble following online examples. I just need general help with the creation and implementation of such listeners, and any other opinions about my code are highly valued, as this is my first real program and I'm not very good at it.
Here's what I have now:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.border.BevelBorder;
public class GameFrame extends JFrame
{
private JPanel[][] panels = new JPanel[11][11];
private JPanel tilePanel;
private JLabel blackSquare;
private JLabel blackCircle;
private JLabel blackTriangle;
private JLabel redSquare;
private JLabel redCircle;
private JLabel redTriangle;
private int sideLength;
public GameFrame()
{
setSize(1000,750);
setResizable(false);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
sideLength = 11;
tilePanel = new JPanel();
tilePanel.setLayout(new GridLayout(sideLength,sideLength));
Color darkBlue = new Color(31,62,148);
Color darkGray = new Color(107,107,107);
for (int i = 0; i < 11; i++)
{
for (int j = 0; j < 11; j++)
{
panels[i][j] = new JPanel();
if (i%2 == j%2)
{
panels[i][j].setBackground(darkGray);
}
else
{
panels[i][j].setBackground(darkBlue);
}
panels[i][j].setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
tilePanel.add(panels[i][j]);
}
}
blackTriangle = new JLabel(new ImageIcon("blackTriangleUp.fw.png"));
blackSquare = new JLabel(new ImageIcon("blackSquare.fw.png"));
blackCircle = new JLabel(new ImageIcon("blackCircle.fw.png"));
redTriangle = new JLabel(new ImageIcon("redTriangleUp.fw.png"));
redSquare = new JLabel(new ImageIcon("redSquare.fw.png"));
redCircle = new JLabel(new ImageIcon("redCircle.fw.png"));
panels[0][0].add(blackTriangle);
panels[1][1].add(blackSquare);
panels[2][2].add(blackCircle);
panels[3][3].add(redTriangle);
panels[4][4].add(redSquare);
panels[5][5].add(redCircle);
add(tilePanel);
setVisible(true);
I recommend learning how to use search engines before saying you don't know how to do something. Part of programming is learning how to problem solve. But here is an idea on how you can get started with adding a mouse listener to a panel.
panels[i][j].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent me) {
System.out.println(me);
}
});
I'm creating a program that features a grid of 12 JPanels. When the "add image" button is pressed, an image appears in the first JPanel in the grid and a counter is incremented by one. From then onwards, every time the "add image" is clicked again, an image would be added to the next JPanel. For some reason, the button only adds an image to the first JPanel and then stops working. Here's the code I've got so far.
public class ImageGrid extends JFrame {
static JPanel[] imageSpaces = new JPanel[12];
int imageCounter = 0;
ImageGrid() {
this.setTitle("Image Grid");
setSize(750, 750);
setDefaultCloseOperation(EXIT_ON_CLOSE);
JPanel p3 = new JPanel();
p3.setLayout(new GridLayout(3, 4, 10, 5));
p3.setBackground(Color.WHITE);
p3.setOpaque(true);
p3.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
for (int j = 0; j < imageSpaces.length; j++) {
imageSpaces[j] = setImageSpace();
p3.add(imageSpaces[j]);
}
MyButtonPanel p1 = new MyButtonPanel();
add(p1, BorderLayout.SOUTH);
add(p3, BorderLayout.CENTER);
}
public JPanel setImageSpace() {
JPanel test;
test = new JPanel();
test.setOpaque(true);
test.setPreferredSize(new Dimension(100, 100));
return test;
}
class MyButtonPanel extends JPanel implements ActionListener {
final JButton addImage = new JButton("Add Image");
ImageIcon lorryPicture = new ImageIcon(ImageGrid.class.getResource("/resources/lorry.png"));
JLabel lorryImage = new JLabel(lorryPicture);
MyButtonPanel() {
add(addImage);
addImage.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == addImage) {
imageSpaces[imageCounter].add(lorryImage);
revalidate();
repaint();
imageCounter++;
}
}
}
public static void main(String[] args) {
ImageGrid test = new ImageGrid();
test.setVisible(true);
}
}
You should be revalidating and repainting the panel, (which is the containter being affected by the addition), not the frame
imageSpaces[imageCounter].add(lorryImage);
imageSpaces[imageCounter].revalidate();
imageSpaces[imageCounter].repaint();
Diclaimer: This may work as a simple fix, but also note that a component (in this case your JLabel lorryImage) can only have one parent container. The reason the above fix still works is because you don't revalidate and repaint the previous panel, the label was added to. So you may want to think about doing it correctly, and adding a new JLabel to each panel.
if (e.getSource() == addImage) {
JLabel lorryImage = new JLabel(lorryPicture);
imageSpaces[imageCounter].add(lorryImage);
imageSpaces[imageCounter].revalidate();
imageSpaces[imageCounter].repaint();
imageCounter++;
}
Disclaimer 2: You should add a check, to only add a label if the count is less than the array length, as to avoid the ArrayIndexOutOfBoundsException
Side Notes
Swing apps should be run from the Event Dispatch Thread (EDT). You can do this by wrapping the code in the main in a SwingUtilities.invokeLater(...). See more at Initial Threads
You could also just use a JLabel and call setIcon, instead of using a JPanel
So I am working on a GUI project for my class and I am a bit stuck. My problem has to do with my GUI aspect so I guess you could ignore the other methods having to do with the sorting. As of now, my main concern is just getting the GUI working. However, I keep running into an error, a null pointer exception to be exact:
Java.lang.NullPointerException
at SortDriver$SortCanvas.paint(SortDriver.java:253)
at SortDriver.init(SortDriver.java:197)
at sun.applet.AppletPanel.run(AppletPanel.java:436)
at java.lang.Thread.run(Thread.java:679)
After reading though my code, I think I narrowed it down to the my SortCanvas class. I never used it before but it was part of the stub my professor gave to us. That is to say that it works correctly and displays the image correctly but it looks like my implementation is incorrect however. Could someone help me figure out how to implement my SortCanvas "picture" correctly please? I read over the Java Docs for Canvas and I still don't understand what I am doing wrong. Here is my code:
import java.awt.*;
import java.applet.Applet;
import javax.swing.*;
import java.awt.event.*;
public class SortDriver extends Applet {
private int array[]; // array to be sorted
private int limit = 1000; // size of array to be sorted - you may have to make
// this bigger for faster sorts
private int largestNum; // need to know for color scaling purposes in paint()
// flag to tell paint() whether to paint a single location or the whole array
private enum PaintType {ALL, SINGLE};
private PaintType doPaint = PaintType.ALL;
private int index = -1; // index of single array location to be painted
//this listener object responds to button events
private ButtonActionListener buttonListener;
//button to start the sort
private JButton sortButton;
//basic window frame
private JFrame mainFrame;
//layouts
private BorderLayout initialLayout;
private FlowLayout northLayout;
private BorderLayout centerLayout;
private BorderLayout southLayout;
//basic panel for window frame
private JPanel initialPanel;
//panels for window layout
private JPanel northPanel;
private JPanel centerPanel;
private JPanel southPanel;
//panels for radio buttons
private JPanel radioOrderPanel;
private JPanel radioSortPanel;
private JPanel radioColorPanel;
//north panel header labels
private JLabel topTitleLabel;
private JLabel bottomTitleLabel;
private JLabel arraySizeLabel;
//radio buttons for list order (radioOrderButton)
//random set, ordered set, reverse set
private JRadioButton rOB1, rOB2, rOB3;
//radio buttons for sort type (radioSortButton)
//bubblesort, insertionsort, mergesort, quicksort
private JRadioButton rSB1, rSB2, rSB3, rSB4;
//radio buttons for color choice (radioColorButton)
//green, red, white, blue
private JRadioButton rCB1, rCB2, rCB3, rCB4;
//radio button groups for each radio panel
private ButtonGroup orderGroup, sortGroup, colorGroup;
//text field for size of the array
private JTextField arraySizeTextField;
// the picture of the sort will appear on this canvas
private SortCanvas picture;
private final int pictureWidth = 500; // size of the sort bar 1001
private final int pictureHeight = 50;
public void init() {
buttonListener = new ButtonActionListener();
array = new int[limit];
// load the array
largestNum = array[0] = (int) (Math.random()*1000000.0);
for (int i=1; i<limit; i++) {
array[i] = (int) (Math.random()*1000000.0);
// also keep track of the largest so that we can scale by it in paint()
if (array[i] > largestNum) largestNum = array[i];
}
//set up the main frame
mainFrame = new JFrame();
initialPanel = (JPanel) mainFrame.getContentPane();
initialLayout = new BorderLayout();
mainFrame.setResizable(false);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(650, 750);
initialPanel.setLayout(initialLayout);
//set up north panel
northPanel = new JPanel();
northLayout = new FlowLayout();
topTitleLabel = new JLabel("SortIt!");
bottomTitleLabel = new JLabel("A program by Mike Sevilla");
northPanel.setLayout(northLayout);
northPanel.add(topTitleLabel, BorderLayout.NORTH);
northPanel.add(bottomTitleLabel, BorderLayout.NORTH);
initialPanel.add(northPanel, BorderLayout.NORTH);
//set up center panel
centerPanel = new JPanel();
centerLayout = new BorderLayout();
centerPanel.setLayout(centerLayout);
//place array size label
arraySizeLabel = new JLabel("Size:");
//place array size text field w/ space for 5 chars
arraySizeTextField = new JTextField("", 5);
//place sort button
sortButton = new JButton("Sort it!");
// the listener is triggered when the button is clicked
sortButton.addActionListener(buttonListener);
centerPanel.setLayout(centerLayout);
//place sort bar on top of center layout
picture = new SortCanvas();
centerPanel.add(picture, BorderLayout.CENTER);
centerPanel.add(arraySizeLabel, BorderLayout.CENTER);
centerPanel.add(arraySizeTextField, BorderLayout.CENTER);
centerPanel.add(sortButton, BorderLayout.CENTER);
initialPanel.add(centerPanel, BorderLayout.CENTER);
//set up south panel
southPanel = new JPanel();
southLayout = new BorderLayout();
southPanel.setLayout(southLayout);
//set radio buttons and format layouts
radioOrderPanel = new JPanel();
radioOrderPanel.setLayout(new BoxLayout(radioOrderPanel, BoxLayout.Y_AXIS));
radioSortPanel = new JPanel();
radioSortPanel.setLayout(new BoxLayout(radioSortPanel, BoxLayout.Y_AXIS));
radioColorPanel = new JPanel();
radioColorPanel.setLayout(new BoxLayout(radioColorPanel, BoxLayout.Y_AXIS));
//define radio buttons
rOB1 = new JRadioButton("Random Order", true);
rOB1.addActionListener(buttonListener);
radioOrderPanel.add(rOB1);
rOB2 = new JRadioButton("In Order", false);
rOB2.addActionListener(buttonListener);
radioOrderPanel.add(rOB2);
rOB3 = new JRadioButton("In Reverse", false);
rOB3.addActionListener(buttonListener);
radioOrderPanel.add(rOB3);
rSB1 = new JRadioButton("Bubble Sort", true);
rSB1.addActionListener(buttonListener);
radioSortPanel.add(rSB1);
rSB2 = new JRadioButton("Insertion Sort", false);
rSB2.addActionListener(buttonListener);
radioSortPanel.add(rSB2);
rSB3 = new JRadioButton("Merge Sort", false);
rSB3.addActionListener(buttonListener);
radioSortPanel.add(rSB3);
rSB4 = new JRadioButton("Quick Sort", false);
rSB4.addActionListener(buttonListener);
radioSortPanel.add(rSB4);
rCB1 = new JRadioButton("Green", true);
rCB1.addActionListener(buttonListener);
radioColorPanel.add(rCB1);
rCB2 = new JRadioButton("Red", false);
rCB2.addActionListener(buttonListener);
radioColorPanel.add(rCB2);
rCB3 = new JRadioButton("White", false);
rCB3.addActionListener(buttonListener);
radioColorPanel.add(rCB3);
rCB4 = new JRadioButton("Blue", false);
rCB4.addActionListener(buttonListener);
radioColorPanel.add(rCB4);
//add radio buttons to a button group
orderGroup = new ButtonGroup();
orderGroup.add(rOB1);
orderGroup.add(rOB2);
orderGroup.add(rOB3);
sortGroup = new ButtonGroup();
sortGroup.add(rSB1);
sortGroup.add(rSB2);
sortGroup.add(rSB3);
sortGroup.add(rSB4);
colorGroup = new ButtonGroup();
colorGroup.add(rCB1);
colorGroup.add(rCB2);
colorGroup.add(rCB3);
colorGroup.add(rCB4);
initialPanel.add(southPanel, BorderLayout.NORTH);
picture.paint(picture.getGraphics());
mainFrame.setVisible(true);
}
// this object is triggered whenever a button is clicked
private class ButtonActionListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
// find out which button was clicked
Object source = event.getSource();
// start sort button was clicked
if (source == sortButton) {
// call the sort
doBubblesort();
}
// called when user hits return in text field
if (source == arraySizeTextField) {
int size = Integer.parseInt(arraySizeTextField.getText());
}
}
}
private void doBubblesort() {
int temp;
// this is just bubblesort
for (int i=0; i<limit-1; i++) {
for (int j=0; j<limit-1-i; j++) {
if (array[j]>array[j+1]) {
temp = array[j]; array[j] = array[j+1]; array[j+1] = temp;
// redraw only locations j and j+1
doPaint = PaintType.SINGLE; // try changing this to ALL and see what happens
index = j;
picture.paint(picture.getGraphics());
index = j+1;
picture.paint(picture.getGraphics());
}
}
}
}
class SortCanvas extends Canvas {
// this class paints the sort bar
SortCanvas() {
setSize(pictureWidth, pictureHeight);
setBackground(Color.white);
}
public void paint(Graphics g) {
if (doPaint == PaintType.ALL) {
// paint whole array - this takes time so it shouldn't be done too frequently
setBackground(Color.white);
g.setColor(Color.white);
g.fillRect(0, 0, pictureWidth, pictureHeight);
for (int i=0; i<limit; i++) {
// the larger the number, the brighter green it is
// green is between 0.0 and 1.0
// divide by the largest number to get a value between 0 and 1
float green = (float)(array[i]/(float)largestNum);
// clamp if necessary - it shouldn't be
if (green<0f) green = 0f;
if (green>1f) green = 1f;
g.setColor(new Color(0.0f, green, 0.0f));
// array location 0 is painted at left;
// array location limit-1 is painted to right
//this is a single vertical line in the bar
g.drawLine((int)(i*pictureWidth/limit), 0,
(int)(i*pictureWidth/limit), pictureHeight);
}
}
else {
// just paint one location on the bar
float green = (float)(array[index]/(float)largestNum);
if (green<0f) green = 0f;
if (green>1f) green = 1f;
g.setColor(new Color(0.0f, green, 0.0f));
g.drawLine((int)(index*pictureWidth/limit), 0,
(int)(index*pictureWidth/limit), pictureHeight);
}
}
}
}
This is not required;
picture.paint(picture.getGraphics());
getGraphics will return null if the component has not yet being painted itself. You should avoid using this method, it is simply a snap shot of the current components graphical state (which in your case is nothing)
You don't control the paint process, that's down to the repaint manager. You can request updates via the repaint methods. Have a read through Painting in AWT and Swing
You should avoid mixing heavy weight (Canvas) & light weight components (JFrame) together, where possible, you should stick with Swing components
Calling paint() directly can lead to unexpected behavior as you are see from this, use repaint() instead:
picture.repaint();