I have the space bar set up to advance the "scene" of a game I am creating. The function is as follows (the Key Handler and everything are all properly implemented):
public void KeySPACE() {
beginGame(player, "Map0");
}
beginGame, for reference, looks like this:
public void beginGame (Player player, String map) {
player.createProfile();
this.map = mapFile.getMap(map);
this.map = findSpawnPoint();
this.arena = this.map.arena;
this.enemyPath = new EnemyPath(this.map);
this.scene = 1; //Game playing state
this.wave.waveNumber = 0;
}
My game starts at a menu screen, which you can advance to the game screen by pressing space (i.e. set scene = 1). However, I only want the space bar to do this once. The problem is, the user can inadvertently reset an active game by pressing the space bar.
Any ideas?
Can you not just add an if statement?
public void KeySPACE() {
if(this.scene == 0){
beginGame(player, "Map0");
}
}
And just make sure that before the game starts, you are on scene 0.
Alternatively you can create a boolean value to do the same, for example:
public void KeySPACE() {
if(!gameRunning) {
beginGame(player, "Map0");
}
}
You will need to define a boolean gameRunning which starts as false. You can set it to true in the beginGame method.
Related
Can someone tell me how I can do so that an animation is made in a pane when the mouse is over said pane and make another when it is the opposite? I tried using the onMouseEntered and onMouseExited methods, with the first one there was no problem, however if we remove the mouse very quickly or abruptly, the program will not detect the exit of the mouse and therefore the animation will not be executed, can someone help me to solve this bug? please
first add 2 methods to an events from the scene builder for the pane, these are said methods
public void scale1 () {
double currentScaleX = pane1.getScaleX();
double currentScaleY = pane1.getScaleY();
if(currentScaleX ==1.0 && currentScaleY ==1.0) {
scale.setNode(pane1);
scale.setDuration(Duration.millis(100));
scale.setByX(0.75);
scale.setByY(0.75);
scale.play();
}
}
public void scale1Re () {
double currentScaleX = pane1.getScaleX();
double currentScaleY = pane1.getScaleY();
if(currentScaleX >1.0 && currentScaleY >1.0) {
scale.setNode(pane1);
scale.setDuration(Duration.millis(100));
scale.setByX(-0.75);
scale.setByY(-0.75);
scale.play();
}
}
However, when executed it works, but if we move the mouse very quickly, it will not detect the change and sometimes it will only execute the first methodIt is not seen in the screenshot, but my mouse is out of the pane
I even tried to make a mouselistener class in my controller class so that it detects when the mouse is out of the pane or something and automatically executes the second method, but I think I did it wrong
#Override
public void initialize(URL arg0, ResourceBundle arg1) {
pane1.setOnMouseExited(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent mouseEvent) {
Bounds bounds = principalPane.getBoundsInParent();
if (bounds.contains(mouseEvent.getSceneX(), mouseEvent.getSceneY())) {
scale1Re();
}
}
});
}
It's not the MouseExited that's being missed, it's the in progress transitions that cause the problem.
Two things need to be done. First, the ScaleTransition has be set to absolutes targets, so setToX() not setByX(). Second, change the play() to playFromStart(). Like so...
class MouseOverExample : Application() {
override fun start(stage: Stage) {
stage.scene = Scene(createContent())
stage.show()
}
private fun createContent(): Region = HBox(40.0).apply {
children += listOf(animatedPane(100.0), animatedPane(500.0), animatedPane(1200.0))
padding = Insets(40.0)
}
private fun animatedPane(transitionDuration: Double): Region = StackPane().apply {
children += Label("H").apply { style = "-fx-font-size: 40px;" }
style = "-fx-border-color: blue; -fx-border-width: 5px;"
padding = Insets(20.0)
val transition: ScaleTransition = ScaleTransition().also {
it.node = this
it.duration = Duration(transitionDuration)
}
onMouseEntered = EventHandler {
with(transition) {
toX = 1.5
toY = 1.5
playFromStart()
}
}
onMouseExited = EventHandler {
with(transition) {
toX = 1.0
toY = 1.0
playFromStart()
}
}
}
}
fun main() {
Application.launch(MouseOverExample::class.java)
}
This is Kotlin, but it should be easy enough to figure out.
This gives three Panes, each with a transition associated with it, and the durations are all different so that you can see how mouse speed has an impact.
At 100ms, a partial grow followed by a shrink looks just fine. At 1200ms, if the mouse exits and the grow transition stops after, say, 100ms then it will still take 1200ms to shrink back to the original size, which is kind of goofy. But in every case the Pane goes back to its original size no matter how fast you sweep the mouse through it.
I'm not 100% sure how to best describe this issue but I will try my best.
I am developing a music application and have different windows within one and have loaded panes into a little in app window shown below:
The bit that changes from a green button to the playlist screen is the window that has FXML files loaded into it.
I recently created a part of the application that plays songs from a button within this little window of the application but the media player is in the main application controller and needs to be here as it updates the values of the two sliders at the bottom.
I have seen something about referencing the exact instance of the controller I am using for the main application but I am unsure how to do this. I tried to create a static version of the mainAppController but this was a separate instance and therefore did not reference properly.
The only method I need to reference is the addPlayerListener one. I tried to make this static but because it dealt with the slider and so on from the FXML file that could not be made static, this did not work.
A simplified version of the controller and FXML file I need to reference from outside of the class looks like this:
public class MainAppController implements Initializable {
#FXML AnchorPane anchor;
#FXML AnchorPane window;
public static AnchorPane pane;
private boolean isPlay = false;
private boolean makeChanges = false;
public static MediaPlayer player;
PlayerUtils playerUtil = new PlayerUtils();
#FXML Slider volume, progressBar;
#FXML Label playTime, fullDuration;
String songFile;
Media songMedia;
Duration duration;
boolean updating = false;
//declaring the media player listener so that it can be removed and added
public InvalidationListener listener = new InvalidationListener()
{
public void invalidated(Observable ov) {
//if changes to the slider are being made then values will not be updated
//as it causes interference when trying to move the slider
if(makeChanges == false){
updateValues();
}
}
};
//this just plays or pauses depending
#FXML public void play_pause(){
play_pauseFunction();
}
//updates values of current time display (playTime) and updates the slider value
//called from the listener so constantly updating
protected void updateValues() {
//updates values of playTime and slider values
}
//THIS IS THE ONE I NEED TO ACCESS
//makes sure the player has no listeners before adding a new one
public void addPlayerListener(){
player.currentTimeProperty().removeListener(listener);
player.currentTimeProperty().addListener(listener);
}
#Override
public void initialize(URL url, ResourceBundle rb) {
}
}
Sorry if this question is poorly asked, but I couldn't think of another way of posing it.
Thank you for help in advance
Ammendment: I would actually like to access this method:
public void play_pauseFunction(){
if(isPlay == false){
//temp while playlists not working
if(player == null){
songFile = "E:\\Project\\Whupsh\\Songs\\Whenever, wherever - Shakira.mp3";
player = new MediaPlayer(PlayerUtils.getSongMedia(songFile));
progressBar.setDisable(false);
volume.setDisable(false);
duration = player.getMedia().getDuration();
}
player.play();
//adds listener to link with slider
addPlayerListener();
play_pause.getStyleClass().remove("play");
play_pause.getStyleClass().add("pause");
isPlay = true;
}
else{
player.pause();
play_pause.getStyleClass().remove("pause");
play_pause.getStyleClass().add("play");
isPlay = false;
}
}
This method is in the same class as all other methods
One way that worked was by having a static class holding all the controllers that would be needed to be accessed from another controller.
This is by not a particularly good way of doing things, and a better way of accessing controllers from outside another would be to pass it around as a parameter as kleopatra has said.
Passing Parameters JavaFX FXML
I want my button to appear whenever an object reaches a certain position, that object is a sprite that is generated every second:
public void create() {
if(spritePosition>700) {
buttonObj.createButton();
}
}
public void render() {
if (condition==true) {
stage.draw();
}
}
The problem is that when the games starts no Sprite is generated yet, so the result is an error. I'm also thinking of calling the createButton() method on the render method but it would generate a new button every frame because it's called constantly.
A simple way to let your button "disappear" is to just set its position to some position outside of the visible screen area.
For example something like:
buttonObj.setPosition(-1000, -1000);
To make it visible again you can just set the real coordinates again!
How about:
public void create() {
buttonObj.createButton();
buttonObj.setVisible(false);
}
public void render() {
if (condition==true) {
buttonObj.setVisible(true);
}
}
All actors in Scene2d have the setVisible method. simply try :
yourButton.setVisible(true)
or
yourButton.setVisible(false);
I have a menu with items that open internal frames, but every time I need to click twice in the frame. One time to give focus to the Int.frame and the second time to actually do something (give focus to a textfield).
So, here is my question: It's possible to automatic give focus to the Int.Frame?
Code of my main screen:
public final class principal extends javax.swing.JFrame {
viewCity city = new viewCity();
public principal() {
initComponents();
myListeners();
setLocationRelativeTo(null);
}
public void myListeners() {
menuCity.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
menuCityClicked(e);
}
});
}
public void central(JInternalFrame window1) {
int lDesk = panelPrincipal.getWidth();
int aDesk = panelPrincipal.getHeight();
int lIFrame = window1.getWidth();
int aIFrame = window1.getHeight();
window1.setLocation(lDesk / 2 - lIFrame / 2, aDesk / 2 - aIFrame / 2);
}
private void menuCityClicked(MouseEvent e) {
if (!city.isVisible()) {
panelPrincipal.add(city);
central(city);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
city.setVisible(true);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
}
}}
No matter what, the menu will always keep the focus. For example, click in your browser's menu, and you will keep the focus, by moving the cursor you will open other menus without need to click.
By putting the properties "selection model" to null works, but give me nullpointerexception.
Ok, the problem is with the jMenu, but with jMenuItem Works fine, so... I'm using
I'm developing a small photo editing application and would like the JButtons disabled until the user loads an image, at which point I want the buttons to become enabled(clickable). My thinking was to add a boolean imageFound, and an image checker method. If boolean is false, the buttons are disabled and if it is true they are enabled (the boolean is set to true in the load image actionPerformed method). The problem im having is that when running the app, the buttons are disabled as they should be, but when i load the image they would still be disabled. I dont know if maybe i am missing any piece of code to recheck whether the image is available, thus enabling the buttons (at runtime ofc). Thanks for any help.
...BufferedImage effects = null;
boolean bmpFound = false;
public GUI()
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.initComponents();
this.bmpChecker();
this.addListeners();
this.setTitle("PicTweak");
this.setSize(900, 600);
this.setVisible(true);
}
...else if(e.getSource() == loadItem)
{
try
{
imagePath = DialogIO.displayOpenDialog();
effects = ImageInOut.loadImage(imagePath);
imageHolder.setIcon(new ImageIcon(effects));
bmpFound = true;
}
....public void bmpChecker()
{
if(bmpFound)
{
grayScale.setEnabled(true);
blur.setEnabled(true);
reset.setEnabled(true);
brightDark.setEnabled(true);
horFlip.setEnabled(true);
verFlip.setEnabled(true);
verHorFlip.setEnabled(true);
}
else
{
grayScale.setEnabled(false);
blur.setEnabled(false);
reset.setEnabled(false);
brightDark.setEnabled(false);
horFlip.setEnabled(false);
verFlip.setEnabled(false);
verHorFlip.setEnabled(false);
}
}
When you load/unload the image, call bmpChecker() afterwards, i.e.
...
try
{
imagePath = DialogIO.displayOpenDialog();
effects = ImageInOut.loadImage(imagePath);
imageHolder.setIcon(new ImageIcon(effects));
bmpFound = true;
bmpChecker();
}
...
A better alternative would be t add listeners for the image loading, i.e. for each control or group of controls that needs to update its state accordingly, you'd register a listener that is notified whenever an image is loaded or unloaded. The listener could then trigger the updates of the corresponding controls.
Something like:
class ImageEvent {
private boolean imageLoaded; //plus getter/setter and maybe initialized in constructor
}
interface ImageListener {
void imageChanged(ImageEvent e);
}
...
List<ImageListener> listeners;
...
try
{
imagePath = DialogIO.displayOpenDialog();
effects = ImageInOut.loadImage(imagePath);
imageHolder.setIcon(new ImageIcon(effects));
bmpFound = true;
ImageEvent imgageEvent = new ImageEvent();
imageEvent.setImageLoaded(true);
for( ImageListener l : listeners ) {
l.imageChanged(imageEvent);
}
}
...
And an example listener:
class JButtonImageListener implements ImageListener {
private JButton button; //plus getter/setter
public void imageChanged(ImageEvent e) {
button.setEnabled(e.isImageLoaded());
}
}