why isnt my thread starting? - java

I'm making a threaded app, and the main class is also the runnable class. for some reason, my thread WILL NOT START. any idea why? updateThread is the culprit...
here is the code:
package avtech.software.bitprice.display;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import avtech.software.bitprice.dialogs.*;
import avtech.software.bitprice.listeners.*;
#SuppressWarnings("serial")
public class Display extends JFrame implements Runnable {
/**
* variables
*/
private static final int WIDTH = 200, HEIGHT = 200;
private static double currentPrice = 0.0;
private static double pauseLength;
private static boolean running = false;
private static String greaterLess = "";
/**
* objects
*/
private static Display d;
private static Thread updateThread;
private static JLabel currentPriceLabel = new JLabel("Current Price: $" + currentPrice);
private static JTextField pullDelayArea = new JTextField("Price Pull Delay In Minutes...");
private static JTextField priceValueArea = new JTextField("Price You Are Waiting For...");
private static JButton update = new JButton("UPDATE DATA");
public Display() {
running = true; // program is now running
updateThread = new Thread(d); // create the local thread
/**
* create the frame
*/
setLayout(null);
setSize(WIDTH, HEIGHT);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("BitPrice");
/**
* set bounds of the components
*/
currentPriceLabel.setBounds(((WIDTH / 2) - (currentPriceLabel.toString().length() / 5)), 5, WIDTH, 50);
pullDelayArea.setBounds(10, 40, WIDTH - 25, 25);
priceValueArea.setBounds(10, 70, WIDTH - 25, 25);
update.setBounds(10, 100, WIDTH - 25, 25);
/**
* set up the listeners to the components
*/
pullDelayArea.addMouseListener(new PullDelayAreaListener(pullDelayArea));
pullDelayArea.addActionListener(new PullDelayAreaListener(pullDelayArea));
priceValueArea.addMouseListener(new PriceValueAreaListener(priceValueArea));
priceValueArea.addActionListener(new PriceValueAreaListener(priceValueArea));
update.addActionListener(new UpdateButtonListener());
/**
* add everything
*/
add(currentPriceLabel);
add(pullDelayArea);
add(priceValueArea);
add(update);
setLocationRelativeTo(null);
setVisible(true);
requestFocus();
/**
* start the update process
*/
System.out.println("hi");
updateThread.start();
}
/**
* everything that happens when the thread is updated, including updating
* the price label, and all that good stuff :)
*/
public static void update() {
/**
* make sure that there is data in the boxes taht is valid
*/
if (pullDelayArea.getText().equals("Price Pull Delay In Minutes...") || pullDelayArea.getText().equals("")) {
new MessageDialog(d, "Please enter a valid number into Price Pull Delay.");
}
if (priceValueArea.getText().equals("Price You Are Waiting For...") || priceValueArea.getText().equals("")) {
new MessageDialog(d, "Please enter a valid number into Price Value.");
}
// set the new price double from the website
// update the label
currentPriceLabel.setText("Current Price: $" + currentPrice);
currentPriceLabel.setBounds(((WIDTH / 2) - (currentPriceLabel.toString().length() / 5)), 5, WIDTH, 50);
currentPriceLabel.repaint();
/**
* check to see if the current value is what the client is waiting for
*/
String priceValueString = priceValueArea.getText();
double priceValue = Double.parseDouble(priceValueString);
}
/**
* this thread is checking the price of the Bitcoin, and will send out the
* notification if it reaches a certain price
*/
public void run() {
System.out.println("started");
/**
* initial pause, letting the client get all set up
*/
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
new ErrorDialog(this, "Error delaying the pull request. Please restart client.");
}
System.out.println("started");
while (running) {
update();
/**
* add a pause to not just destroy internet speeds, pause settable
* through the GUI
*/
try {
Thread.sleep((long) (pauseLength * 1000000)); // 1 million cause
// its in
// milliseconds
} catch (InterruptedException e) {
new ErrorDialog(this, "Error delaying the pull request. Please restart client.");
}
}
}
public static void main(String[] args) {
d = new Display();
}
}
Any help would be greatly appreciated.
PS: my internet is about to turn off, so responses may be delayed until tomorrow.

The short version is that the reference to d is not set until the constructor exits, so in your Display, you're creating a new thread object and passing the static reference to d, which is still presently null at that point. I would remove the new Thread(d) line, and the .start() line from the constructor, and simply invoke d.start() from the main method.

Related

Load a new JPanel into an existing JPanel

Good Afternoon, I'm back with another new-bee question. I am trying to create an program with a Star Trek inspired interface. I do not want to use dialog boxes with the program.
My interface is drawn on the screen in the fraMain class that my program calls first. It is shown below:
/**
* Troy Marker Enterprises
* TMEA-002-J: PHMS Database - Java
* Main Activity Code File
* Copyright (c) 2020 By Troy Marker Enterprises
* All Rights Under Copyright Reserved
*
* The code in this file was created for use with Troy Marker Enterprises Software.
* Use of this code by the public is strictly prohibited.
*/
package com.troymarkerenterprises;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Main program frame class
*/
public class fraMain extends JFrame implements ActionListener{
/**
* Program variable definitions
*/
private JPanel panMainMenu;
public static JPanel panSubMenu;
public static JPanel panTop;
private JPanel panBottom;
private int screenWidth;
private int screenHeight;
/**
* Method to start the program
* #param args - Method arguments
*/
public static void main(String[] args) {
new fraMain();
}
/**
* Method to draw the main window
*/
public fraMain() {
EventQueue.invokeLater(this::run);
}
/**
* Draw the main window
*/
private void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
GraphicsEnvironment graphics = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = graphics.getDefaultScreenDevice();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.setBackground(Color.BLACK);
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
screenWidth = gd.getDisplayMode().getWidth();
screenHeight = gd.getDisplayMode().getHeight();
this.panMainMenu = new ClassMainMenu(screenWidth, screenHeight);
panSubMenu = new ClassSubMenu(screenWidth, screenHeight);
panSubMenu.setVisible(false);
panTop = new ClassTopFrame(screenWidth,screenHeight);
this.panBottom = new ClassBottomFrame(screenWidth, screenHeight);
this.add(this.panMainMenu);
this.add(panSubMenu);
this.add(panTop);
this.add(panBottom);
this.pack();
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
device.setFullScreenWindow(this);
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
The screen is divided into four panels: panMainMenu, panSubMenu, panTop, and panBotom.
Each panel has its own class that draw its contents.
The panSubMenu is hidden until a button in the Main Menu is pressed, which show the sub menu. That part is working fine.
However, when I click the Exit Button on the main menu the only t hing that happens is the top frame turns white.
Here is my code for the Main Menu:
package com.troymarkerenterprises;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ClassMainMenu extends JPanel implements ActionListener {
final TMButton department;
final TMButton grade;
final TMButton user;
final TMButton exit;
private String MainMenuOption;
private final int screenHeight;
private final int screenWidth;
public ClassMainMenu(int screenWidth, int screenHeight) {
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.setBackground(Color.BLACK);
this.setBounds(0, 0, 160, screenHeight);
department = new TMButton("DEPARTMENT", "green");
grade = new TMButton("GRADES", "green");
user = new TMButton("USERS", "green");
exit = new TMButton("EXIT","blue");
department.addActionListener(this);
grade.addActionListener(this);
user.addActionListener(this);
exit.addActionListener(this);
this.add(department);
this.add(grade);
this.add(user);
this.add(exit);
}
public void deselectAll() {
for (Component c : this.getComponents()) {
if (c instanceof TMButton) {
((TMButton)c).setSelected(false);
}
}
}
#Override
public void actionPerformed(ActionEvent e) {
ClassTopFrame topFrame = new ClassTopFrame();
if(e.getSource()==department) {
this.deselectAll();
fraMain.panSubMenu.setVisible(true);
department.setSelected(true);
MainMenuOption = "Department";
}
if(e.getSource()==grade) {
this.deselectAll();
fraMain.panSubMenu.setVisible(true);
grade.setSelected(true);
MainMenuOption = "Grade";
}
if(e.getSource()==user) {
this.deselectAll();
fraMain.panSubMenu.setVisible(true);
user.setSelected(true);
MainMenuOption = "User";
}
if(e.getSource()==exit) {
this.deselectAll();
exit.setSelected(true);
fraMain.panTop = topFrame.exitProgram(fraMain.panTop);
//System.exit(0);
}
}
}
And the code for the top panel:
package com.troymarkerenterprises;
import javax.swing.*;
import java.awt.*;
import java.util.Objects;
public class ClassTopFrame extends JPanel{
private int screenWidth;
private int screenHeight;
public ClassTopFrame(int Width, int Height) {
screenWidth = Width;
screenHeight = Height;
this.setBackground(Color.BLACK);
this.setBounds(160, 0, screenWidth-160, screenHeight/2);
JLabel jl=new JLabel();
jl.setIcon(new javax.swing.ImageIcon(Objects.requireNonNull(getClass().getResource("/i_TMEA-0002-J_Logo.png"))));
this.add(jl);
}
public ClassTopFrame() {
}
public JPanel exitProgram(JPanel returnPanel) {
returnPanel.setBackground(Color.BLACK);
returnPanel.setBounds(160, 0, screenWidth-160, screenHeight/2);
JLabel jl=new JLabel();
jl.setIcon(new javax.swing.ImageIcon(Objects.requireNonNull(getClass().getResource("/i_TMEA-0002-J_Logo.png"))));
returnPanel.add(jl);
return returnPanel;
}
}
My plan is the have a new panel replace the top panel when the Exit button is pressed. I know the current code will only display the same contents of the panel when the button is clicked, it just wanted to put something the int exitProgram method for it to display.
As I said, I am a Java new-bee. I am not even sure if what I want to do is possible, I want to think so. Can anyone help me figure this out?
Thanks, Troy
Here is a picture of what I am looking to do:
The right side of the screen will show the sub menu when one of the buttons is clicked.
ADDITION:
In response to some help I have been getting, I am trying to switch to a card layout, but am having problem. I tried posting here, but it looks like adding the required information will make this post to long. So I uploaded everything to my GitHub account. The main changes I made are in this fine: https://github.com/troy-marker/TMEA-0002-J/blob/main/src/com/troymarkerenterprises/ClassBottomFrame.java

How could I add a refreshing timer to a JLabel using swing components

I am creating a Maze game and want a timer to be displayed on the gameStage.
I have tried using java.util but it requires me to get rid of my swing timer.How could i add a refreshing timer to game
This code is used to make the game frame which contains the button pane and the gameStage.
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
/**
* This class Holds the game pane that has the moving player. It also contains
* the GamePane
*
* #author 602052004
*
*/
public class GamePane extends JPanel implements ActionListener, KeyListener {// *change
// GamePane
// to
// GamePane
// This is were the game screen is made and the player is created.
static final long serialVersionUID = 1L;
JLabel player = new JLabel();
JLabel finish = new JLabel();
JFrame gameFrame;
int playerSpeed = 4;
int FPS = 40;
// This array holds my JLabels for the walls.I used it so that i can have a
// for loop with an index for the labels.
JLabel[] walls = new JLabel[3];
{
walls[0] = new JLabel();
walls[1] = new JLabel();
walls[2] = new JLabel();
}
private final Set<Integer> keys = new HashSet<>();
// The keys set holds the keys being pressed
public static void main(String[] args) {
// Open the GUI window
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
// Create a new object and
// run its go() method
new GamePane().go();
}
});
}
GamePane() {
// Run the parent class constructor
super();
// Allow the panel to get focus
setFocusable(true);
// Don't let keys change the focus
}
/**
* This method creates the gameFrame and sets its layout to a cardlayout.It
* then proceeds the set up the GameFrame.The gameFrame contains the button
* pane and the gameStage
*
* The walls are an array and are used to create an index which is then used
* for the collisions.I set up the walls location here
*/
protected void go() {
setLayout(new CardLayout());
// Setup the window
gameFrame = new JFrame();
// Add this panel to the window
gameFrame.setLayout(new CardLayout());
gameFrame.add(this, "main");
gameFrame.setContentPane(this);
// Set's the window properties
gameFrame.setTitle("main");
gameFrame.setSize(800, 600);
gameFrame.setResizable(false);
gameFrame.setLocationRelativeTo(null);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setVisible(true);
gameFrame.add(new ButtonPane(gameFrame), "buttons");
// Creates the new JPanel that will hold the game.
JPanel gamestage = new JPanel();
gamestage.setBackground(Color.darkGray);
gameFrame.add(gamestage, "game");
gamestage.setLayout(null);
// *Move the setup of the player and the timer under the walls
// Get a sample of collisions going so that i can do it over the weekend
// Setup the movable box
player.setBounds(25, 25, 20, 20);
player.setVisible(true);
player.setBackground(Color.red);
// Opaque makes the background visible
player.setOpaque(true);
// Setup the key listener
addKeyListener(this);
// Null layout allows moving objects!!!
gamestage.add(player);
// Set the timer
Timer tm = new Timer(1000 / FPS, this);
tm.start();
walls[0].setBounds(10, 15, 10, 480);// left height
walls[0].setVisible(true);
walls[0].setBackground(Color.white);
walls[0].setOpaque(true);
gamestage.add(walls[0]);
walls[1].setBounds(10, 10, 490, 10);// top width
walls[1].setVisible(true);
walls[1].setBackground(Color.white);
walls[1].setOpaque(true);
gamestage.add(walls[1]);
// wall3.setBounds(x, y, width, height);
walls[2].setBounds(10, 100, 100, 10);
walls[2].setVisible(true);
walls[2].setBackground(Color.white);
walls[2].setOpaque(true);
gamestage.add(walls[2]);
finish.setBounds(30, 455, 20, 20); // *make the game change to the main
// screen when finished
// Add a timer
finish.setVisible(true);
finish.setBackground(Color.LIGHT_GRAY);
finish.setOpaque(true);
gamestage.add(finish);
}
/**
* Check if two JLabel objects are touching
*
* #param a
* The first JLabel
* #param b
* The second JLabel
* #return true if the JLabels are touching
*/
public boolean areColliding(JLabel a, JLabel b) {
return a.getBounds().intersects(b.getBounds());
}
/**
* this method makes the player move. It takes the players speed and
* subtracts or adds the player speed to the current position of the player.
* It also figures out were the player is at currently aswell.
*
* #param arg0
*/
#Override
public void actionPerformed(ActionEvent arg0) {
// Move up if W is pressed
if (keys.contains(KeyEvent.VK_W)) {
player.setLocation(player.getX(), player.getY() - playerSpeed);
}
// Move right if D is pressed
if (keys.contains(KeyEvent.VK_D)) {
player.setLocation(player.getX() + playerSpeed, player.getY());
}
// Move down if S is pressed
if (keys.contains(KeyEvent.VK_S)) {
player.setLocation(player.getX(), player.getY() + playerSpeed);
}
// Move left if A is pressed
if (keys.contains(KeyEvent.VK_A)) {
player.setLocation(player.getX() - playerSpeed, player.getY());
}
for (int i = 0; i < walls.length; i++) {
// I created a for loop instead
// of a do loop because the for
// loop would have been a lot
// simpler to manage
if (areColliding(walls[i], player)) { // Reposition the target
int newX = (int) (25);
int newY = (int) (25);
player.setLocation(newX, newY);
}
}
if (areColliding(finish, player)) {
// Reposition the target
int newX = 25;
int newY = 25;
player.setLocation(newX, newY);
CardLayout layout = (CardLayout) gameFrame.getContentPane()
.getLayout();
layout.show(gameFrame.getContentPane(), "buttons");
}
}
#Override
public void keyPressed(KeyEvent e) {
// Add the key to the list
// of pressed keys
if (!keys.contains(e.getKeyCode())) {
keys.add(e.getKeyCode());
}
}
#Override
public void keyReleased(KeyEvent e) {
// Remove the key from the
// list of pressed keys
keys.remove((Integer) e.getKeyCode());
}
#Override
public void keyTyped(KeyEvent e) {
}
}
this code shows the game pane when the buttob is pressed
/**
* This pane contains the button and sets up the button pane
*/
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class ButtonPane extends JPanel {
private JButton startBTN;// Calls the JButton
JFrame game;
public ButtonPane(JFrame g) {
game = g;
setLayout(new GridBagLayout());
setBackground(Color.gray);// Sets the menu stages color blue
startBTN = new JButton("Game");// Creates a new button
add(startBTN);// Adds the button on the startStage
startBTN.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (game.getContentPane().getLayout() instanceof CardLayout) {
CardLayout layout = (CardLayout) getParent().getLayout();
layout.show(game.getContentPane(), "game");
}
}
});
}
}
Okay, so you have a Timer already, which is ticking away at 1000/FPS times a second, cool. All you really need is away to calculate the difference between two points in time, which, amazingly, is very simple.
Start by defining a "start time"
private Instant startTime;
This will be null till you need it. When you want to start the timer, use startTime = Instant.now();
When startTime != null, you want to calculate the difference between it and now...
Duration runningTime = Duration.between(startTime, Instant.now());
This now tells you how long the timer has been running for.
Next, we need to make some decisions, like what to do when the timer runs out, but for that, we actually need to know how lone the timer should run for...
private Duration timeOutDuration = Duration.ofSeconds(5);
This just sets up a timeout of 5 seconds, you can use what ever range you want.
This then allows us to calculate the remaining time of the timer...
Duration timeRemainig = timeOutDuration.minus(runningTime);
and then to make decisions about what to do...
if (timeRemainig.isNegative() || timeRemainig.isZero()) {
// Time has run out...
// startTime = null; // stop the timer
} else {
// Update the UI
}
The date/time API introduced in Java 8 is incredibly powerful and flexible (and a lot of fun, when you get your head around it)
A solution might start looking something like...
private Duration timeOutDuration = Duration.ofSeconds(5);
private Instant startTime; // Set this when you're ready to start the timer
#Override
public void actionPerformed(ActionEvent arg0) {
if (startTime != null) {
Duration runningTime = Duration.between(startTime, Instant.now());
Duration timeRemainig = timeOutDuration.minus(runningTime);
if (timeRemainig.isNegative() || timeRemainig.isZero()) {
// Time has run out...
// startTime = null; // stop the timer
} else {
// Update the UI
}
}
Formatting a Duration for output generally looks something like...
long hours = timeRemainig.toHours();
long mins = timeRemainig.minusHours(hours).toMinutes();
// Or if you're lucky enough to be using Java 9+
//String formatted = String.format("%dhrs %02dmins", duration.toHours(), duration.toMinutesPart());
String formatted = String.format("%dhrs %02dmins", hours, mins);
or simular, depending on how you want it formatted
Why use this approach instead of some "counter"
Simple, it's (super) accurate. Timer only guarantees a "at least" interval, that is, it will delay no less then the value apply, this means that it's possible to introduce a "drag" over time, where a counter would fall out of sync. Sure, over a short period of time, it's probably not a big deal, but since there is a (super easy) better way to do it, why not make use of it.
The solution is also super flexible, applied to a broad spectrum of similar issues. I use the above concept as part of time based animations, which generally produce a far superior, overall, result.

Cannot find symbol when using a array in an if statement with for loop

I am getting a cannot find symbol- method occupant(int) at the bottom of the code (line 150) probably missing something simple but cannot fix it. Only need help with this part, the program is far from incomplete.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Accommodation extends JFrame
implements ActionListener
{
/** Window layout constants (these need to be "static" to be referred to in main) */
private static final int panelWidth = 700;
private static final int panelHeight = 300;
/** The apartment block data structure */
private final int apartments = 10; // Total number of apartments (numbered from 1 for the user, but from 0 in the array!)
private String[] occupant; // Occupant information: one string per apartment
private int selectedApartment; // To identify the currently selected apartment
/** Configuration constants for the display */
private final int aptHeight = 40; // Dimensions for individual apartment rectangles
private final int aptWidth = 50;
/** A useful colour */
private final Color emptyColor = Color.green;
/** Graphical interface components */
private JButton next; // Dummy selection button
/** The drawing panel. */
private JPanel panel;
/**
* The main program launcher for the Accommodation application.
*
* #param args The command line arguments (ignored here).
*/
public static void main( String[] args )
{
Accommodation frame = new Accommodation();
frame.setSize( panelWidth+40, panelHeight+200 );
frame.setUpAccommodation();
frame.setUpGUI();
frame.setVisible( true );
frame.setTitle("Accomodation");
frame.setLocationRelativeTo(null);
} // End of main
/** Organizes overall set up of the apartment block details at launch time. */
private void setUpAccommodation()
{
// Create the occupant array and fill in first two apartments.
// The other elements need to contain "Empty"
occupant = new String[apartments];
occupant[0] = "Luke Skywalker"; // Occupants in apartments 1 and 2
occupant[1] = "The Hulk";
occupant[2] = "Empty";
occupant[3] = "Empty";
occupant[4] = "Empty";
occupant[5] = "Empty";
occupant[6] = "Iron Man";
occupant[7] = "Empty";
occupant[8] = "Empty";
occupant[9] = "Empty";
selectedApartment = 0; // Apartment 1 initially selected
} // End of setUpAccommodation
/** Organizes overall set up of the GUI at launch time. */
private void setUpGUI()
{
// Now set up the initial GUI: window, button, graphics panel and background colours.
setDefaultCloseOperation( EXIT_ON_CLOSE );
Container window = getContentPane();
window.setLayout( new FlowLayout() );
window.setBackground( Color.gray );
// Set up the next button
next = new JButton("Next");
window.add(next);
next.addActionListener(this);
// Set up the drawing panel
panel = new JPanel()
{
// paintComponent is called automatically when a screen refresh is needed
public void paintComponent(Graphics g)
{
// g is a cleared panel area
super.paintComponent(g); // Paint the panel's background
paintScreen(g); // Then the required graphics
}
};
panel.setPreferredSize( new Dimension( panelWidth, panelHeight ) );
panel.setBackground( Color.white );
window.add( panel );
} // End of setUpGUI
/**
* Handle button clicks
*
* #param e Information about the button click
*/
public void actionPerformed( ActionEvent e )
{
// In this template there is only a Next button.
// In the second stage (up to 69 marks) it should causes the display to be updated
// to show the details of the next occupant of the apartment block.
// Here is an indication of what it should do:
// Adjust the selected apartment indicator
selectedApartment++;
// And refresh the display
repaint();
} // End of actionPerformed
/**
* Display the apartment block, and the details of the occupant of the selected apartment.
*
* #param g The Graphics area to be drawn on, already cleared.
*/
private void paintScreen( Graphics g )
{
// Now draw the display
displayStatus(g);
displayBlock(g);
} // End of paintScreen
/** Display information about the currently selected apartment */
private void displayStatus(Graphics g)
{
// Just information about apartment 1 in this template
g.setColor(Color.black);
g.drawString(occupant[0], 190, 70);
} // End of displayStatus
/** Draw the apartments themselves: boundary, empty/occupied colouring, number */
private void displayBlock(Graphics g)
{
for(int i = 0; i < 10; i++)
{
if (occupant(i).equals("Empty"))
{
g.setColor(Color.green);
g.fillRect(150+(i*50), 120, aptWidth, aptHeight); //Sets the rectangle red to show the room is occupied
}
else
{
g.setColor(Color.red);
g.fillRect(150+(i*50), 120, aptWidth, aptHeight); //Sets the rectangle green to show the room is free
}
g.setColor(Color.black);
g.drawRect(150+(i*50), 120, aptWidth, aptHeight);
// Draws the numbers in the Corresponding boxes
g.setColor(Color.black);
g.drawString(Integer.toString(i+1), 150+(i*50)+15, 120+25);
}
//Drawing the key allowing the user to see what the colours refer to
g.setFont(new Font("TimesRoman", Font.PLAIN, 14));
g.drawString("Key", 20,120);
g.drawString("Occupied",60,150);
g.drawString("Empty", 60, 170);
// Drawing the boxes to show what the colours mean in the key
g.setColor(Color.red);
g.fillRect(20, 130, 25, 25);
g.setColor(Color.black);
g.drawRect(20, 130, 25, 25);
g.setColor(Color.green);
g.fillRect(20,150,25,25);
g.setColor(Color.black);
g.drawRect(20,150,25,25);
} // End of displayBlock
} // End of Accommodation
occupant(i) should be occupant[i] because it's an array and not a method
occupant(i)
This is a method call
occupant[i]
this is element i in array occupant

Jslider displaying values of array

I' m trying to change the displayed value(selected variable) to what the slider is in line with. The main issue is the worksheet I'm working from specifies this
"The displaySelected method is responsible for displaying just the selected item. Look at it,and work out why it is always element 0 that is displayed – it is something quite simple, and not something complex."
I understand that the change of display requires the variable selected, I've already tried ( g.drawString(names[selected], 200, 150);) but the issue with this is that it only does value 4 of the array and resets to 0 once moved and doesn't, I know that I have to change the value of selected then, I've tried selected = selector.getValue(); but I'm returned with a null error.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
/**
* A simple address database for Practical 5B
* Demonstrates arrays, graphics, selection.
*/
public class Addresses extends JFrame
implements ChangeListener
{
/**
* Frame coordinate constants
*/
private static final int FRAME_X = 200;
private static final int FRAME_Y = 200;
/**
* Frame size constants
*/
private static final int FRAME_WIDTH = 500;
private static final int FRAME_HEIGHT = 400;
/**
* The slider for selecting an address record (selectable 0 to size-1).
*/
private JSlider selector;
/**
* Array to hold the database.
*/
private String[] names;
/**
* To indicate which entry is currently selected.
*/
private int selected;
/**
* The drawing panel for display of information.
*/
private JPanel panel;
/**
* Drawing panel size constants
*/
private final int PANEL_WIDTH = 400;
private final int PANEL_HEIGHT = 300;
/**
* The main program launcher for the Addresses class.
*
* #param args The command line arguments (ignored here).
*/
public static void main( String[] args )
{
Addresses frame = new Addresses();
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setUpData(); // Initial data set-up
frame.createGUI(); // Initial GUI set-up
frame.setVisible( true );
}
/**
* Sets up the graphical user interface.
*/
private void createGUI()
{
setDefaultCloseOperation( EXIT_ON_CLOSE );
Container window = getContentPane();
window.setLayout( new FlowLayout() );
// Slider for selecting an address entry
selector = new JSlider(JSlider.VERTICAL, 0, 0, 0);
// Note: the useable range of the slider is 0 - 0 at the moment!
window.add(selector);
selector.addChangeListener(this);
// Graphics panel for displaying the address list
panel = new JPanel()
{
// paintComponent is called automatically when a screen refresh is needed
public void paintComponent(Graphics g)
{
// g is a cleared panel area
super.paintComponent(g); // Paint the panel's background
paintScreen(g); // Then the required graphics
}
};
panel.setPreferredSize( new Dimension( PANEL_WIDTH, PANEL_HEIGHT ) );
panel.setBackground( Color.white );
window.add( panel );
}
/**
* Helper method to set up the array data, and the associated variable selected,
* with their initial configuration.
*/
private void setUpData()
{
// All the data is "built-in": set it up here - just one entry at the moment
names = new String[6]; // Create the array with space for one entry
names[0] = "James"; // The entry
names[1] = "Connor";
names[2] = "Alfred";
names[3] = "Billy";
names[4] = "Jack";
names[5] = "Chris";
selected = names.length-1; // Indicate that entry 0 is selected
}
/**
* This methods redraws the screen.
*/
private void paintScreen(Graphics g)
{
displayList(g);
displaySelected(g);
}
/**
* Display all the elements of array names in a column on the screen.
*/
private void displayList(Graphics g)
{
int y = 100; // Top y coordinate of the column
g.setColor(Color.black);
/*
g.drawString(names[0], 20, y);
g.drawString(names[1], 20, y+25);
g.drawString(names[2], 20, y+50);
g.drawString(names[3], 20, y+75);
g.drawString(names[4], 20, y+100);
g.drawString(names[5], 20, y+125);
*/
for (int i = 0; i< names.length; i++)
g.drawString(names[i], 20, y+25*i);
}
/**
* Display the single element of array names that is currently selected by the slider.
*/
private void displaySelected(Graphics g)
{
g.setColor(Color.black);
g.drawString("Current selection is:", 200, 135);
g.drawString(names[selected], 200, 150);
}
/**
* Reacts to adjustment of the slider.
* Notes the new selector setting, then forces screen refresh.
*/
public void stateChanged( ChangeEvent e )
{
// selector has been adjusted: record the new setting
selected = selector.getValue();
repaint(); // Refresh the screen
}
}
You never set the maximum value for the slider. That's why you can't move it. Make this change to your code, then you will be able to debug the rest of this program.
selector = new JSlider(JSlider.VERTICAL, 0, names.length-1 /* HERE */ , 0);

How can I solve different types of collection

There are a lot of questions in here.
I wrote a code this far, but hard to write in code in some methods.
1.I don't know how to do setDice(List dice) method. If I use for(JButton b:dice), then it keeps giving me compile-time error.
2.Help me to implement setWordIsCorrect(boolean isCorrect) & clearCurrentWord() methods
Make sure you cannot touch other methods and modify the method signatures.
package cse1030.games.boggle;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
/**
* The view for the Boggle app. Please see the lab for a detailed description of
* the view.
*
* #author CSE1030_F13_14
*
*/
public class BoggleView extends JFrame implements ActionListener {
/**
* The string representing the clear command. The view listens for its own
* clear event.
*/
public static final String CLEAR_COMMAND = "clear";
/**
* The string representing the roll command.
*/
public static final String ROLL_COMMAND = "roll";
/**
* The string repesenting the submit command.
*/
public static final String SUBMIT_COMMAND = "submit";
/**
* A list that contains references to the buttons representing the dice.
*/
private List<JButton> diceButtons;
/**
* The text field that displays the current word.
*/
private JTextField word;
/**
* The set of dice buttons that have already been used to form the current
* word.
*/
private Set<JButton> usedButtons;
/**
* The text area that displays the list of correct words.
*/
private JTextArea correctWords;
/**
* The text area that displays the list of incorrect words.
*/
private JTextArea incorrectWords;
/**
* Create the Boggle user interface. Please see the lab for a detailed
* description of the user interface.
*
* #param controller
* the controller that listens for submit and roll events
*/
public BoggleView(BoggleController controller) {
super("Boggle");
this.diceButtons = new ArrayList<JButton>();
this.usedButtons = new HashSet<JButton>();
JPanel contentPanel = new JPanel();
JPanel leftPanel = this.makeLeftPanel();
JPanel rightPanel = this.makeRightPanel();
JPanel middlePanel = this.makeMiddlePanel(controller);
contentPanel.add(leftPanel);
contentPanel.add(middlePanel);
contentPanel.add(rightPanel);
this.setContentPane(contentPanel);
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
* Creates the panel that contains the buttons representing the Boggle dice.
*
* #return the <code>JPanel</code> that contains the buttons representing the
* Boggle dice.
*
*/
private JPanel makeDicePanel() {
Font font = new Font(Font.SANS_SERIF, Font.BOLD, 32);
JPanel p = new JPanel();
p.setLayout(new GridLayout(4, 4));
p.setMaximumSize(new Dimension(450, 450));
for (int i = 0; i < 16; i++) {
JButton b = new JButton("" + i);
b.setPreferredSize(new Dimension(100, 100));
b.setMaximumSize(b.getSize());
b.setFont(font);
b.setBackground(Color.WHITE);
b.setActionCommand("" + i);
b.addActionListener(this);
p.add(b);
this.diceButtons.add(b);
}
return p;
}
/**
* Returns the buttons surrounding the button representing the die that was
* last selected by the user. These are the buttons that could legally be
* chosen next by the user when forming a word.
*
* #param idx
* the index of the button representing the die that was last
* selected by the user
* #return the buttons surrounding the last selected die
*/
private List<JButton> findNeighbors(int idx) {
List<JButton> neighbors = new ArrayList<JButton>();
final int row = idx / 4;
final int col = idx % 4;
final int minRow = Math.max(0, row - 1);
final int maxRow = Math.min(3, row + 1);
final int minCol = Math.max(0, col - 1);
final int maxCol = Math.min(3, col + 1);
for (int i = minRow; i <= maxRow; i++) {
for (int j = minCol; j <= maxCol; j++) {
int n = i * 4 + j;
if (n != idx) {
neighbors.add(this.diceButtons.get(n));
}
}
}
return neighbors;
}
/**
* Disable all of the buttons representing the dice.
*/
private void disableAllDiceButtons() {
for (JButton b : this.diceButtons) {
b.setEnabled(false);
}
}
/**
* Enable all of the buttons representing the dice.
*/
private void enableAllDiceButtons() {
for (JButton b : this.diceButtons) {
b.setEnabled(true);
b.setBackground(Color.WHITE);
}
}
/**
* Responds to events from the view. This method responds to an event where
* the action command is either <code>BoggleView.CLEAR_COMMAND</code>,
* <code>BoggleView.ROLL_COMMAND</code>, or
* <code>BoggleView.SUBMIT_COMMAND</code>.
*
* #param event
* an event emitted by the view
*
* #see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
#Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals(CLEAR_COMMAND)) {
this.clearCurrentWord();
} else if (command.equals(ROLL_COMMAND)) {
this.clearCorrectWords();
this.clearIncorrectWords();
this.clearCurrentWord();
} else {
try {
int d = Integer.parseInt(command);
JButton b = this.diceButtons.get(d);
b.setBackground(Color.BLUE);
this.word.setText(this.word.getText() + b.getText());
this.usedButtons.add(b);
this.disableAllDiceButtons();
List<JButton> neighbors = findNeighbors(d);
for (JButton n : neighbors) {
if (!this.usedButtons.contains(n)) {
n.setEnabled(true);
}
}
} catch (NumberFormatException ex) {
}
}
}
/**
* Creates the left-hand panel. Please see the lab for a detailed description
* of the panel's contents.
*
* #return the left-hand <code>JPanel</code> with all of its necessary
* components
*/
private JPanel makeLeftPanel() {
// create the panel
JPanel p = new JPanel();
// set the layout for the panel to use a BoxLayout;
// BoxLayout stacks its components vertically or horizontally
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
// create a label for the list of correct words and add it to the panel
JLabel label = new JLabel("Correct Words");
p.add(label);
// create the list of correct words, remove the ability for the user to
// edit the list, and add it to the panel
this.correctWords = new JTextArea(30, 16);
this.correctWords.setEditable(false);
p.add(this.correctWords);
return p;
}
/**
* Creates the right-hand panel. Please see the lab for a detailed description
* of the panel's contents.
*
* #return the right-hand <code>JPanel</code> with all of its necessary
* components
*/
private JPanel makeRightPanel() {
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
JLabel label = new JLabel("Incorrect Words");
p.add(label);
this.incorrectWords = new JTextArea(30, 16);
this.incorrectWords.setEditable(false);
p.add(this.incorrectWords);
return p;
}
/**
* Creates the middle panel. Please see the lab for a detailed description of
* the panel's contents.
*
* #return the middle <code>JPanel</code> with all of its necessary components
*/
private JPanel makeMiddlePanel(BoggleController controller) {
JPanel p = new JPanel();
// 1. set the layout to a BoxLayout (same as makeLeftPanel)
p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
// 2. make the dice panel and add it to p; there is a method that makes the
// dice panel for you!
p.add(makeDicePanel());
// 3. make the contorl panel and add it to p; there is a method that makes
// the control for you!
p.add(makeControlPanel(controller));
return p;
}
/**
* Creates the panel that contains the clear, submit, and re-roll buttons, and
* the text field for the word.
*
* #return the <code>JPanel</code> that contains the controls below the dice
*
*/
private JPanel makeControlPanel(BoggleController controller) {
JPanel p = new JPanel();
// You don't need to create a lay out. JPanel uses FlowLayout if you don't
// specify a lay out.
// Make the clear button
JButton clear = new JButton("Clear");
// Set its action command to the clear command
clear.setActionCommand(BoggleView.CLEAR_COMMAND);
// Add this as an action listener; see the actionPerformed method above.
// The controller does not need to listen to this button because the model
// is not needed to clear the current word.
clear.addActionListener(this);
// Add the clear button to the panel.
p.add(clear);
// Make a text field that can display a 16 character word
this.word = new JTextField(16);
// Disable editing by the user.
this.word.setEditable(false);
// Add the text field to the panel.
p.add(this.word);
// - make the submit button
JButton submit = new JButton("Submit");
// - set its action command
submit.setActionCommand(BoggleView.SUBMIT_COMMAND);
// - add the controller as an action listener
submit.addActionListener(controller);
// - add the submit button to the panel
p.add(submit);
// - make the re-roll button
JButton roll = new JButton("Re-roll");
// - set its action command
roll.setActionCommand(BoggleView.ROLL_COMMAND);
// - add the controller as an action listener
roll.addActionListener(controller);
// - add this as an action listener
roll.addActionListener(this);
// - add the re-roll button to the panel
p.add(roll);
return p;
}
/**
* Get the current string that is in the word text field.
*
* #return the current string that is in the word text field
*/
public String getWord() {
// change the return statement below
return this.word.getText();
}
/**
* Sets the text on the buttons representing the dice.
*
* #pre. <code>dice.size() == 16</code>
*
* #param dice
* a list of 16 Boggle dice
*/
public void setDice(List<BoggleDie> dice) {
**for (JButton b : dice) {
b.setText(b.getText());
}**
}
/**
* Causes the view to update after the submitted word is evaluated for
* correctness. If <code>isCorrect == true</code> then the current word is
* added to the list of correct words. If <code>isCorrect == false</code> then
* the current word is added to the list of incorrect words. In both cases,
* the current word is cleared.
*
* #param isCorrect
* <code>true</code> if the current word has been determined to be a
* legal Boggle word, <code>false</code> otherwise
*/
public void setWordIsCorrect(boolean isCorrect) {
if(isCorrect == true) {
} else {
}
}
/**
* Clears the list of correct words.
*/
private void clearCorrectWords() {
this.correctWords.setText(null);
}
/**
* Clears the list of incorrect words.
*/
private void clearIncorrectWords() {
this.incorrectWords.setText(null);
}
/**
* Clears the current word and prepares the view to accept a new word. This
* requires re-enabling all of the dice buttons and clearing the set
* this.usedButtons
*/
private void clearCurrentWord() {
// 1. enable all of the dice buttons; there is a method that does this for
// you
enableAllDiceButtons();
// 2. set the text of this.word to the empty string
// 3. remove all of the buttons from this.usedButtons
}
public static void main(String[] args) {
BoggleView v = new BoggleView(null);
v.setVisible(true);
}
}
I will appreciate you if you can help me how to do these methods...
You need to use for (BoggleDie b : dice) or (List<JButton> dice). If the list contains BoggleDie, you must use the former.
You may want to have a list of JButtons instead
public void setDice(List<JButton> dice) {
for (JButton b : dice) {
b.setText(b.getText());
}
}
You need to make sure you actually initialize the list and add JButtons to the list before you can do anything with it.
List<JButton> diceButtons = new List<JButton>();
for (int i = 0; i < 16; i++){
diceButton.add(new JButton("" + i + 1);
}
Try this for your method
public void setDice(){
for (int i = 0; i < 16; i++){
diceButtons.add(new JButton("SomeText");
}
}
Edit: with BoggleDie class
public class BoggleDie{
int value;
public BoggleDie(int value){
this.value = value;
}
}
public class BoggleView ... {
...
private List<BoggleDie> dice = new List<BoggleDie>();
private List<JButton> diceButton = new ArrayList<JButton>();
public BoggleView(){
for (int i = 0; i < 16; i++){
dice.add(new BoggleDie(i)); // or whatever value you want for the die
}
setDice(dice);
}
public void setDice(List<BoggleDie> dice) {
for (BoggleDie b : dice) {
diceButtons.add(new JButton(b.value));
}
}
}
Change the code as follows
public void setDice(List<JButton> dice) {
for (JButton b : dice) {
b.setText(b.getText());
}
}

Categories