I wonder if there's a good documentation (or a (viewable) ebook) about
the lifecycle of Swing components.
Is "lifecycle" the correct term, anyway?
I hope to find answers to question such as:
How, when, in which order painting methods are called?
How, when, which events are called by whom?
What is the exact sequence of method calls for component creation?
From time to time I encounter strange behavior of my apps, for example:
ComponentListener's resize event is called before setVisible(true)
(so that root pane has negative dimensions!)
Some components are laid out correctly only after resizing the JFrame by hand
Changing a super class from JPanel to JLayeredPane causes my class
to be laid out differently inside an other container.
And lot of other strange things...
I had the same question long ago.
I can't believe how hard is to find a good resource about this topic in the internet.
Fortunately I've found this link and now I have it in my bookmark with golden tag. :)
A Swing Architecture Overview
Once you have a good grasp of how they work conceptually you will be able to fix most of the problems you mention.
I hope it helps.
Related
First of all, I would like you to know that I'm new in Java world; so please forgive me if my question is basic.
I'm working with a team, and we are trying to create a browser using Java.
To begin with, we are watching some tutorials, and all of them begin with a class that extends JFrame. What does this JFrame do?
This could easily be answered in a 10 second Google search... But to answer your question anyway, a JFrame is an extension of java.awt.Frame, which displays a graphical window to the user, in which you can house components and graphics on.
These components range from JButton's JLabel's all the way to Menu bars, etc.
Also, extending a JFrame is never a good idea. It works fine, but for the best code readability, and usage, do not do it. There are plenty of reasons why, and they are explained thoroughly here:
Why shouldn't you extend JFrame and other components?
Extract:
Generally speaking, extending the component tends to be done strictly to use the component. This severely limits your options in unnecessary ways in terms of design, so that your classes can't extend different classes, you can't hide the JFrame's methods causing it to be more difficult to maintain and easier to trigger unexpected bugs when using the class.
More can be found below in the links provided:
JavaDoc for JFrame
How to use a JFrame
I'm trying to get a grasp on a couple concepts. Lets imagine you have a JFrame and in that JFrame there are two panels, we'll say left_half and right_half. If I click a button in right_half, I want something to change in left_half. The issue is that the right half doesn't know the left half exists. So, you could tell the Frame, but technically neither panel knows the Frame exists either, right? The Frame can change the panels, but panels can't change the Frame, or so it seems to me.
So, I pass a reference to the Frame into the panels. Now the right_half can call Frame.setVariable(data) and the Frame can, from that same method, say left_half.setStuff(data). That just seems wrong to me and I have been looking for a way to do it without passing references up and down the hierarchy.
Next, someone says "That's why Observable exists!!" Cool, I think to myself. I then found many confusing examples of how to use Observable that didn't help at all. Finally I see this one, which makes sense.
http://www.javaquizplayer.com/blogposts/blogpost7.html
However, it has this: "observable.addObserver(mainWindow);" mainWindow is the equivalent of Frame in my example above, and it had to pass a reference to attach the Obserable to! So even with Observable, I have to pass references down the hierarchy?
It just seems wrong. If it's not wrong, that's fine... I can do it this way. However, my question once all that back-story is finished is simply this: how are you supposed to pass data between two panels? I'm okay with abstract answers if they're in plain language, I'm okay with code samples if they're short and easy to follow. I'm not a pro Java coder, I can't just search through 29 API pages and 1400 lines of code and just suddenly understand how it works... yet. I'll get there.
The observable pattern (in the form of event listeners) is OK and is good practice. You see, even though RightPanel knows someone might be listening to all its events, it does not know who is listening. Well, technically, it could go through all its listeners and use reflection to find out who they are; now, that would be bad practice.
As it is, RightPanel knows someone might be listening to it, and that's all. Components are always aware someone might be listening, since the whole Swing is based on it. What matters is that RightPanel compiles without LeftPanel (or frame), and is completely decoupled from it, except via the listener interface. Not only cool, but standard.
As a side note, your class structure does not have to mirror your nesting panel hierarchy. Depending on what you are doing, it may be entirely fine to control behavior of both left and right panels from inner classes within Frame. (Personally, I'd use a JPanel, not a JFrame, since it allows for more flexibility, but this can be easily refactored). Otherwise, you risk splitting your View/Controller into too many closely coupled classes, and that would violate encapsulation and cause a lot of boilerplate code. Normally, I don't code big fat classes and try to refactor them into smaller ones; Swing is usually an exception. Better one big fat class than a maze of densely coupled classes. Unless of course you have a reusable component or some piece of functionality that can be clearly and intuitively decoupled; not just a couple of buttons or checkboxes that have no meaning in and of themselves. The simple fact that some subcomponents are situated within a certain panel in a component tree should not be a major factor IMHO.
For that matter, I usually don't nest JPanels; I use MigLayout and make all components into siblings. Matter of taste! I'd just encourage you to check out MiGLayout first and see whether you like it.
I'm sorry this is probably way too basic to be on here, but it's a subject I've been struggling with for about a month now and I don't know where else to go (as far as I know there is no "noob overflow", lol).
I'm trying to create a class that would:
1. put an image on a window (a JFrame, JPanel or other container)
2. be able to support keyboard and mouse listeners
3. could have multiple instances in the same container
So anyway I've tried all the usual places - Google, YouTube, the official Java site (sorry forgot the URL) and of course here on Stack Overflow - but haven't been able to find anything even remotely similar to what I'm trying to do.
Of course, I've also considered the possiblity that maybe it can't be done at all. There doesn't seem to be any kind of standard "JImage" or "JGraphic" that works like JButton or JLabel, and for whatever reason graphics requires a completely different list of (extremely involved) processes and procedures. As an example, in this post: How to "really" draw images in a Java app - it took me 60+ lines of code and 2 classes to just come close. That project didn't work in the end because for some reason it would only let me create one instance (even it you created 2-4 in the main method, it would only display the last one you told it to add).
But anyway, assuming that I'm not trying to "re-invent the wheel" here and it is actually possible (in Java), does anyone have an idea as to how (or at least know of a better site to study it)? Unfortunately most of the sites I've visited tend to assume you know all the inner workings of images (I know what a pixel is but that's about it - Buffers, Rastars etc. are still beyond me). It would be absolutely outstanding if there were a site that would explain it in layman's terms, if such a site exists. Thanks in advance.
Just use a plain old JLabel.
Regarding your requirements:
put an image on a window (a JFrame, JPanel or other container).
You can give a JLabel an ImageIcon of the image of interest and it will display it. This can then be easily placed in any other container such as a JPanel or JFrame.
be able to support keyboard and mouse listeners
Any component that extends JComponent, such as a JLabel allows for use of MouseListener, MouseMotionListener and can listen for keyboard input via Key Bindings.
could have multiple instances in the same container
You can add as many as you'd like to any container. Just be cognizant and respectful of the layout managers in use.
I fear I'm just making a ten-times duplicate question, but I've been trying to Google this for quite some time without finding anything, neither in general nor even here on SO, so I'm starting to think it's worth a shot.
I'm wondering, is there a good guide on what is necessary to implement an AWT widget in Java? What needs to be implemented in order to respond to such things as redrawing, resizing, placement, focus behavior and all other such things as widgets may or should do, in a proper manner? All the articles I manage to find describe the process from the perspective of a user of widgets, never from the perspective of the one implementing them.
Also, what would be the primary differences between implementing an AWT widget and implementing a Swing widget? Is there even a difference from the implementer's point of view?
Probably the best way to learn how to write an AWT widget would be to look at the source code for an AWT widget. Here's the source code for the java.awt.Frame class.
I haven't worked with AWT much, but Swing is much better from the GUI developer's point of view. The only difference that I know about from the implementer's point of view is Swing's usage of Listeners.
Again, you can look at the source code to see what's different. Here's the source code for the javax.swing.JFrame class
Not too much difference aside from the fact that AWT widgets are simpler.
You extend one of the 4 classes: Component, Container, Canvas, Panel. The first two are heavyweight, the latter two are lightweight (don't have native window system peers). Override paint(Graphics) (or update()) and getPreferredSize() to make it visible, then look into javadocs for overriding event handling methods.
Sure you know this link, http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html
There have been many times on StackOverflow where a user asks a question like this...
I have a main JPanel that contains a child JPanel. When the user clicks a
button, the child JPanel should change to a different JPanel. How can I
achieve this.
More often than not, the user has actually tried to implement this problem, but can't get it working.
Whenever I answer this question, I tell them to do something like this (put simply)...
JPanel myFrame = new JPanel();
myFrame.remove(oldPanel);
myFrame.add(newPanel);
I see this as quite a legitimate answer, and I personally have used this in many of my own Java projects without problem. However, I always get downvotes for my answer, and everyone just says "Use a CardLayout".
So my question is, why is everyone so fascinated with CardLayout, to the point where my answer deserves a downvote? Why should I choose to use a CardLayout rather than adding/removing panels using my code above?
As a further question, would you still be suggesting CardLayout for interfaces that have dynamic JPanels. For example, most of my programs implement a custom plugin framework where there could be many hundreds of JPanels, but I only load and display the panels as they are actually required. For the normal use of the program, most of the panels would never actually be loaded or required. For this type of scenario, would my coding approach be the best solution, as I understand that CardLayout would require me to actually create all of the JPanels even though most will never be used?
With CardLayout, it's easier to have loose coupling (though not impossible with roll your own)
With CardLayout, the preferredSize of the card-holder is that of the largest card it holds.
CardLayout is harder to fark-up, and allows almost trivial contiguous component swapping its next() and prev() methods.
You can easily associate the desired component with a constant -- no need to have to create a Map<String, Component> for this purpose as it's already there for you. I've not infrequently used enums for this.
No need to remember to call repaint() and revalidate() when swapping components.
It's built for and allows for easy re-use of components.
CardLayout has been thoroughly tested and proven to work. It correctly acquires the component-tree lock and performs component validation in order to ensure that nothing can go wrong. Your solution, while it may work most of the time, will fail under certain circumstances.
This all boils to reinventing the wheel: Why would you want to when such a time-tested class is already available?