I'm not understanding Java GUI's as well as I thought. In my paint method for a frame, I'd like to wipe all of the current buttons, and add new ones. (The overall goal is to have an interface where the user can see characters and click on the buttons to download documents related to the character. Since every character is different, when the user selects a new user from my list, a new set of documents and buttons will be available to them.)
This is a test frame that I just wrote that shows where things go sideways. It has the similar paradigms that I use in my actual program, without too much clutter:
public class GUITest extends JFrame
{
/**
* #param args
*/
public static void main(String[] args)
{
Container gui_test = new GUITest();
}
private JComponent content = null;
public GUITest()
{
super();
setVisible(true);
}
public void paint(Graphics g)
{
this.removeAll();
content = new JPanel();
JComponent test_button = new JButton("New Button 1");
JComponent button = new JButton("New Button 2");
content.add(button);
content.add(test_button);
this.add(content);
super.paint(g);
}
}
Without the call to removeAll(), buttons will continue to be thrown on top of the JPanel, but with the call, nothing shows up. I don't know why this is, as I'm adding the components appropriately, right?
Edit
Got it, let me give you a more detailed breakdown. A client is navigating my program by looking at a list of characters in a game on a west panel. They can select a row from the list which will show char details on the east panel. The details are an image and description. Recently, I added relevant documents for that particular char, which will show on the bottom of the east panel. I created key listener's, so the client can quickly view the document by pressing a num key, but I also want to give them the ability to click on the button to launch a pdf view and see the contents of the document.
Since every char has different related docs and different number of docs, I repainted the buttons every time, to reflect the amount of related docs and the appropriate titles for the docs. This is where the repaint is acting strange. You gave me a good explanation of what's going wrong, but I don't know how to give the client access to the docs now, aside from painting a description of the doc along with the hot key needed to launch it. Does that make sense?
Never add components to your GUI or remove components in the paint or paintComponent methods. Just don't do it. Ever. Period.
These methods are for drawing only, and need to be as fast as possible, else your program will appear unresponsive. Not only that, you do not have full control over when or even if these methods will be called, so program logic and structure should not go into these methods.
Instead react to user events with event listeners such as ActionListeners, ListSelectionListeners, or with key bindings.
Edit
Regarding
Got it, let me give you a more detailed breakdown. A client is navigating my program by looking at a list of characters in a game on a west panel. They can select a row from the list which will show char details on the east panel. The details are an image and description. Recently, I added relevant documents for that particular char, which will show on the bottom of the east panel. I created key listener's, so the client can quickly view the document by pressing a num key, but I also want to give them the ability to click on the button to launch a pdf view and see the contents of the document.
I'd use a JList to hold the list of selectable information on the left, and would react to it with a ListSelectionListener. In the listener, I'd change the related displayed information. I also avoid using KeyListeners with Swing but instead gravitate towards Key Bindings as they're more flexible and less rigid regarding focus.
Regarding
Since every char has different related docs and different number of docs, I repainted the buttons every time, to reflect the amount of related docs and the appropriate titles for the docs. This is where the repaint is acting strange. You gave me a good explanation of what's going wrong, but I don't know how to give the client access to the docs now, aside from painting a description of the doc along with the hot key needed to launch it. Does that make sense?
I'm not sure what you're doing here or what you're trying to do.
Since every char has different related docs and different number of docs, I repainted the buttons every time, to reflect the amount of related docs and the appropriate titles for the docs. This is where the repaint is acting strange. You gave me a good explanation of what's going wrong, but I don't know how to give the client access to the docs now, aside from painting a description of the doc along with the hot key needed to launch it. Does that make sense?
So rather then "painting" the buttons, why not just change there text (setText(...)).
When a user selects a "char". You are going to need to rebuild portions of your screen. Change the list model (as suggest above) and remove/add any buttons you need on the document container.
Related
I'm about to write a program using Java and i want it to have the next behavior:
Start with a small screen, just one button (i'm going for the JMenuBar) for the user to select a image file (a country or state map)
Once selected the image file, i'll need to resize the frame to the size of the selected image, and put the image as background.
when the user clicks somewhere inside the frame (click on a state or city) the program will have to create a visual object there, a circle, square or any form in that coordinates.
will need also a listener in those objects to know when they are clicked.
Summary: User has to select an image and trace a graph on it.
I am not asking for the code to do this. I would like to have some ideas about which components use to achieve this since i have been reading and there are plenty of ways to set the background image and stuff. But, considering the requirements, can you recommend me which components to use? I am a bit short of time since i've been given only about a week to code this, otherwise i would try all the alternatives by myself.
Some answer like:
"use a label to set the background and then resize the frame by this way: (some stuff) and then you can create a class extending from JLabel to create the circles with the listeners...." that would be enough help
I hope I was clear, any idea is welcome
Many thanks!
If you're going to stick with Swing I would use a JFileChooser to select the image. Once you got the image you can easily resize the JFrame by using the frame.setSize(image.getWidth(), image.getHeight());
To listen for mouse clicks inside your JFrame you need to use a MouseListener, make sure to add it to the frame, I always forget doing that.
Not sure whether you've succeeded drawing images/shapes at all. If not, you need to use a JPanel, check this topic if you need extra help.
If you are going to use a "JFrame " then you should definitely use Swing JFrames JPanels, and JLabels (as well as any other JComponents you need.) to accomplish this. Use only one JFrame. Use JPanel as the content pane/background for your JFrame and add everything else to it. But I would also suggest learning and using JavaFX because its the newest and I think it would be the easiest to use to do something like this. But if you only have a week and you know some swing use what you know. If you need more information post some code. Or ask a more direct question.
I have a public JFrame with a CardLayout, this JFrame includes some JPanels for different stages of analysis, I want to return to the main panel and erase all data stored in the objects to start a new analysis using a JMenuItem, but I don't know which function could do that. Any suggestion?
I have tried with this code, a jMenuItem1ActionPerformed which just backs to that jpanel but doesn't reset the gui. "Seleccion" is the main jpanel, the main menu of the application
panelPrincipal.removeAll();
panelPrincipal.revalidate();
panelPrincipal.repaint();
panelPrincipal.add(seleccion);
panelPrincipal.revalidate();
panelPrincipal.repaint();
There is no "one-size-fits-all" solution, and there is no core Java "function" that you can call for this since it all depends on the structure of your program. In other words, you will have to create your own reset mechanism. Hopefully, your program structure is built around an Model-View-Control (MVC) type of pattern, and if so, then your JMenuItem's listener would notify the Control of the user's wish to reset, the Control would call reset() on the Model (a method which you would have to create of course) which would reset the Model to the initial state. The View which should have listeners attached to the Model will then change its display accordingly.
From your codes you probably tried every means you can think of to reset everything to initial state.
Personally, I do not think it is a good idea to remove all Components and add it back simply just because you want to reset it. You have to write your own codes to specifically tell Java what things need to change (reset).
For example if you have 3 text fields, you can do it in your action listener:
public void actionPerformed(ActionEvent e){
txtField1.setText("");
txtField2.setText("");
txtField3.setText("");
}
Doing this works, but it looks pretty much hard-coded and it is hard to maintain. Image if you have 999 textfields to deal with. You can always improve your program structure for example like:
input --> update database --> text fields read from database
Input updates database. The fields just read from the database. If you want to reset everything, just clear of the data in the database.
public void actionPerformed(ActionEvent e){
//Delete records from database
//Instead of updating all 999 fields.
}
This is just an example. It is up to you to decide how your program shall be structured.
repaint() basically just inform the paintManager to call the paintComponent() method, you probably won't see any difference in your UI appearance for calling that unless you have been doing things like overriding paintComponent() and making changes to the look and feel of the JComponents or using Graphics for drawing.
I've set up a Server which runs and accepts connections from my Remote Client, and now I'm working on my GUI.
Before anything else, my goal here is to create a nice looking client that will have a login screen (login/pw), and then a nice layout with my options/perhaps a chat box after the user has logged in.
I've searched a lot online and used this site to set up my server and get things working, but I've got a bit of a problem with the GUI/theory and hope someone here can guide me a bit.
At the moment, I've set up a class called ClientGUI which is called from my main class, and this produces a 420x240 size screen. After placing my login/password JTextField boxes here, is it "proper" to set up the other GUI's the way I've outlined below? I'm not sure if I should be putting them under one class or how I would advance from one GUI to the next. I'm thinking I should repaint and resize the screen as necessary, but I am not sure how to set it all up. A brief outline would be helpful (you don't need to give me exact code).
public class ClientGUI extends JFrame {
public ClientGUI() {
setSize(420,240);
setVisible(true);
setTitle("Title");
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
}
public loginGUI() {
//code for my login/pw boxes, images, listener for entering information
}
public afterlogginginGUI() {
}
paint() {
//not too sure about how this should be setup either. Should I do all my textfield
//and image work in paint()?
}
}
I have never made anything like this, so I have the feeling I'm not setting this up in an ideal way.
An alternative is to have a different java class extending JFrame for each 'screen' I want, but if I do it this way, would I do it like this?
In my main RemoteClient class:
main {
ClientGUI();
//display whatever
LoginGUI();
//listen for login info
if (loginIsValid) {
afterlogginginGUI();
}
}
I think you're thinking in to much of a linear fashion, where the code flows from A then to B then to C ... where in fact, Swing (and GUI's in general) are event driven...
C happens, so you do B, which triggers F so you do E ...
Start by creating a JPanel, onto this add your JTextField and JPasswordField, this will act as you basic login view. You could then add this to a JFrame or JDialog depending on your needs. You will need some way for the user to either "cancel" or "validate" their credentials.
Typically, I do this a separate view, as I never know where my poor "user details" pane might end up, but you could do this a single view (including the buttons within the "user details" pane), that will come down to your requirements.
You can use a CardLayout to switch from the "login" view to the "application" view. This has the benefit of maintaining only a single frame and prevents windows from been splashed all about the place...
I would, personally, separate the core functionality of the views to separate classes, this means you can simply create an instance when you need it and add it to whatever container you want.
I would recommend against extending from JFrame directly. This locks you into a single container (making it hard to re-use components or extend the program later) and you're not adding any new functionality to the class anyway...
Start by having a look at Creating a GUI With JFC/Swing.
You'll probably also be interested in How to Use CardLayout, How to Make Dialogs, How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listeners
You'll also need to have a look at Laying Out Components Within a Container
Because you're likely waiting for a response from the server at some point, you will need to have a look at Concurrency in Swing and Worker Threads and SwingWorker wouldn't hurt
I am wanting to make an applet for practice, and my goal is to make a program that displays seven rectangles with info inside of each one. I would also like the cards to display in a random order.
After the cards are displayed, the user should be able to click on the card, and then the card should be removed from the options and be displayed beneath them, in the order that you click them. This may sound confusing, but I basically want the user to be able to prioritize or sort the info cards.
For example, if the cards had dates on them, the user could sort them in order from past to present.
My first idea was to draw rectangles on the screen and get the mouse click x and y to see if the user clicked that card, but I'm sure that there is another way that doesn't have to be that complicated.
I'm sorry that I don't have decent code to post, I would rather not post my messy version. I can update this with code later.
I'm wondering what the best solution would be, because I would like to learn as much as I can from this project.
You can use panels, and register for action events. Action events don't care the coordinates where your mouse was clicked, but rather if the component was clicked or not. You can use setActionCommand() to identify each panel (card) or use some other attribute of your panel that you can read after capturing the event (the event.getSource() method returns the component that was clicked).
panel.setActionCommand("card1");
panel.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent event) {
if (event.getActionCommand().equals("card1") {
// do something
}
}
}
You can also use an existing LayoutManager or adapt or write one to display your panels any way you like.
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.