I basically have 1 class called ClueGame dedicated to painting the main gui using swing.
In this class, I iterate through a list of BoardCell objects, and call boardcell.draw(g) from within paintComponents(Graphics g), which draws rectangles to the board.
However, in a different class entirely, the WalkwayCell class (a child of BoardCell), I need to update the color of specific rectangles. I'm thinking something like cell.updateColor()
But obviously I need to get draw to do that some how. I don't know how to update the color of one object (rectangle) on the board because I can't call draw because I don't have a graphics object.
Hopefully that makes sense. I can post code if someone requests it.
You have any number of options...
You Could
Pass a reference of your ClueGame to the instances of WalkwayCell which would then be capable of calling repaint on the ClueGame reference directly.
The problem with this is you expose the entire ClueGame class to ever instance of WalkwayCell, which allows them to do whatever they want to it...
You Could
Use an observer pattern, to allow the ClueGame to monitor changes to the state of the WalkwayCells
This means that WalkwayCell doesn't really care, it will simply provide some kind of event notification when the state of the object changes and doesn't expose parts of your application to other parts that have no right to know about...
Swing makes use of the observer pattern for it's listener API. You could take a look at Writing Event Listeners for some more ideas...
When creating a Swing GUI, it’s important to create GUI model classes. The model classes hold the data for the GUI. Having model classes makes coding the Swing view classes so much simpler.
In your case, you would change the state of the instance of the WalkwayCell class, using a method like cell.updateColor(), as you suggested. First, you update the model instances. Then you draw the model instances on the view.
I've explained this concept in more detail with a working example in my Hangman Swing GUI article.
Related
In AS3, there is an event that listens for when an object is added to the stage. This is useful for cases where, for example, some variables are not set until it is added on-screen. By waiting until the object has been added, you can assure that all of those variables are set.
Is there an equivalent in swing? For example, I have a function that relies on an objects getWidth function. Obviously, if I try to call this before the object is added on screen, this function will have problems because the width will be zero. I would like this function to be called as soon as the component is added and has a width. In as3, I would do something like:
myComponent.addEventListener(Event.ADDED_TO_STAGE, myFunction).
How would I do that in Java?
Depending on your setup, a ComponentListener might be enough. There is a section in The Java Tutorials about ComponentListeners.
Another way of initializing stuff as soon as it is displayed is overriding the paintComponent method and performing the setup on the first invocation.
JavaScript is different from Java. There are no function objects in Java and hence no JavaScript-style callbacks. In Swing you can react to events related to showing/adding of components by adding ComponentListener or ContainerListenerto either component or container via addComponentListener() and addContainerListener() methods.
My question is more about general design and code flow, rather than a specific issue like syntax. How can I take an existing game (a fighting game, kind of like Pokemon) and add a GUI to it? I've done very simple GUIs before, so I understand the concepts of adding a frame, selecting a layout, and adding panels, buttons, images, etc. I'm not stuck on the details. Rather, I don't know where to implement the GUI.
Is it best to create a class or classes for the GUI, and then create instances of those classes within my existing code? Or do I go the other way around, and have the code within the GUI drive the game forward?
I also haven't used event driven programming before. How does this fit into the structure?
You might want to read up on the Model-View-Controller pattern.
Take your existing game and turn it into a library of objects that maintain the game state through the various actions the players can make. This will be your "Model".
Then create some graphical elements that will display the game state to the user. This will be your "View".
Finally, you will need some user interface elements that allow the user to update the game state (buttons and such). These will have callback or events in which you will put the code that calls the methods in your "Model" object to update the game state, and to update the "View" objects as necessary. That's the Controller.
I am interested in creating a new widget similar to the JSlider widget, but with a "ghost" (translucent) knob displaying the previous slider position, as well as adding a trails-like animation to the real knob's movement.
I am a bit confused on the proper way of extending a Java Swing widget to add new functionality.
As I see it I have a few options:
1) Extend JSlider, place all my new model information here, and overwrite paint to first draw the JSlider, and than to overlay my desired additions. The problem with this solution is I would need to use trial and error to get the marks in the correct position (as I won't have access to full geometrical information) which will could make it not work in all situations.
2) Extend various classes of the Slider widget (JSlider, SliderUI, BasicSliderUI, MetalSliderUI, BoundedRangeModel, DefaultBoundedRangeModel). The advantage I see here is maintaining the proper model-view-controller architecture. However, this will require overloading various functions within the classes. I believe the result would seem very hacked together.
3) Copying all of the Slider widget's code, and modifying to create my new widget. This would be similar to options (2), but may be a bit simpler to modify code then to extend functions (which will be basically copying/modifying code anyways).
4) Re-create the slider widget from scratch with my desired functionality. After looking at the existing Swing Slider widget's code, this is not a trivial task.
Am I missing some more elegant method of creating a new widget that borrows functionality from an existing one?
Thank you for your insight.
I would choose 2) with some changes
Create WrapperSliderUI class which delegates all the methods calls to the delegate UI. And override just paint method.
SetUI of your JSlider should wrap original UI in the WrapperSliderUI
public void setUI(SliderUI ui) {
super.setUI(new WrapperSliderUI(ui));
}
The in the paint you will check original UI class and adapt your painting accordingly.
If I have a massive Swing component in my application which takes a long time to initialize, and want to display this component in different places in my GUI at the same time, how would I preferably do this?
The GUI user must be able to interact with the different copies of the component
(they could, for example, work as mirrors).
Let's assume that one might want to display copies of this component dynamically, depending on the input of the GUI user (that is, we do not want pre-loading of many copies of the same component).
You need to change your components to access data in a model-view like fashion. Each component would need to point to the same model that would server up the data and do the intensive task once rather than multiple times.
Also, initialization is slowing the GUI, then it sounds like you need a splash screen or a progress bar and the task moved off the EDT.
Is there any way that you could pull the heavy-duty initialization code out, maybe into a '...Factory' class?
I would create a one instance of the component (let's say HeavyComponent) and a custom class extending e.g. JPanel and referencing the component. Let's name it MyContainer. On paintComponent() of the MyContainer I would draw original component into a BufferedImage or use heavyComponentReference.paint(g).
Then on click by the MyContainer I would swap the component replacing the panel with real instance of HeavyComponent and placing in the old location of the HeavyComponent new instance of MyContainer.
display this component in different
places in my GUI at the same time ...
without having to create a new copy of
the same component ... user must be able to interact with the different copies
No way.
I am trying to write simple vector graphics editor in Java and got stuck with GUI... I have 2 JPanels: First one is for the "canvas area", second one is for the buttons. Canvas area is a Singleton, so then button pressed, it calls method of the Singleton and it adds element to list of the Singleton and re-paints the area. But now, I want to change these buttons to JToggleButtons and don't know how to revert it's state after click on the canvas.
Which design pattern should I use (because I have bad feeling that I'm doing it wrong)?
Have you ever heard of call backs? Once they are understood and implemented correctly, they can work quite nicely.
http://en.wikipedia.org/wiki/Callback_(computer_science)
I like this example too.
http://www.linuxtopia.org/online_books/programming_books/thinking_in_java/TIJ310_019.htm
Make use of the Command and Memento patterns. Implement an Undo Command. Allow commands to store state in the form of a Memento. Restore the state from the Caretaker when you find fit.