JTabbedPane spacing - java

Original Top tab orientation setting:
http://dl.dropbox.com/u/3238736/screenshots/Screenshot-PasswordStore-1.png
Problematic Right tab orientation setting:
From the GUI above, my JTabbedPane (the blue colour tab on the right) is overlapping the "Quit" button (which is rendered using a GlassPane).
Note: Quit button is rendered onto top right using GlassPane.
I would like some technical advise on moving the blue colour tab to give some spacing for the "Quit" button ?
Codes for creating the GlassPane to insert the Quit button as shown below:
public void addUniversalQuitBtn() {
// Thanks to http://www.java-forums.org/awt-swing/12267-how-add-jbutton-tabbed-pane-headder.html forum post regarding adding a button on glasspane.
Rectangle tabBounds = mainTabPane.getBoundsAt(0);
Container glassPane = (Container) this.getRootPane().getGlassPane();
glassPane.setVisible(true);
glassPane.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.weightx = 1.0;
gbc.weighty = 1.0;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(tabBounds.y, 0, 0, 10);
gbc.anchor = GridBagConstraints.NORTHEAST;
quitBtn.setPreferredSize(new Dimension(quitBtn.getPreferredSize().width, (int) tabBounds.getHeight() - 2));
glassPane.add(quitBtn, gbc);
}
Thanks.

Well, i'd offer you to move the quit button from glasspane to some proper container but with standart Swing JTabbedPane you can't put it that way...
So here is some sort of solution:
public static void main ( String[] args )
{
JFrame frame = new JFrame ();
Insets current = UIManager.getInsets ( "TabbedPane.tabAreaInsets" );
UIManager.put ( "TabbedPane.tabAreaInsets",
new Insets ( current.top, 40, current.bottom, current.right ) );
JTabbedPane tabbedPane = new JTabbedPane ();
tabbedPane.setTabPlacement ( JTabbedPane.RIGHT );
tabbedPane.addTab ( "Tab 1", new JLabel () );
tabbedPane.addTab ( "Tab 2", new JLabel () );
frame.add ( tabbedPane );
UIManager.put ( "TabbedPane.tabAreaInsets", current );
JTabbedPane tabbedPane2 = new JTabbedPane ();
tabbedPane2.setTabPlacement ( JTabbedPane.RIGHT );
tabbedPane2.addTab ( "Tab 3", new JLabel () );
tabbedPane2.addTab ( "Tab 4", new JLabel () );
frame.add ( tabbedPane2, BorderLayout.SOUTH );
frame.setSize ( 400, 400 );
frame.setLocationRelativeTo ( null );
frame.setVisible ( true );
}
First tabbed pane (top one) has 30px gap between top side and tabs. The second tabbed pane has default gap set.
By changing the insets under "TabbedPane.tabAreaInsets" key you can manipulate the spacings between tabs run and tabbed pane sides. Be aware that those insets are rotated when tab position differs from TOP. So if you want to modify the top spacing with RIGHT tabs position you should modify the left one but not the top one, like i did in my example.
And don't forget to put the old Insets value back, otherwise that change will affect ALL tabbed panes created after the change.
Also i cannot guarantee that this will work for all of the native UIs, but i think such basic features should be supported. Atleast it is supported in Windows, Mac OS and Metal LaFs.
One more thing - you won't be able to change tab area Insets in runtime for already created tabbed pane, since it is saved into specific system UI when it is created and it is not possible to update that value (atleast without using Reflection "features" and violently accesing private fields). So you will have to recreate the tabbed pane if you want that gap only in one kind of tab placement.

ok. sounds a bit strange to me... but you could have 2 Buttons: one in the GlassPane (visible if TabbedPane is oriented top) and one in the Bar at the top (visible if TabbedPane is oriented right)

Related

Java Swing - MigLayout: Docking a component in center isn't fully centering

I am attempting to design a panel with MiGFormat that has a label at the top, and two buttons at the bottom - a yes/no prompt.
I achieve this closely, but the label yesOrNoText (text is "TEST") is not fully centered:
I initialize the panel containing this prompt like so:
private JPanel createYesNoPrompt() {
JPanel panel = new JPanel(new MigLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.red));
JButton yesButton = new JButton("Yes");
JButton noButton = new JButton("No");
yesOrNoText = new JLabel();
yesOrNoText.setText("TEST");
yesOrNoText.setFont(panel.getFont().deriveFont(Font.BOLD, 30f));
yesOrNoText.setHorizontalAlignment(SwingConstants.CENTER);
Dimension dimension = new Dimension(500, 125);
Font font = panel.getFont().deriveFont(Font.BOLD, 20f);
yesButton.setFont(font);
yesButton.setBackground(new Color(35, 138, 35));
yesButton.setPreferredSize(dimension);
noButton.setFont(font);
noButton.setBackground(new Color(183, 19, 19));
noButton.setPreferredSize(dimension);
yesButton.addActionListener(e -> isYes = true);
noButton.addActionListener(e -> isYes = false);
panel.add(yesOrNoText, "wrap, dock center");
panel.add(yesButton);
panel.add(noButton);
return panel;
}
Then, I add it to gamePanel, then gamePanel to mainPanel, then mainPanel to the frame.
gamePanel.add(YesOrNoPanel, "align center");
mainPanel.add(gamePanel);
add(mainPanel);
I'm unsure of what would be causing yesOrNoText to not become fully centered within the YesNoPanel. Please let me know if I need to clarify anything!
Thank you.
I needed to make the add call for the yesNo label span 2 cells. By adding one component in the first row, then adding two in the next, I essentially created a 2x2 grid.
panel.add(yesOrNoText, "wrap, align center, span 2 1");
panel.add(yesButton);
panel.add(noButton);
Notice that on the first component I add yesOrNoText I use span to tell MiGFormat to take up two cells for this component. I can then center that with the remaining two components because it becomes the only component in the row.

Add scroll-lock button to JScrollBar

Background
Looking to add a scroll-lock button to the corner of JScrollPane without obscuring the view port contents. The following image shows a JScrollPane wrapped in a SwingNode within a JavaFX application:
The lower-right corner shows a button with a lock icon that may be toggled, which is the desired result:
Notice how the content at the very bottom of the view port---the portion beside the lock button---is visible. (Clicking the button will simulate pressing the scroll-lock button on the keyboard. Having a scroll-lock button at the top is perfectly fine, if that's any easier.)
Problem
The JScrollPane API shows the following image:
Enabling the corner component also seems to require adding a column header. The addition of the header obscures part of the view port, in direct proportion to the scroll-lock button height. Here's a screenshot showing the visible column header, which hides part of the document:
Ideas
I've tried making the header view panel transparent, to no avail.
Code
The relevant code within the SwingNode:
// FlyingSaucer subclass
mView = new HtmlPanel();
mScrollPane = new JScrollPane( mView );
setContent( mScrollPane );
final var lock = new JButton( "X" );
mScrollPane.setCorner( UPPER_TRAILING_CORNER, lock );
mScrollPane.setVerticalScrollBarPolicy( VERTICAL_SCROLLBAR_ALWAYS );
final var header = new JPanel();
header.setPreferredSize(
new Dimension( 12, lock.getPreferredSize().height ) );
header.setOpaque( false );
header.setBackground( new Color( 0, 0, 0, 0 ) );
mScrollPane.setColumnHeaderView( header );
See camickr's answer for another example.
Question
How would you add a button to JScrollPane's bottom (or top) corner such that no view port content is obscured?
Related
How to make a corner component always visible in a JScrollPane
I would suggest using "wrapper" panels to achieve you desired layout. Something like:
JButton scrollLock = new JButton("...");
JScrollPane scrollPane = new JScrollPane(...);
JScrollBar verticalBar = scrollPane.getVerticalScrollBar();
JPanel verticalPanel = new JPanel( new BorderLayout() );
verticalPanel.add(verticalBar, BorderLayout.CENTER);
verticalPanel.add(scrollLock, BorderLayout.PAGE_END);
JPanel wrapper = new JPanel( new BorderLayout() );
wrapper.add(scrollPane, BorderLayout.CENTER);
wrapper.add(verticalPanel, BorderLayout.LINE_END);
setContent(wrapper);

Scrolling issue (Java-JFrame-JScrollBar)

INTRO:
I created a java application using JFrame. I have a JMenuBar at the top and under that I'd like to display rows of text.
PURPOSE:
When I have 50 rows and only 20 are displayable at once, I'd like to be able to scroll down and back up again.
PROBLEM:
Of course, my theory doesn't wanna work as it should. My problem is that I don't know how to add a vertical scroll properly.
QUESTION:
How should I change this code to reach my goal?
public void display(){
Container content = this.window.getContentPane();
content.setLayout(new BorderLayout());
Border border = LineBorder.createGrayLineBorder();
//this is just a sample
for(int i = 0;i<50;i++){
JLabel lab = new JLabel("lonyaladek");
lab.setSize(570, 20);
lab.setBorder(border);
lab.setLocation(10, 20+(i*25));
content.add(lab);
}
//scroll
JScrollBar sb = new JScrollBar(JScrollBar.VERTICAL, 0, 0, 0, 0);
content.add(sb);
}
First you need to start with a layout manager that allows you to add multiple components to the container. Maybe a GridLayout is the best place to start.
Then you add this container to the scrollPane and then you add the scrollpane to the window.
So the basic code would be:
JPanel panel = new JPanel( new GridLayout(0, 1) );
panel.add(...);
panel.add(...);
JScrollPane scrollPane = new JScrollPane( panel );
window.add(scrollPane, BorderLayout.CENTER);
I suggest you read the section from the Swing tutorial on How to Use Scroll Panes for more info.

Java Swing and Component Positioning

I am creating a base class for the JFrames of my application. I would like to inject a JXSearchField in the top right and corner of all frames that inherit from this class. I have a web background and know CSS fairly well. The effect I am going for is a float:right; or Fixed position, where other elements are not effected by the height of this component.
An example of what I am talking about would be a JFrame with a JTabbedPane aligned at the top. My tab pane only has three tabs but my frame is 800px wide. This gives me plenty of space for my top right aligned search box but my tabbedpane is reserving that space for additional tabs. I want to float in or fix position my searchbox to overlay that space.
if I understand correctly, you want to paint the TextField over the JTabbedPane beside the Tabs?
There is no easy way in swing doing this. You can use a glassPane-Component which draw the TextField on top right. And set it to the Frame.
UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName() );
JFrame frame = new JFrame();
frame.setBounds( 50, 50, 800, 600 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JPanel glasspane = new JPanel(new FlowLayout(FlowLayout.RIGHT));
frame.setGlassPane( glasspane );
glasspane.setOpaque( false );
JTextField textField = new JTextField("Search");
glasspane.add(textField);
glasspane.setVisible( true );
JTabbedPane tabs = new JTabbedPane();
tabs.setBorder( BorderFactory.createEmptyBorder( 10, 5, 5, 5 ) );
tabs.addTab( "Lorem", null );
tabs.addTab( "Ipsum", null );
tabs.addTab( "Dolor", null );
frame.setContentPane( tabs );
frame.setVisible( true );
A Good Layout that a lot of people use for organizing SWING components is the GridBagLayout
GridBagLayout

How do i get vertical scrolling to JPanel?

I have written a code in java using swing, so that I will have a JscrollPane added to JPanel and then I will add buttons of fixed size to JPanel in vertical fashion
JPanel panel=new JPanel();
panel.setBackground(Color.WHITE);
int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
JScrollPane jsp=new JScrollPane(panel,v,h);
jsp.setPreferredSize(new Dimension(600,600));
jsp.setBounds(150,670,850,200);
frame.add(jsp);
then I am adding buttons to it at run time.
for(i=0;i<n;i++)
{
button[i]=new JButton();
button[i].setBounds(20,y,120,120);
button[i].setSize(120,120);
button[i].setToolTipText(file[i].toString());
button[i].setIcon(Icon);
panel.add(button[i]);
y=y+140;
}
I want to add a buttons one below the other...(i.e I want a vertical scrollbar)
i.e. button1
button2
'
'
but above code is giving me buttons in a line (i.e. I am getting horizontal scrollbar)
i.e. button1 button2...
another problem is the size of the buttons. Using btn.setSize() is not affecting size at all...
can anybody help me?
You must use an appropriate Layoutmanager like GridLayout, Boxlayout or GridBagLayout for the panel.
It depends what else you want to put into the panel.
GridLayout is easier to use IMO:
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1)); // any number of rows, 1 column
...
panel.add(button[i]);
BoxLayout is almost as easy:
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
...
panel.add(button[i]);
GridBagLayout is more powerful, allowing more than one column, components spanning more than one cell, ... needs a GridBagConstraints to add the elements:
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints(
0, RELATIVE, // x = 0, y = below previous element
1, 1, // cell width = 1, cell height = 1
0.0, 0.0 // how to distribute space: weightx = 0.0, weighty = 0,0
GridBagConstraints.CENTER, // anchor
GridBagConstraints.BOTH, // fill
new Insets(0, 0, 0, 0), // cell insets
0, 0); // internal padding
...
panel.add(button[i], constraints);
Have a look at this tutorial: Laying Out Components Within a Container (The visual guide is a good start point)
EDIT:
you can also lay out the components by hand, that is, specify the location and size of each component in the container. For this you must set the LayoutManager to null so the default manager gets removed.
JPanel panel = new JPanel();
panel.setLayout(null);
...
button[i].setLocation(x, y);
button[i].setSize(width, heigth);
// OR button[i].setBounds(x, y, width, height);
panel.add(button[i]);
You need to define an appropriate LayoutManager for your JPanel, which is responsible for how the Components added to it are positioned. The default LayoutManager is FlowLayout, which lays out Components left-to-right. For laying out Components vertically you should consider using BoxLayout or GridBagLayout.
You have to set LayoutManager for JPanel or use Box(BoxLayout.Y_AXIS) instead.
For the size of buttons use preferredSize
For your layout problem you need to change the layout manager to one that does a vertical layout. For playing around purposes you can use BoxLayout like this:
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
This is much easier if you let the layout manager do its work.
In Swing, the way the components are layout over other component ( a panel for instance ) is using a layout manager.
It is used to avoid having to compute the coordinates of all the components against each other each time the container component resizes, or a new component is added.
There are different layout mangers, the one that you need here is BoxLayout.
By using this layout you don't need to specify the button position, nor its size. The layout manager query each component and use that information to place them in the correct position and size.
For instance the following frame
Was created this ( modified version of your ) code:
import javax.swing.*;
import java.awt.*;
public class ScrollTest {
private JPanel panel;
private Icon[] icons = new Icon[3];
public void main() {
panel =new JPanel();
// Use top to bottom layout in a column
panel.setLayout( new BoxLayout( panel, BoxLayout.Y_AXIS ));
panel.setBackground(Color.WHITE);
int v=ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
int h=ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS;
JScrollPane jsp=new JScrollPane(panel,v,h);
jsp.setPreferredSize(new Dimension(600,600));
jsp.setBounds(150,670,850,200);
JFrame frame = new JFrame();
frame.add(jsp);
// my addition to load sample icons
loadImages();
// simulate dynamic buttons
addButtons();
frame.pack();
frame.setVisible( true );
}
void loadImages() {
icons[0] = new ImageIcon( "a.png" );
icons[1] = new ImageIcon( "b.png" );
icons[2] = new ImageIcon( "c.png" );
}
void addButtons() {
for( int i = 0 ; i < icons.length ; i++ ) {
JButton button = new JButton();
Icon icon = icons[i];
button.setIcon( icon );
// Set the button size to be the same as the icon size
// The preferred size is used by the layout manager
// to know what the component "better" size is.
button.setPreferredSize( new Dimension( icon.getIconWidth(),
icon.getIconHeight() ) );
// This is IMPORTANT. The maximum size is used bythe layout manager
// to know "how big" could this component be.
button.setMaximumSize( button.getPreferredSize() );
panel.add( button );
}
}
public static void main( String ... args ) {
new ScrollTest().main();
}
}
I hope this helps.
One can also get a vertical scrolling for JPanel with SpringLayout. It's possible if panel's vertical size will be defined by setting a constraint SpringLayout.SOUTH. This can be done like this:
JPanel panel = new JPanel();
SpringLayout panelLayout = new SpringLayout();
panel.setLayout(panelLayout);
// Adding components to the panel here
// .....
// That's what defines panel's exact size and makes its scrolling possible
panelLayout.putConstraint(SpringLayout.SOUTH, panel, 0,
SpringLayout.SOUTH, lastComponentOfThePanel);
JScrollPane panelScrollPane = new JScrollPane(panel);
where lastComponentOfThePanel is a component at the bottom of a panel.
Hope this will help somebody. In my opinion, SpringLayout is very powerful layout manager, and sometimes it's very difficult or almost impossible to replace this one with GridBagLayout.
What about?
JScrollPane scrollPane = new JScrollPane(yourpanel);
container.add(scrollPane);

Categories

Resources