I am doing an autonomous code while refreshing things on the gui. (the logic is completely random right now).
When I call the button.doClick() method. It runs like it should have, but inside I have the button.setBackground(Color.red) method.
The problem being it doesn't set the background until the end. Do I have to do things with multiple threads? Thank you
EDIT: CODE ADDED
private void jButtonAutoActionPerformed(java.awt.event.ActionEvent evt){
//pick one here, but lets say it is number one
JB00.doClick();
}
private void JB00ActionPerformed(java.awt.event.ActionEvent evt){
//sends out shot and gets response
if(response.equals("Hit"){
JB00.setBackground(Color.red);
}
else{
JB00.setBackgorund(Color.Blue)
}
}
Everything works when I just click the button from the gui, So I do not think it is an issue with anything in the JB00 method.
Related
I am writing a trivia/quiz program in which the user answers questions and his/her answers are judged as correct or incorrect based on the screen coordinates they have clicked. For a clean design, I wish to load the questions using an external function, then attach a MouseListener to the screen object afterward.
My code currently resembles that given below.
void main() {
screen = new QuizScreen();
//load data for question
screen.awaitAnswer();
}
public class QuizScreen implements MouseListener{
//...variables...
//...blank methods for MousePressed, MouseReleased, etc...
public void mouseClicked(MouseEvent me){
//check if answer is right
}
public void awaitAnswer(){
QuizScreen.addMouseListener(this);
}
}
This code works fine for loading, allowing play of, and checking the answer to a single question. However, after the first question has been loaded, I want to be able to repeat the process -- to load ANOTHER (and possibly many more) questions -- by adding a loop to the "main" function. This is currently not possible, since I don't know how to get the MouseListener to stop listening to the user's clicks and return from awaitAnswer() to main().
How do I stop getting the MouseListener to listen to the user? How would I get out of an event-driven section of my code and back to an automatically executing section?
Remove the awaitAnswer method.
Create a (default) constructor for QuizScreen with statement addMouseListener(this);.
From your mouseClicked function, just execute a callback to your main program to create and destroy the QuizScreen
I'm making a small game and I've already implemented a save function in which the game is saved (by writing information to a new XML file). The saving takes a couple of seconds and I want to do the following: while the program is saving the game, I want to change the look of the JPanel, and when it is done saving, I want to go back to another page(show another JPanel).
I have the following code:
confirm.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e){
String fileNaam = saveGame.getText();
//This method changes the look of the panel
changePanel();
//This method saves the game
model.saveGame(fileNaam);
//This method takes the user back to a previous page
controller.viewTeamPage();
}
});
What happens is that the game is saved and the user is taken back to the teampage, but the panel is never changed. The changePanel() method does work, so that is not the problem but it seems like it is never executed. I was wondering if somebody knows how I can fix this.
EDIT:
private void changePanel () {
panel.removeAll();
panel.repaint();
panel.revalidate();
}
This is the method to change the look of the panel, for now I just remove everything on the panel to keep it simple.
Also, the saving is not done in a separate Thread, is that something I should look at?
EDIT 2: I fixed it by using a thread to save the game and return to the teampage after the saving is done. See the code below.
confirm.addActionListener(new ActionListener () {
#Override
public void actionPerformed(ActionEvent e){
final String fileNaam = saveGame.getText();
changePanel();
Thread t = new Thread (new Runnable () {
#Override
public void run() {
model.saveGame(fileNaam);
controller.viewTeamPage();
}
});
t.start();
}
});
If you are changing the same panel and not intializing a new panel then the problem i think is that you need to call the panel.revalidate or panel.repaint i think. I made a demo for a Procedural generation project and i had to do this to make my panel change.
Call your save game method from a new thread but don't "join" or "try" to wait for this thread to finish from inside the method actionPerformed();
Make the call to controller.viewTeamPage() after the save game thread is done saving the game. One simple way of doing that would be passing the "controller" object to the constructor of your custom thread so you can make that call after saving the game.
The step 1 is very important in this case because all the calls you are making in the method actionPerformed() are being made in the UI thread, preventing the entire UI from refreshing until the method returns. Even calling repaint() alone, in changePanel(), wont be enough because it just "schedules" a refresh on you panel that will only happen after actionPerformed() returns. If you put the most time consuming call in a separate thread however, the actionPerformed() returns quickly allowing the UI to be refreshed while the game saving thread is doing its job.
I have written a calculator in NetBeans and it functions perfectly. However, I have to actually click the buttons to insert numbers and am trying to remedy that with a KeyListener. I have all my numbers and function buttons set inside a JPanel named buttons. I have my display label in a JPanel named display.
I set my class to implement KeyListener and it inserted the KeyPressed, -Typed, and -Released methods; however I stuck from there. I'm not sure how to make my buttons actually listen for the KeyPressed event, and when it hears the event - activate the button. Also, my buttons are named by their number (e.g. the Zero Button is named zero, One button is one, etc.).
I've read that you actually have to implement a KeyListener somewhere by using: something.addKeyListener(something);
but I cannot seem to figure this out.
Can I get some help here? I'm new to Java and this is my first solo project. And let me know if I didn't provide enough information.
EDIT: Most of my code is NetBeans Generated and I cannot edit the initialization of the components which seems to be my problem I think?
My class declaration:
public class Calculator extends javax.swing.JFrame implements KeyListener {
//Creates new form Calculator
public Calculator() {
initComponents();
}
One of my buttonPressed actions (all identical with changes for actual number):
private void zeroActionPerformed(java.awt.event.ActionEvent evt) {
if (display.getText().length() >= 16)
{
JOptionPane.showMessageDialog(null, "Cannot Handle > 16 digits");
return;
}
else if (display.getText().equals("0"))
{
return;
}
display.setText(display.getText().concat("0"));
Main method supplied by NetBeans:
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Calculator().setVisible(true);
}
});
}
The initComponents() netbeans generated is absolutely massive (about 500 lines of code) and I cannot edit any of it. Let me know if I can supply any more helpful information.
Could there be an issue of Focus, and if so how can I resolve the issue?
Yes there is probably an issue with focus. That is why you should NOT be using a KeyListener.
Swing was designed to be used with Key Bindings. That is you create an Action that does what you want. Then this Action can be added to your JButton. It can also be bound to a KeyStroke. So you have nice reusable code.
Read the Swing tutorial on How to Use Key Bindings for more information. Key Bindings don't have the focus issue that you currently have.
I'm not sure I completely understand your question, and some code would help, but I'll take a crack, since it sounds like a problem I used to have a lot.
It sounds like the reason that your key presses aren't being recognized is that the focus is on one of the buttons. If you add keylisteners to the buttons, then you shouldn't have any problem.
In netbeans you can add keylisteners through the design screen really easily.
Here's a picture showing you how to add a keyPressed listener to a button in a jPanel.
private void jButton1KeyPressed(java.awt.event.KeyEvent evt) {
//Check which key is pressed
//do whatever you need to do with the keypressed information
}
It is nice to be able to write out the listeners yourself, but if you are just learning, then it is also nice to get as much help as possible.
This might not be the best solution, since you would have to add the listener for each of your buttons.
I'm trying to accomplish something very simple. First, load my layout (main.xml). Then wait 1 second, modify an image, wait 1 second and modify it to a third image. (My end goal is more complex, of course, but I can't even get this to work).
Basically, I get a black screen when the app loads. It stays that way until all the waiting is over, then it shows the final image. Here's my code:
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageCard[0] = (ImageView)findViewById(R.id.imageView11);
Thread.sleep(1000);
ImageCard[0].setImageDrawable(getResources().getDrawable(R.drawable.secondimage));
Thread.sleep(1000);
ImageCard[0].setImageDrawable(getResources().getDrawable(R.drawable.thirdimage));
ImageCard[0] is the image I'm trying to change. It loads in main.xml and shows fine if I remove the rest of the code.
If I change the sleep time to 5000, it then takes 10 seconds before it finally comes away from the black screen and shows the third image. This is how I know it's not just loading slow, but that it's actually waiting.
It's like it's not running sequentially. I'm no java expert, so I'm assuming I'm doing something dumb...
Thanks for any help!
I think you are blocking the UI Thead. Try Handler.postDelayed on a static Handler object.
Ok heres your problem, you can never do a sleep(...) when you are in the UIThread. The UIThread is never suppose to be locked up, it causes a lot of very bad things to happen in android. But there is a very easy way around it, just get off the UIThread and hop back on it when you need to. Heres what i would recommend:
public void onCreate(...)
{
super.onCreate(...);
myActivity.setContentView(R.layout.main);
new Thread(this).start();
}
public void run()
{
try
{
changeLayout(R.layout.main2);
Thread.sleep(5000);
changeLayout(R.layout.main3);
Thread.sleep(10000)
changeLayout(R.layout.main4);
}catch(Exception e){}
}
public void changeLayout(int id)
{
this.id = id;
myActivity.post(new Runnable()
{
public void run()
{
myActivity.setContentView(id);
}
});
}
private int id;
Of course with this example your class must implement Runnable to work. Only the UIThread can access the UI, no other thread can. Thats why you have to hop on and off the UIThread. Hope this worked!
Try adding ImageCard[0].invalidate() when you want it to draw.
I think Hovercraft Full of Eels is pointing you in the right direction. Essentially, you're not doing any multi-threading, you're telling the main thread to wait which means that it never completes the drawing. I'm not sure about Android, but Swing uses double-buffering by default (to avoid screen flashes), but that means that what is drawn, is actually drawn on to a buffer, not the window itself which is why you don't see anything. You could try disabling the double buffering (which Android is likely using) but that could cause other issues.
You might want to actually do multi-threading, or, I'm sure Android likely has a Timer component. If it does, I'd suggest you use it over Thread.sleep or actual multi-threading. Using a Timer you can have it fire an event after one second. That event will execute the other code.
do you have that code in constructor or in init() function? if yes, draw just the first picture and the Thread.sleep() function move after the place which the constructor or the init() function was called from.
then call repaint() function or something.
Each time the user presses a button a counter amountWrongGuessed gets incremented by 1. (works correctly with testing with System.prinln)
But how exactly do i get this to update in my label each time i press the button?
I have made a property that returns this value.
public int getAmountGuessed(){
return amountGuessed;
}
Next i try to get the value of the label, but the value always remains at 0.
lblAmountGuessDisplay = new JLabel(String.valueOf(hg.getAmountGuessed()));
private void UpdateComponents()
{
lblAmountGuessDisplay.setText(String.valueOf(hg.getAmountGuessed()));
}/*updateComponents*/
This example shows one way to update a label each time a button is clicked.
It might be a threading issue. Please take a look here.
I agree with Fredrick -- that you've not posted enough information for your question to be answerable and that it may be a reference issue -- that the JLabel you are changing is not the one that is displayed in the program. If you post more code, we'll have a better chance of giving your a decent answer. Also, this doesn't smell like a threading issue.
You need to add an ActionListener to your button. When the ActionListener is notified that the button is pressed, you can increment the counter and update the JLabel. The actionPerformed method will be triggered in the EDT, so you should be ok with threading.
lblAmountGuessDisplay.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
hg.incrementAmountGuessed();
lblAmountGuessDisplay.setText(String.valueOf(hg.getAmountGuessed()));
}
}
You will probably need to implement the incrementAmountGuessed method (which may be the root of your problem in the first place).