I have a working code which creates a window with a text area. The code is here. I try to figure out how this code works. A lot of things are clear:
The main-method creates an instance of the TextAreaDeom class (which is subclass of the JFrame). In other words, the main-method creates a window.
In the main-method we set some "parameters" of the window and make it visible.
It is not clear to me, in which place we put the text area in the window. I see that the text area is created right before the constructor. I also see that in the constructor we set some "parameters" of the text area (setText). I also see that in the constructor we create a a scrolling area and set some parameters for it. I see that the scrolling area is "connected" to the text area (since we use the instance of the text area to create the scrolling area). I also see that we create an object called "content" (using the current window) and we "add" the scrolling area to the "content".
But at which place the text area is added to the window? May be I can say that the text area is added to the scrolling area and the scrolling area is added to the "content" and the content is a part of the window-object?
in line 16 you create a JScrollPane which wraps around your JTextArea object. On line 21 you add this JScrollPane, which contains your TextArea to the ContentPane of the JFrame.As you call getContentPane() instead of creating a new one the ContentPane is already part of the JFrame.
All elements of the ContentPane will be displayed as part of the JFrame. The add method of JFrame is only for convenience and forwards the call to the JFrames ContentPane.
The scroll pane scrollingArea is created with the text area inside. scrollPane, was constructed with text area m_resultArea (see the documentation for JScrollPane's constructor). is then added to the frame's content pane.
The GUI elements should be constructed on the EDT. Here is a more reliable main() method for the program cited above.
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame win = new TextAreaDemo();
win.setTitle("TextAreaDemo");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.pack();
win.setVisible(true);
}
});
}
Related
I have a Java Swing GUI and everything in my JFrame is offset by a few pixels. On MacOS, I had to offset everything by 12 pixels downward to account for it. On Windows, everything is shifted to the left and downward as well. I discovered that
setUndecorated(true);
removes the JFrame border (which I suspect is the cause of my problems) but it also removes the title bar.
Is there a way I can remove the JFrame border (or some other alternative to make sure everything is centered) and still keep the title bar? I need the title bar so that I can move the JFrame around and have the maximize/minimize/close functions.
Also, the layout is set to null in case that matters. (Everything I'm doing is pixel - based so I cannot set it to anything else).
Thanks.
I found a solution after Googling a bit more. Calling
getContentPane().setPreferredSize(...)
pack();
inside the JFrame constructor will adjust everything so that the titlebar and borders will not impact the view of the content pane.
For anyone else that may need this, you have to set the preferred size of the content pane specifically as that is what you want to appear correctly.
This way you can keep the titlebar and all the normal functionality of a JFrame window that you would otherwise lose with setUndecorated(true);.
The reason why you are adding 12px is because this is consume by the Title and border.
If you use setUndecorated(true) You will loose the title bar and you have to implement the addWindowListener to add a location changing of of an application.
The best way to do is:
Class Main{
public static void main(String[] args){
//JFrame
JFrame frame = new JFrame();
//Create a Main Panel and setPreferred Size and not set Size or set Bound
JPanel mainPanel = new JPanel(); //You value down
mainPanel.setPrefferedSize(new Dimension(x, y));
frame.add(mainPanel);
//and then in last add
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//the pack method help you to setSize of the JFrame According to the
//Component size
frame.pack();
frame.setVisible(true);
}
}
In my JPanel (which is in a JScrollPane) I have several JTextArea. When launching the program these areas are populated by JTextArea.setText("text");
The problem is that the JScrollPane scrolls down to the JTextArea with the lowest Y-position as if the user would have focus on the JTextArea, no matter when it was populated with text. I thought that I could work around the problem by populating the JTextArea at the bottom first, if the JScrollPane maybe want to scroll to the "current" JTextArea that's being used. It didn't work so I'm assuming it just remembers the lowest point it's been and then just stays there for some reason.
Setting the view like this doesn't make any difference.
JScrollPane.getViewPort().scrollRectToVisible(new Rectangle(0,0,1,1));
I've tested by neglecting to populate the last JTextAreas and the JScrollPane is then viewing the top of the JPanel, as I want.
What's happening, and why is it ignoring my code?
Update, answer selected
You have to set the viewport a tad later when the GUI is ready
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
scrollPane.getViewport().setViewPosition(new Point(0, 0));
}
});
JScrollPane.getViewPort().scrollRectToVisible(new Rectangle(0,0,1,1));
The scrollRectToVisible() method is meant to be used on the component added to the viewport (the panel containing the text areas), not the viewport itself. Not sure what happens when you invoke it directly on the viewport.
Instead I would do the following:
scrollPane.getViewPort().setViewPosition( new Point(0, 0) );
Note, you may need to wrap that statement in a SwingUtilities.invokeLater() to make sure the code is executed on the EDT after all the components have been positioned on the panel by the layout manager.
If the frame is placing on top of the content pane the exterior colour to the user is colour of JFrame. Here even i'm painting the frame after content pane but content pane colour will be displayed. Why?
public class GUI {
public static void main(String[] args){
JFrame frame = new JFrame();
frame.setSize(300,300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Color myColor = new Color(100,100,100);
frame.setLocationRelativeTo(null);
frame.getContentPane().setBackground(myColor);
frame.setBackground(Color.red);
}
}
You shouldn't be setting the background of the JFrame itself. You CAN, yes, but it doesn't work very well.
It's got a content pane that covers the whole frame, so any color "underneath" will be covered up, as you've found.
All layout and styling should happen in the content pane.
You can set the content pane to a container of your choice, though, with a special layout or whatnot.
Also, when you say "painting the frame after the content pane" that's not actually happening. :) You're setting the background color after you set the background of the content pane, but it doesn't actually get repainted until its repaint flag is triggered by the application runtime.
Then it goes and checks what color is set, and paints. The order that you call the setters doesn't really matter.
I found three ways to fill my JFrame frame = new JFrame("...")
createContentPanel returns a JPanel and createToolBar returns a ToolBar.
frame.add(this.createToolBar(), BorderLayout.PAGE_START); //this works and puts the ToolBar above and the ContentPanel under it<br>
frame.add(this.createContentPanel(), BorderLayout.CENTER);
frame.setContentPane(this.createContentPanel()); //this lets the JToolBar hover over the ContentPanel
frame.getContentPane().add(this.createToolBar());
frame.getContentPane().add(this.createContentPanel()); //this only puts the last one into the JFrame
frame.getContentPane().add(this.createToolBar());
And now I am wondering why should i use the getContentPane()/setContentPane() method if i could just use a simple frame.add(...) to fill my frame.
You are right that it doesn't matter which you use (JFrame#add(...) vs. JFrame#getContentPane().add(...)) since they both essentially call the same code, however there will be times in the future when you'll need access to the contentPane itself, such as if you want to change its border, set its background color or determine its dimensions, and so you'll likely use getContentPane() at some point, and thus getting to know it and be familiar with it would be helpful.
//this only puts the last one into the JFrame
You need to understand how layout managers work. The default content pane is a JPanel that uses a BorderLayout. When you add a component and don't specify a constraint, then it defaults to the CENTER. However you can only has a single component in the center so the layout manager only knows about the last one added. When the layout manager is invoked it sets the size() and location() of that component. The other component has a size of 0, so it is never painted.
In Java 1.6, you can just use the add method of JFrame:
http://download.oracle.com/javase/6/docs/api/javax/swing/JFrame.html
(It will be delegated to the contentPane.)
http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JFrame.html
Which says:
The JFrame class is slightly
incompatible with Frame. Like all
other JFC/Swing top-level containers,
a JFrame contains a JRootPane as its
only child. The content pane provided
by the root pane should, as a rule,
contain all the non-menu components
displayed by the JFrame. This is
different from the AWT Frame case. For
example, to add a child to an AWT
frame you'd write:
frame.add(child);
However using JFrame you need to add the child
to the JFrame's content pane instead:
frame.getContentPane().add(child);
The same is true for setting layout
managers, removing components, listing
children, and so on. All these methods
should normally be sent to the content
pane instead of the JFrame itself. The
content pane will always be non-null.
Attempting to set it to null will
cause the JFrame to throw an
exception. The default content pane
will have a BorderLayout manager set
on it.
I've created a simple Swing panel that, when loaded, takes up my application's entire window. It contains two JTextAreas and a handful of buttons. I want one of the text areas to have the focus when the panel loads, so that the user can immediately start typing instead of having to click on the text area first. How can I achieve this?
By default focus goes to the first component defined on the window.
If this is not the component you want to have focus then you need to request focus once the window is realized.
The Dialog Focus example shows a couple of ways to do this.
See here the Documentation which contains exactlly what you are searching for (I think):
A component can also be given the
focus programmatically, such as when
its containing frame or dialog-box is
made visible. This code snippet shows
how to give a particular component the
focus every time the window gains the
focus:
//Make textField get the focus whenever frame is activated.
frame.addWindowFocusListener(new WindowAdapter() {
public void windowGainedFocus(WindowEvent e) {
textField.requestFocusInWindow();
}
});
You just need to call requestFocus method of Jcomponent class,
public void requestFocus()
On the Component that you want to focus.
And pleas make sure that you call this method after setVisible is called for its parent component.
For example:-
You have a Jframe in which you added a JTextArea, so after calling you should call in following order:-
jframe.setVisible(true);
jarea.requestFocus();