How do I revert state of JToggleButton from another class? - java

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.

Related

Unable to get values from another jFrame

I want to fill values of multiple jTextBox from a jFrame into another, using accessor methods like
String getNameVal()
{
return jTextBox1.getText();
}
How to call these methods from another jFrame?
Suggestions:
It sounds like your GUI code is geared towards making JFrames, and if so, you will want to avoid this. You are painting yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this.
More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
This question has direct bearing on your problem. I will guess that your main problem isn't how to give classes getter methods, and how to have other classes call the getter methods. More often then not, when faced with the issue of extracting information from one GUI view to another, the issue is one of when to extract the information. If you displayed your second window as a non-modal JFrame, and then had the calling class immediately extract the data from that second JFrame, you'd get nonsense data, because you'd be extracting data before the user would have time to interact with the 2nd window and enter data.
One possible solution to this when using non-modal windows to get information from the user is to use a WindowListener so you can be notified when the user has completed his dealing with the second window, and so now data can be safely extracted.
Often better is for the 2nd window not be non-modal, as JFrames are, but instead to be a modal window such as a modal JDialog. When the calling code displays a modal dialog, all code flow in the calling code stops until the dialog is no longer visible. In this situation, no WindowListener is needed since you will know exactly when the dialog has been dealt with -- on the code line immediately after you set it visible -- and so can extract your data from it with ease.
A nice variant on this has already been mentioned in by Andrew Thompson in comments -- use a JOptionPane. Don't poo-poo this option since JOptionPanes are powerful tools, likely much more powerful than you realize as they can hold fully formed complex JPanel views, and behave just as described above, as modal dialogs.
If you need more specific help, then please don't hesitate to comment to this answer. Also if so, then consider creating and posting a Minimal, Complete, and Verifiable Example Program where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
Edit
For my mcve code examples of the above suggestions, please my answers to the following StackOverflow Questions:
Using a modal JDialog to extract information
Using a JOptonPane to extract information
I assume the textfields are present in frame1 and you want to access them in frame2. The following can be a way to achieve this:
First create getters for all JTextFields that you have in your frame1. Alternatively you can have them in a panel and call getComponents() method.
Create a private variable of JFrame type in your frame2.
Modify the constructor of frame2 to receive the frame1 object and assign it to the private variable of JFrame type.
Now you can create a close() method in frame2 which disposes the frame2 and sets frame1 to visible.
But in my opinion you should create a class which handles the data in these textfields. Initialize the class object in any button click of frame1 and check for any inconsistency in the input. I can guess there is something wrong with your design.

Should i redraw the GUI after change?

I have built a GUI displaying a matrix. It looks much like in excel where you have labels on the first row and first column. The cells contains either 1 or 0.
There's a JComboBox below the matrix. I can select an item from the JComboBox and click a button "add". This adds an extra row to the matrix with the JComboBox item as its name. My question is how i should handle expanding this.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
It depends on what's in your window.
If you're drawing on a JPanel, by overriding the paintComponent method, redraw the entire JPanel. It's not worth the effort to try and redraw a part of a JPanel.
If you have a window made up of many JPanels, you can redraw just the JPanel with the changes.
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
It's generally a good idea to create methods to perform specific GUI tasks. I'd have separate initializeWindow and updateWindow methods for my own sanity. I usually separate the initialization of my GUI from the update of my GUI.
Read this excellent article, Sudoku Solver Swing GUI, to get an idea of how to put together a Swing GUI.
When you add components to a container, you will be invalidating that container's layout. This will automatically trigger a repaint, so the question becomes moot.
The real question becomes why?
Instead of messing about with labels and fields, you should just simply use a JTable. Check out How to use Tables.
This is optimized for performance, so if you're really concerned, this should provide a better solution, so long as you are firing the correct events to the required changes.
Unless you're finding yourself performance bound, I see no real reason not to redraw the entire window; sure there will be a performance hit but it should be negligible and your source will be simpler and easier to maintain. However, if you're finding yourself pressed for performance, I would suggest looking into implementing a "dirty rectangles" method of redrawing (i.e. your second approach).

How do I refresh a GUI in Java?

I have a general question that is Java related.
I am writing an application that has a GUI menu. I am trying to change one part of the GUI menu based on the selection of a Radio button.
Do I need to:
Redraw the whole window or just update that part with:
setVisible(true)?
If I just use the statement from #1 above .. the GUI is fine -- until I move the mouse over it and then I see the previous button choice. What am I doing wrong?
Swing components have a repaint(), revalidate(), and doLayout() method. One of those should probably be able to redraw whichever pieces you want. However, doLayout is not something that you should be taking responsibility for, that's the layout engines responsibility.
You may also want to check out this post, the first response has a pretty good explanation, and links to an article with more detail.
In terms of the second part of your question, I'm not sure, but we may need to see some code to get an idea. Is the 'replaced area' actually being removed from the view?
..in my application the user select which device platform type they want top test (that choice is a set of two radio buttons on the left). When the user selects either Android or iOS, the center grouping of check boxes changes to reflect a group of android devices they can test or a group of iOS devices that they can test.
Put a panel in the 'center grouping'.
Use a CardLayout for the panel.
Add both iOS & Android controls to the panel with the card layout.
Flip between them as needed.
Call revalidate() on the top level component.

Making a game menu using Canvas?

I am already familiar with JButtons, JLabels and such, but I want to start making a game a very "colorful" menu. Is there a way to do this using Canvas (like adding a mouse listener and make some buttons in PhotoShop and detect if the mouse hovers over and clicks the button), or is there a better way?
Since you're already familiar with JButtons, you may find it easier (and more practical) simply to extend the existing JButton and modify its appearance, so that it looks like an image rather than the traditional grey button.
Amongst other things, it means you get all the standard button behaviour for free, including special cases, and in exchange all you have to do is override a couple of methods.
Have a read through the accepted answer for the following question, which explains pretty much exactly how to do that:
Creating a custom button in Java

Keep track of Swing GUI "current state"

Sorry the title is fuzzy, but I really coudln't come up with a fitting title.
I'm developing my first application with Swing, and I'm having a hard time figuring out how to keep track of the current view of the application. With I mean with current view is for example if a button has already been pushed. For example, you shouldn't be able to press "Execute" before a file has even been loaded. I've come up with an architechtural solution to this that is really crappy, and I'd like tips on how to improve it.
I have a label called infoText, and it's updated pretty much every time I press a button. Through this, I'm keeping track of the applications state in this fugly way:
if (infoText == LOADING_NARROW){
printSelected(narrow_list);
}else{
printSelected(list);
}
Rather than keeping track of your state with GUI components, use normal Java objects and variables.
Just keep a boolean loadingNarrow in this case that you reference and update when needed.
Also if you are running a large load as the result of a button press and don't want the user to press it again you can disable the button once the load starts and re-enable it later. (Note I am assuming you are running the load on a separate thread so the GUI does not freeze).
Swing Components keep track of their own states.
My advice:
Initiate the application to a default state.
Adjust the settings in an event driven manner. For instance when JButton A is clicked, enable JButtons B and C and set a JTextField.
Check the states of objects with their builtin methods. Example
if((jButtonA.isEnabled() && jTextField.getText().equals("foobar"))
You can also use the mediator pattern to group related components and their actions.
First: Are they different methods, or a copy-paste-error?
printSelecteds (narrow_list);
printSelected (list);
Second: To disable a button you usually use:
ok.setEnabled (false);
If the file is loaded, you call
ok.setEnabled (true);
to enable the JButton "ok".
I don't see how that is related to your info-text, and to your printSelected(s) method. If you pass the state via the GUI, you might loose the one or the other due to race conditions. Changing a label could be the sink of an state change.
You could have mutual exclusive bit patterns to allow interference:
FILE_OPEN = 1;
SEARCHED = 2;
FRIDAY = 4;
to add them bitwise:
state |= FRIDAY
to ask them up in a binary pattern:
if (state | FILE_OPEN) ....
It doesn't look very elegant to me. I guess I'm not sure what your problem is. :)
To fire an action if some button is pressed, you have to implement an actionListener, which could modify your label as well. But the swing eventloop will already check the state of your components. You seem to duplicate the work partly.

Categories

Resources