I want to create a vertical list of items with a bottom status line such that when it gets resized, the space between the items and the bottom line grows. UsingMigLayout this must be pretty trivial, but somehow it isn't.
The following code does exactly what I want, but I had to use a component to do the spacing:
final JFrame frame = new JFrame();
final JPanel panel = new JPanel(new MigLayout("wrap, debug", "[grow, fill]", ""));
for (int i=0; i<5; ++i) {
final JEditorPane line = new JEditorPane();
line.setText("a" + i);
panel.add(line);
}
panel.add(new JLabel(), "push"); // This should be a gap!
final JLabel status = new JLabel("status line");
panel.add(status, "");
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
I guess I could specify the growing gap in the third constructor argument, but the list length is variable. This could be all solved, too, but I doubt it's the best practice. What I was hoping for, was something like gaptop push, but it seems to do nothing at all.
What am I doing wrong? Is there an argument doing what I want?
MigLayout is a very powerful manager indeed. This could be accomplished
in multiple ways. I provide three solutions.
Solution 1
We put a greedy gap between row 5 and 6.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class MigLayoutGapGrow extends JFrame {
public MigLayoutGapGrow() {
initUI();
setTitle("Gaps");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout("wrap", "[grow, fill]", "[][][][][]20:push[]"));
add(new JTextField("a"+1));
add(new JTextField("a"+2));
add(new JTextField("a"+3));
add(new JTextField("a"+4));
add(new JTextField("a"+5));
final JLabel status = new JLabel("status line");
add(status);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutGapGrow ex = new MigLayoutGapGrow();
ex.setVisible(true);
}
});
}
}
Solution 2
We enlarge the last cell in which the label is placed. The label is then
aligned to the bottom.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class MigLayoutGapGrow2 extends JFrame {
public MigLayoutGapGrow2() {
initUI();
setTitle("Gaps");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout("wrap, debug", "[grow, fill]"));
add(new JTextField("a"+1));
add(new JTextField("a"+2));
add(new JTextField("a"+3));
add(new JTextField("a"+4));
add(new JTextField("a"+5));
final JLabel status = new JLabel("status line");
add(status, "pushy, bottom");
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutGapGrow2 ex = new MigLayoutGapGrow2();
ex.setVisible(true);
}
});
}
}
Solution 3
The label is attached to the bottom using relative positioning. Relative
positioning does not seem to work with the pack() method and this might
be a problem.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;
public class MigLayoutGapGrow3 extends JFrame {
public MigLayoutGapGrow3() {
initUI();
setTitle("Gaps");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout("wrap", "[grow, fill]"));
add(new JTextField("a"+1), "id a1");
add(new JTextField("a"+2));
add(new JTextField("a"+3));
add(new JTextField("a"+4));
add(new JTextField("a"+5));
final JLabel status = new JLabel("status line");
add(status, "pos a1.x visual.y2-p");
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutGapGrow3 ex = new MigLayoutGapGrow3();
ex.setVisible(true);
}
});
}
}
If you add push on the component it has a different semnatic. From the docs:
Makes the row and/or column that the component is residing in grow with "weight". This can be used instead of having a "grow" keyword in the column/row constraints.
So you have to add the push keyword as the row constraint.
Related
How can I make the JMenuBar streak dissapear after the menuitems? I want to put a 2nd menu in the middle of the frame, and it looks weird with this streak.
I tried to set the background to Panel.background but it doesn't work.
import java.awt.*;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.UIManager;
public class SwingMenuDemo extends JPanel {
public SwingMenuDemo(){
setLayout(null);
JMenuBar menuBar = new JMenuBar();
menuBar.setBackground(UIManager.getColor("Panel.background"));
menuBar.setBounds(0, 0, 450, 25);
add(menuBar);
JButton btn1 = new JButton("Menu1");
menuBar.add(btn1);
JButton btn2 = new JButton("Menu2");
menuBar.add(btn2);
JButton btn3 = new JButton("Menu3");
menuBar.add(btn3);
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("SwingMenuDemo");
frame.setPreferredSize(new Dimension(400,400));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(),BoxLayout.PAGE_AXIS));
frame.getContentPane().add(new SwingMenuDemo());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
If you want to create your own "menu" of several JButtons, then don't use JMenu and don't use null layout and setBounds(...) (you should avoid the latter just as a general rule). Instead nest JPanels, each using its own layout manager to allow for simple creation of complex GUI's.
For instance you could create a JPanel to hold the buttons, say called menuPanel, give it a new GridLayout(1, 0) layout, meaning it will hold a grid of components in 1 row, and a variable number of columns (that's what the 0 means). Then put your buttons in that.
Then place that JPanel into another JPanel that uses say FlowLayout.LEADING, 0, 0) as its layout -- it will push all its components to the left.
Then make the main GUI use a BorderLayout and add the above panel to it's top in the BorderLayout.PAGE_START position. For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.*;
#SuppressWarnings("serial")
public class SwingMenuDemo2 extends JPanel {
private static final String[] MENU_TEXTS = {"Menu 1", "Menu 2", "Menu 3"};
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
public SwingMenuDemo2() {
JPanel menuPanel = new JPanel(new GridLayout(1, 0));
for (String menuText : MENU_TEXTS) {
menuPanel.add(new JButton(menuText));
}
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
topPanel.add(menuPanel);
setLayout(new BorderLayout());
add(topPanel, BorderLayout.PAGE_START);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
SwingMenuDemo2 mainPanel = new SwingMenuDemo2();
JFrame frame = new JFrame("Swing Menu Demo 2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
You can do that with
menuBar.setBorderPainted(false);
I am relatively new to programming, so I am sorry if this question is stupid. I am creating a Java program that involves one JButton inside a JPanel, and the JPanel is in a JFrame. Another button is outside the JPanel but still in the JFrame. I set the layout to a BoxLayout. My problem is that the the panel, which I made black, is taking up the whole JFrame except for where the second button is. How do I make the JPanel so it is only taking up the area right around the first button?
public class alt {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton button1 = new JButton("button 1");
JButton button2 = new JButton("button 2");
public alt(){
frame.setVisible(true);
frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS));
panel.setBackground(Color.black);
frame.setTitle("test");
frame.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
panel.add(button1);
frame.add(panel);
frame.add(button2);
button2.setAlignmentX(Component.CENTER_ALIGNMENT);
}
}
You could make use of a different layout manager, one which gives you more control over deciding how space is allocated and filling is handled, for example, GridBagLayout...
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class SampleLayout {
public static void main(String[] args) {
new SampleLayout();
}
public SampleLayout() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JPanel panel = new JPanel();
JButton button1 = new JButton("button 1");
JButton button2 = new JButton("button 2");
panel.setBackground(Color.black);
panel.add(button1);
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
frame.add(panel, gbc);
frame.add(button2, gbc);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Take a look at Laying Out Components Within a Container for more details
The reason why your panel takes up the bulk of the frame's content pane lies
in the way the BoxLayout manager works with the minimum, preferred,
and maximum values of components. It takes the maximum value of a component
into account. And since the maximum value of a JPanel is huge, it takes
all the space available. The solution is to change the maximum value
of a panel. However, this is bad practice. I do not recommend to use
the BoxLayout manager -- it is very weak and leads to poor code.
I recommend to use either the MigLayout manager or the GroupLayout manager.
I provide three solutions: a corrected BoxLayout solution, a MigLayout solution,
and a GroupLayout solution.
BoxLayout solution
We determine the maximum size of the button and change the panel's size
to be a bit larger than the button's.
package com.zetcode;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BoxLayoutPanel extends JFrame {
public BoxLayoutPanel() {
initUI();
}
private void initUI() {
JPanel cpane = (JPanel) getContentPane();
cpane.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
cpane.setLayout(new BoxLayout(cpane,
BoxLayout.Y_AXIS));
JPanel pnl = new JPanel();
JButton btn1 = new JButton("Button 1");
JButton btn2 = new JButton("Button 2");
Dimension dm = btn1.getMaximumSize();
dm.height += 15;
dm.width += 15;
pnl.setMaximumSize(dm);
pnl.setBackground(Color.black);
add(pnl);
add(Box.createVerticalStrut(10));
pnl.add(btn1);
btn2.setAlignmentX(Component.CENTER_ALIGNMENT);
add(btn2);
setTitle("BoxLayout solution");
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
BoxLayoutPanel ex = new BoxLayoutPanel();
ex.setVisible(true);
}
});
}
}
This is not a clean solution. Generally, we should avoid calling the getMaximumSize() and
the setMaximumSize() in the application code -- this is the layout manager's job. Also in three occasions, we use fixed pixel widths: when we define an empty border, a vertical strut, and a maximum panel's size. This code is however not portable.
Pixel widths change when the resolution of the screen changes. This is a
shortcoming of the BoxLayout manager.
MigLayout solution
This solution is much cleaner and more portable. MigLayout is a third-party
manager, so we need to download additional libraries.
package com.zetcode;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutPanel extends JFrame {
public MigLayoutPanel(){
initUI();
setTitle("MigLayout solution");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void initUI() {
JPanel main = new JPanel(new MigLayout("center"));
JPanel pnl2 = new JPanel();
JButton btn1 = new JButton("Button 1");
JButton btn2 = new JButton("Button 2");
pnl2.setBackground(Color.black);
pnl2.add(btn1);
main.add(pnl2, "wrap");
main.add(btn2, "alignx center");
add(main);
pack();
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutPanel ex = new MigLayoutPanel();
ex.setVisible(true);
}
});
}
}
GroupLayout solution
GroupLayout is a built-in layout manager. With MigLayout, they are the most
portable and flexible layout managers.
package com.zetcode;
import java.awt.Color;
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.GroupLayout;
import static javax.swing.GroupLayout.Alignment.CENTER;
import static javax.swing.GroupLayout.DEFAULT_SIZE;
import static javax.swing.GroupLayout.PREFERRED_SIZE;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
public class GroupLayoutPanel extends JFrame {
public GroupLayoutPanel(){
initUI();
setTitle("GroupLayout solution");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
Container pane = getContentPane();
GroupLayout gl = new GroupLayout(pane);
pane.setLayout(gl);
JPanel pnl = new JPanel();
JButton btn1 = new JButton("Button 1");
pnl.add(btn1);
JButton btn2 = new JButton("Button 2");
pnl.setBackground(Color.black);
gl.setAutoCreateGaps(true);
gl.setHorizontalGroup(gl.createSequentialGroup()
.addContainerGap(DEFAULT_SIZE, Integer.MAX_VALUE)
.addGroup(gl.createParallelGroup(CENTER)
.addComponent(pnl, DEFAULT_SIZE, DEFAULT_SIZE,
PREFERRED_SIZE)
.addComponent(btn2))
.addContainerGap(DEFAULT_SIZE, Integer.MAX_VALUE)
);
gl.setVerticalGroup(gl.createSequentialGroup()
.addContainerGap()
.addComponent(pnl, DEFAULT_SIZE, DEFAULT_SIZE,
PREFERRED_SIZE)
.addPreferredGap(RELATED)
.addComponent(btn2)
.addContainerGap()
);
pack();
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
GroupLayoutPanel ex = new GroupLayoutPanel();
ex.setVisible(true);
}
});
}
}
I have been trying to make a layout with MigLayout that consists of 3 panels, one on the right, one on top, and one that fills the rest of the space.
Like this:
There are several solutions possible. I provide two examples.
In both examples we also set the preferred width and height of
the panels. Normally, the panels would derive their preferred with from
their children.
The first layout is done with the dock constraint.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutThreePanels extends JFrame {
public MigLayoutThreePanels() {
initUI();
setTitle("Three panels");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout());
JPanel pnl1 = new JPanel();
pnl1.setBorder(BorderFactory.createEtchedBorder());
JPanel pnl2 = new JPanel();
pnl2.setBorder(BorderFactory.createEtchedBorder());
JPanel pnl3 = new JPanel();
pnl3.setBorder(BorderFactory.createEtchedBorder());
add(pnl2, "w 40, dock east");
add(pnl1, "h 40, dock north");
add(pnl3, "w 250, h 200, dock center");
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutThreePanels ex = new MigLayoutThreePanels();
ex.setVisible(true);
}
});
}
}
The three panels are docked to east, north, and center. Additional spaces between
panels can be created with the gap constraints.
In the second example, we use utilize the grid structure.
package com.zetcode;
import java.awt.EventQueue;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
public class MigLayoutThreePanels2 extends JFrame {
public MigLayoutThreePanels2() {
initUI();
setTitle("Three panels");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
private void initUI() {
setLayout(new MigLayout("gap 3 3"));
JPanel pnl1 = new JPanel();
pnl1.setBorder(BorderFactory.createEtchedBorder());
JPanel pnl2 = new JPanel();
pnl2.setBorder(BorderFactory.createEtchedBorder());
JPanel pnl3 = new JPanel();
pnl3.setBorder(BorderFactory.createEtchedBorder());
add(pnl1, "h 40, growx");
add(pnl2, "w 40, spany 2, growy, wrap");
add(pnl3, "w 250, h 200, grow, push");
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
MigLayoutThreePanels2 ex = new MigLayoutThreePanels2();
ex.setVisible(true);
}
});
}
}
In this example, we also set some gaps between the cells and container insets.
I'm trying to put my jpanel in the middle of the frame... so when the user try to change the size of the window frame, it remain in the middle...
something like this:
so if i change size it have to remain in the middle:
i Tried to change the layout of my contentPane with the BorderLayout and put my jpanel in the center position... but when i change size of my frame the panel go in the top left corner.
In my windows builder the situation is this:
my jpanel have to work exactly how works the redbox. i tried everything but the result is everytime the same:
this is my code:
package StudApp;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JTextPane;
import javax.swing.JLabel;
import java.awt.Font;
import javax.swing.SwingConstants;
import java.awt.Color;
import javax.swing.JTextArea;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class StudApp {
private JFrame frame;
private JPanel homeFirstRun;
private ArrayList<Corso> corsi = new ArrayList<Corso>();
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
new StudApp();
}
});
}
/**
* Create the frame.
*/
public StudApp() {
frame = new JFrame("Student Note");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 450, 300);
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
JMenu menuHelp = new JMenu("Help");
menuBar.add(menuHelp);
JMenuItem menuIstrStud = new JMenuItem("Intructions Student Note");
menuIstrStud.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
frame.remove(homeFirstRun);
frame.revalidate();
frame.repaint();
homeFirstRun = null;
}
});
menuHelp.add(menuIstrStud);
homeFirstRun = new JPanel();
homeFirstRun.setBorder(new EmptyBorder(5, 5, 5, 5));
homeFirstRun.setLayout(null);
frame.getContentPane().add(homeFirstRun);
JLabel welcomeMessage = new JLabel("Welcome to Student Note");
welcomeMessage.setBounds(5, 5, 424, 18);
welcomeMessage.setForeground(Color.DARK_GRAY);
welcomeMessage.setHorizontalAlignment(SwingConstants.CENTER);
welcomeMessage.setFont(new Font("Verdana", Font.BOLD, 14));
homeFirstRun.add(welcomeMessage);
JTextArea welcomeTextArea = new JTextArea();
welcomeTextArea.setFont(new Font("Verdana", Font.PLAIN, 13));
welcomeTextArea.setText(" I think it's your first time here.\n\n"
+ " So the first step is to create a new course to\n insert your grades.\n\n"
+ " If you want my advice, read how this program\n works in the help section (it is very simple),\n "
+ "just 2 minutes ... believe me");
welcomeTextArea.setEditable(false);
welcomeTextArea.setBounds(27, 34, 381, 184);
homeFirstRun.add(welcomeTextArea);
frame.setVisible(true);
}
}
There are several ways to do this, but one of the easiest is to give the contentPane a GridBagLayout, and then add your JPanel of interest with no GridBagConstraints. If the JPanel of interest is the only thing added to this container, this will then place that JPanel into a central position.
e.g.,
import java.awt.*;
import javax.swing.*;
public class CentralPanel {
private static void createAndShowGui() {
JFrame frame = new JFrame("CentralPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new MyContentPane());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyContentPane extends JPanel {
private static final int PREF_W = 700;
private static final int PREF_H = 550;
public MyContentPane() {
setLayout(new GridBagLayout());
add(new JPanelOfInterest());
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
class JPanelOfInterest extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = PREF_W;
public JPanelOfInterest() {
setBorder(BorderFactory.createTitledBorder("JPanel of Interest"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
}
I am trying to extend the StyledEditorKit in Swing to be able to include a JLabel inside the editor. I was able to do that and this is what I got so far. In the image below, the highlighted text button is of type JLabel whereas the rest of the text is normal text.
As you can see the label renders a little below than the normal text. How do I align its top with top of the remaining text?
Here is the code for the view that is used to create this label element:
class ComponentView(Element elem) {
#Override
protected Component createComponent() {
JLabel lbl = new JLabel("");
lbl.setOpaque(true);
lbl.setBackground(Color.red);
try {
int start = getElement().getStartOffset();
int end = getElement().getEndOffset();
String text = getElement().getDocument().getText(start, end - start);
lbl.setText(text);
} catch (BadLocationException e) {}
return lbl;
}
}
Try adjusting Component.getAlignmentY that controls the positioning of component relative to the text baseline as suggested in ComponentView.
You could also try using JTextPane that provides easier support for embedded components. Components can be added using insertComponent() method. Here is an example, it also demos setAlignmentY:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
public class TextPaneDemo {
private static void createAndShowGUI() {
final JTextPane pane = new JTextPane();
pane.setText("Some text");
JButton buttonButton = new JButton("Insert label");
buttonButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JLabel label = new JLabel("label");
label.setAlignmentY(0.85f);
pane.insertComponent(label);
}
});
JPanel panel = new JPanel(new BorderLayout());
panel.add(buttonButton, BorderLayout.SOUTH);
panel.add(pane, BorderLayout.CENTER);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setSize(400, 200);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}