Setting divider location on a JSplitPane - java

I'd like to have 3 resizable horizontally JPanels. It works fine but I can not set the position of the first JSlitPane: sp.setDividerLocation(.3); doesn't work.
public class JSplitPanelProva extends JFrame {
public JSplitPanelProva() {
this.setLayout(new BorderLayout());
JPanel leftPanel = new JPanel();
leftPanel.setBackground(Color.BLUE);
JPanel centerPanel = new JPanel();
centerPanel.setBackground(Color.CYAN);
JPanel rightPanel = new JPanel();
rightPanel.setBackground(Color.GREEN);
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftPanel, centerPanel);
JSplitPane sp2 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, sp, rightPanel);
sp.setOneTouchExpandable(true);
sp2.setOneTouchExpandable(true);
this.add(sp2, BorderLayout.CENTER);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(1000, 600);
this.setVisible(true);
sp.setDividerLocation(.3);
sp2.setDividerLocation(.6);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new JSplitPanelProva();
}
}
I get this:
Can someone help me?
Thanks.

Change:
sp.setDividerLocation(.3);
sp2.setDividerLocation(.6);
To:
sp2.setDividerLocation(.6);
ActionListener splitListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
sp.setDividerLocation(.3);
}
};
Timer t = new Timer(200, splitListener);
t.setRepeats(false);
t.start();
And it will work as expected. The delay gives time for the GUI to recalculate sizes.

The documentation of the setDividerLocation(double proportionalLocation) method says:
If the split pane is not correctly realized and on screen, this method
will have no effect (new divider location will become (current size *
proportionalLocation) which is 0).
What you can do instead is using the setDividerLocation(int location) method like this:
sp.setDividerLocation(300);
sp2.setDividerLocation(600);

It looks like 3 things need to happen:
The divider location can't be set until the frame is visible
Setting the location of the second split pane needs to be done first
Setting the location of the first split pane needs to be added to the end of on the Event Dispatch Thread (EDT)
The following code will accomplish all 3:
this.setVisible(true);
sp2.setDividerLocation(.6);
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
sp.setDividerLocation(.3);
}
});
Note: all Swing components should be create on the EDT. So you should also be using the following to create the frame:
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new JSplitPaneProva();
}
});

Related

How can I change the style of the split bar in a JSplitPane?

I am using JSplitPanes for some of my panels, but they are a bit thick, especially when you have a few of them showing.
Is it possible to style these bars into something thinner, like a line with an arrow, or even just a line?
You can use setDividerSize to it in order to change its width. Its default value is 10. Full example:
public class SplitPaneTest extends JFrame {
public SplitPaneTest() {
super("test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel left = new JPanel();
JPanel right = new JPanel();
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right);
System.out.println(sp.getDividerSize()); //Prints 10
sp.setDividerSize(1);
add(sp, BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new SplitPaneTest().setVisible(true);
});
}
}
However, Look & Feels are capable of changing the way it looks since they change its UI. If the above solution does not work for you, you will have to mess with its UI. For example, in one of my applications I did not want any line (while using Windows Look and Feel), so in order to make it invisible I had to:
sp.setUI(new BasicSplitPaneUI() {
#Override
public BasicSplitPaneDivider createDefaultDivider() {
return new BasicSplitPaneDivider(this) {
private static final long serialVersionUID = -6000773723083732304L;
#Override
public void paint(Graphics g) {
//Divider gets no painting
}
};
}
});

Resize JTextArea only vertical

What is the best way to resize JTextArea vertical? I think I shoud put JTextArea into JScrollPane (and I can make a simple pane with scrollbar). But I want to JTextArea scroll by mouse vertical. I tried to use class according to this tut.:
https://tips4java.wordpress.com/2009/09/13/resizing-components/, but it is able to resize component with all sides.
I want something like here:
http://www.w3schools.com/cssref/playit.asp?filename=playcss_resize&preval=vertical
or something like textarea which you use to post answer to topic here.
EDIT:
My piece of code with class ComponentResizer (from https://tips4java.wordpress.com/2009/09/13/resizing-components/)
package textsamplerdemo;
import javax.swing.*;
import java.awt.*;
public class TextSamplerDemo extends JPanel {
public TextSamplerDemo() {
setLayout(new BorderLayout());
JTextArea textArea = new JTextArea(10, 20);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(textArea);
ComponentResizer componentResizer = new ComponentResizer();
componentResizer.registerComponent(scrollPane);
add(scrollPane, BorderLayout.PAGE_START);
}
/**
* Create the GUI and show it. For thread safety, this method should be
* invoked from the event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("TextSamplerDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add content to the window.
frame.add(new TextSamplerDemo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatching thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
but it is able to resize component with all sides.
The ComponentResizer supports a maximum size property. So you can do something like:
JTextArea textArea = new JTextArea(5, 20);
ScrollPane scrollPane = new JScrollPane( textArea );
Dimension d = scrollPane.getPreferredSize();
d.height = Toolkit.getDefaultToolkit().getScreenSize().height;
ComponentResizer cr = new ComponentResizer();
cr.setMaximumSize(d));
cr.registerComponent(scrollPane);

JLabel that changes text from one thing to another

I'm working on this program and I ran into another issue. I have a Jframe with a JLabel that I wish for it to change text from one thing to another. However, when I try to do that it doesnt show me the text changing, rather the last text I set it to.
How do I get my JLabel to cycle through text SLOWLY?
I'm trying a wait method to make the program go slowly so I can see if I can make it cycle through, but that doesnt seem to be working.
it would be helpful if someone could edit my code or make their own example of how to do this, THANKS!
public class CreditGraphics {
public String cardNum;
public JFrame frame;
public JPanel panel;
public JLabel label;
public JTextField text;
public CreditGraphics() {
synchronized(this){
try {
frame = new JFrame("HI");
panel = new JPanel();
label = new JLabel();
text = new JTextField(16);
panel.add(label);
panel.add(text);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel.setPreferredSize(new Dimension(500, 500));
frame.getContentPane().add(panel);
frame.pack();
frame.setVisible(true);
wait(4000);
label.setText("Hi");
wait(4000);
frame.revalidate();
frame.repaint();
label.setText("Hello");
frame.revalidate();
frame.repaint();
text.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardNum = text.getText();
}
});
}
catch(InterruptedException e) {
e.printStackTrace();
}}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new CreditGraphics();
}
});
}
public void checkCard(){
}
}
As suggested by #trashgod use Swing Timer that is more suitable for swing application to perform a task once, after a delay or to perform a task repeatedly.
sample code:
private Timer timer;
...
label.setText("Hi");
// delay of 4 seconds
timer=new Timer(4000,new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
label.setText("Hello");
// timer.stop(); // stop the timer if repeated mode is on
}
});
timer.setRepeats(false); // you can turn-on it if needed
timer.start();
Note:
There is no need to call frame.repaint() and frame.revalidate() in this case.
Override getPreferredSize() to set the preferred size of the JPanel in case of custom painting.
sample code:
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(..., ...);
}
};
read more...
Do not use Thread.sleep() or wait() as it will freeze your Swing application.
Instead you should use a javax.swing.Timer
See the Java tutorial How to Use Swing Timers and Lesson: Concurrency in Swing for more information and examples.

Internal JFrames

I want to know how to show an internal frame in swing. That means,when a JFrame is needed, normally what I do is,
new MyJFrame().setVisible(true);
Let's say the previous form should be displayed as well. And when this new frame is displayed,another new icon is displayed on the task bar.(it sounds like two separate applications run in one application) I want to avoid showing that icon and display both frames as they are in one application. Thank you
..want to avoid showing that icon and display both frames as they are in one application.
Another solution is to put the 2nd and subsequent free floating elements in a JDialog.
E.G. of using both a frame and dialog to hold extra content.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class FrameTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
initGui();
}
});
}
public static void initGui() {
final JFrame f = new JFrame("Frame Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel gui = new JPanel(new GridLayout(0,1,5,5));
final Content c = new Content();
JButton frame = new JButton("Frame");
frame.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JFrame f2 = new JFrame("Content");
f2.add(c.getContent());
f2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f2.pack();
f2.setLocationByPlatform(true);
f2.setVisible(true);
}
});
gui.add(frame);
JButton dialog = new JButton("Dialog");
dialog.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JDialog d = new JDialog(f);
d.add(new Content().getContent());
d.pack();
d.setLocationByPlatform(true);
d.setVisible(true);
}
});
gui.add(dialog);
f.add(gui);
f.pack();
f.setVisible(true);
}
}
class Content {
public Component getContent() {
JPanel p = new JPanel();
p.add(new JLabel("Hello World!"));
return p;
}
}
You have one JFrame for an application.
You can display multiple JPanels within a JFrame.
Or, as trashgod pointed out, you can have multiple JInternalFrames within a JDesktopFrame.

JTextArea in JScrollPane, view coordinate translation

I'm trying to translate between view and viewport coordinates.
But the JViewport/JScrollpane doesn't seem to work as documented. JViewport.toViewCoordinates()
thinks the view is always at the top left of the component, even though that's clearly not the case.
String text = "blahblahblah\nblahblah\nblah";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30); // shows only one line
frame.add(new JScrollPane(textArea));
frame.pack();
frame.setVisible(true);
textArea.setCaretPosition(text.length()); // now showing the last line
JViewport viewport = ((JViewport)textArea.getParent());
viewport.getViewRect(); // returns java.awt.Rectangle[x=0,y=0,width=330,height=16]
viewport.getViewPosition(); // returns java.awt.Point[x=0,y=0]
viewport.toViewCoordinates(new Point(0,0)); // returns java.awt.Point[x=0,y=0]
The above is contrived example. My real JTextArea is larger than one line. I don't need JTextArea "model" coordinate (the offset in the text). I need genuine 2d coordinates.
The view position shouldn't be (0,0), as the first visible character in the viewport is actually in the 3rd line of the JTextArea.
Any other suggestions on how I can translate between view and component coordinates when using JScrollPane?
--- added ---
This also fails.
SwingUtilities.convertPoint(viewport,0,0, textArea);
(java.awt.Point) java.awt.Point[x=0,y=0]
--- added ---
Here is the final working version, based on the answer I received.
it shows java.awt.Point[x=0,y=32] which is what I expected.
#Test
public void test() throws InterruptedException {
String text = "blahblahblah\nblahblah\nblah";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30);
frame.add(new JScrollPane(textArea));
frame.pack();
frame.setVisible(true);
textArea.setCaretPosition(text.length());
final JViewport viewport = ((JViewport)textArea.getParent());
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run() {
System.out.println(viewport.getViewPosition());
}
});
Thread.sleep(1000);
}
The problem is that the method to get the viewPosition() executes before the viewport has actually been scrolled. This is because sometimes Swing adds code to the end of the event thread for later processing.
Usually this problem can be solved by wrapping your code in a SwingUtilities.invokeLater() so the code is executed after Swing has done all its processing. However in the simple demo below I found I needed to add two invokeLater() methods. I'm not sure why.
Move the caret up/down and you will see the view position change. The second value will contain the correct position:
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test5
{
public static void createAndShowGUI()
{
String text = "one\ntwo\nthree\nfour\nfive";
JFrame frame = new JFrame("title");
JTextArea textArea = new JTextArea(text, 1, 30); // shows only one line
JScrollPane scrollPane = new JScrollPane( textArea );
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
final JViewport viewport = scrollPane.getViewport();
textArea.addCaretListener( new CaretListener()
{
public void caretUpdate(CaretEvent e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("First : " + viewport.getViewPosition() );
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
System.out.println("Second: " + viewport.getViewPosition() );
}
});
}
});
}
});
textArea.setCaretPosition(text.length());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
could
SwingUtilities.convertPoint
be of use?

Categories