How can I print a JPanel content in another JPanel? - java

I'm creating a GUI with two JPanels, one for typing and another to show the same text that I type in the first JPanel. How can I make the second JPanel printable? Is there a way to show in the second JPanel the same text that I type in the first JPanel?

You'll want to have them share the same Document.
textArea2.setDocument(textArea1.getDocument());
public void createAndShowGUI() {
// ... frame, panel etc.
// each panel has BorderLayout
scrollPane1 = new JScrollPane();
panel1.add(scrollPane1, BorderLayout.CENTER);
scrollPane2 = new JScrollPane();
panel2.add(scrollPane2, BorderLayout.CENTER);
textArea1 = new JTextArea();
scrollPane1.setViewportView(textArea1);
textArea1.requestFocus();
textArea2 = new JTextArea();
scrollPane2.setViewportView(textArea2);
textArea2.setEditable(false);
textArea1.getDocument().addDocumentListener(new MyDocumentListener());
textArea2.getDocument().addDocumentListener(new MyDocumentListener());
}
class MyDocumentListener implements DocumentListener {
public void insertUpdate(DocumentEvent e) {
textArea2.setDocument(textArea1.getDocument());
textArea1.setCaretPosition(textArea1.getDocument().getLength());
textArea2.setCaretPosition(textArea2.getDocument().getLength());
}
public void removeUpdate(DocumentEvent e) {
textArea2.setDocument(textArea1.getDocument());
textArea1.setCaretPosition(textArea1.getDocument().getLength());
textArea2.setCaretPosition(textArea2.getDocument().getLength());
}
public void changedUpdate(DocumentEvent e) {
// Plain text components don't fire these events.
}
}
From: The Tutorials and this and this.
EDIT:
Here is the full example of this implementation:
import javax.swing.*;
import java.awt.*;
import javax.swing.text.*;
import javax.swing.event.*;
class DocumentListenerTest {
JFrame frame;
JPanel panel, panel1, panel2;
JScrollPane scrollPane1, scrollPane2;
JTextArea textArea1, textArea2;
JSplitPane splitPane;
public DocumentListenerTest() {
createAndShowGUI();
}
public void createAndShowGUI() {
frame = new JFrame("Copy Text");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setMinimumSize(new Dimension(200, 200));
panel = new JPanel();
panel.setLayout(new BorderLayout(5, 5));
frame.setContentPane(panel);
panel1 = new JPanel();
panel1.setLayout(new BorderLayout());
panel.add(panel1);
panel2 = new JPanel();
panel2.setLayout(new BorderLayout());
panel.add(panel2, BorderLayout.SOUTH);
scrollPane1 = new JScrollPane();
panel1.add(scrollPane1, BorderLayout.CENTER);
scrollPane2 = new JScrollPane();
panel2.add(scrollPane2, BorderLayout.CENTER);
textArea1 = new JTextArea();
scrollPane1.setViewportView(textArea1);
textArea1.requestFocus();
textArea2 = new JTextArea();
scrollPane2.setViewportView(textArea2);
textArea2.setEditable(false);
splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane1, scrollPane2);
panel.add(splitPane, BorderLayout.CENTER);
splitPane.setDividerLocation(0.5);
splitPane.setResizeWeight(0.5);
textArea1.getDocument().addDocumentListener(new MyDocumentListener());
textArea2.getDocument().addDocumentListener(new MyDocumentListener());
frame.pack();
frame.setVisible(true);
}
class MyDocumentListener implements DocumentListener {
public void insertUpdate(DocumentEvent e) {
textArea2.setDocument(textArea1.getDocument());
//textArea1.setCaretPosition(textArea1.getDocument().getLength());
//textArea2.setCaretPosition(textArea2.getDocument().getLength());
textArea2.setCaretPosition(textArea1.getCaretPosition());
}
public void removeUpdate(DocumentEvent e) {
textArea2.setDocument(textArea1.getDocument());
//textArea1.setCaretPosition(textArea1.getDocument().getLength());
//textArea2.setCaretPosition(textArea2.getDocument().getLength());
textArea2.setCaretPosition(textArea1.getCaretPosition());
}
public void changedUpdate(DocumentEvent e) {
// Plain text components don't fire these events.
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new DocumentListenerTest();
}
});
}
}
Here is a sample gif:

Related

How to make JPanel fill the entire JFrame?

I am making an UI in a minecraft plugin. Everything is working, except I have a JPanel and it doesn't fill the whole JFrame. So what I want is the JPanel fill the entire JFrame even if we re-scale the window.
I use Layout manager (FlowLayout) for the JPanel.
I tried using a Layout manager for the JFrame, well it didn't solved my problem because it didn't resize the JPanel.. I tried setting the size of the JPanel to the JFrame's size, but when it's resized it doesn't scale with it.
So, how can I do this?
My plugin creates a button for every player and when I click the button it kicks the player.
My code (I can't really post less because I don't know where I need to change something):
public static JFrame f;
public static JTextField jtf;
public static JPanel jp;
public static void creategui()
{
System.out.println("GUI created.");
f = new JFrame("Players");
jp = new JPanel();
jp.setLayout(new FlowLayout(FlowLayout.LEFT));
jp.setBackground(Color.GRAY);
jtf = new JTextField("Reason");
jtf.setPreferredSize(new Dimension(200,20));
jtf.setToolTipText("Write the reason here.");
jp.setSize(new Dimension(200,200));
f.setLayout(null);
f.setSize(500,500);
f.setVisible(true);
jp.add(jtf);f.add(jp, BorderLayout.CENTER);
for (final Player p : Bukkit.getOnlinePlayers())
{
System.out.println("Looping.");
final JButton b = new JButton();
b.setName(p.getName());
b.setText(p.getName());
b.setToolTipText("Kick " + b.getText());
b.setBackground(Color.GREEN);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!b.getBackground().equals(Color.RED))
{
Bukkit.getScheduler().runTask(main, new Runnable() {
public void run() {
Bukkit.getPlayer(b.getText()).kickPlayer(jtf.getText());
b.setBackground(Color.RED);
}
});
}
}
});
jp.add(b);
System.out.println("Button added.");
}
f.add(jp, BorderLayout.CENTER);
}
The question should include an mcve reproducing the problem so we can test it.
It could look like this :
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.util.Arrays;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Mcve {
private static List<String> players = Arrays.asList(new String[]{"Player A", "Player B"});
public static void main(String[] args) {
creategui();
}
public static void creategui()
{
JPanel jp = new JPanel();
jp.setBackground(Color.GRAY);
JTextField jtf = new JTextField("Reason");
jtf.setPreferredSize(new Dimension(200,20));
jtf.setToolTipText("Write the reason here.");
jp.setSize(new Dimension(200,200));
jp.add(jtf);
for (final String p : players)
{
final JButton b = new JButton();
b.setText(p);
b.setBackground(Color.GREEN);
b.addActionListener(e -> {
if (!b.getBackground().equals(Color.RED))
{
b.setBackground(Color.RED);
}
});
jp.add(b);
}
JFrame f = new JFrame("Players");
f.setLayout(null);
f.setSize(500,500);
f.add(jp, BorderLayout.CENTER);
f.setVisible(true);
}
}
To make the JPanel fill the entire frame simply remove this line :
f.setLayout(null);
and let the default BorderLayout manager do its work.
Here is a modified version with some additional comments:
public class Mcve {
private static List<String> players = Arrays.asList(new String[]{"Player A", "Player B"});
public static void main(String[] args) {
creategui();
}
public static void creategui()
{
JPanel jp = new JPanel();
jp.setBackground(Color.GRAY);
JTextField jtf = new JTextField("Reason");
jtf.setPreferredSize(new Dimension(200,20));
jtf.setToolTipText("Write the reason here.");
jp.setPreferredSize(new Dimension(250,200)); // set preferred size rather than size
jp.add(jtf);
for (final String p : players)
{
final JButton b = new JButton();
b.setText(p);
b.setBackground(Color.GREEN);
b.addActionListener(e -> {
if (!b.getBackground().equals(Color.RED))
{
b.setBackground(Color.RED);
}
});
jp.add(b);
}
JFrame f = new JFrame("Players");
//f.setLayout(null); null layouts are bad practice
//f.setSize(500,500); let layout managers set the sizes
f.add(jp, BorderLayout.CENTER);
f.pack();
f.setVisible(true);
}
}
A 1x1 grid layout does the job quite nicely.
window = new JFrame();
panel = new JPanel();
window.setLayout(new java.awt.GridLayout(1, 1));
window.add(panel);
Either set the layout manager for jp (the JPanel in the code you posted) to BorderLayout and add jtf (the JTextField in the code you posted) to the CENTER of jp, as in:
f = new JFrame();
jp = new JPanel(new BorderLayout());
jtf = new JTextField(30); // number of columns
jp.add(jtf, BorderLayout.CENTER);
f.add(jp, BorderLayout.CENTER);
or dispense with jp and add jtf directly to f (the JFrame in the code you posted), as in:
f = new JFrame();
jtf = new JTextField(30);
f.add(jtf, BorderLayout.CENTER);
The key is that the CENTER component of BorderLayout expands to fill the available space.
So I fixed it somehow, this is the code:
public static void creategui()
{
System.out.println("GUI created.");
f = new JFrame("Players");
jp = new JPanel();
jp.setBackground(Color.GRAY);
jp.setSize(200,200);
jtf = new JTextField(30);
jtf.setToolTipText("Write the reason here.");
jp.add(jtf);
for (final Player p : Bukkit.getOnlinePlayers())
{
System.out.println("Looping.");
final JButton b = new JButton();
b.setName(p.getName());
b.setText(p.getName());
b.setToolTipText("Kick " + b.getText());
b.setBackground(Color.GREEN);
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (!b.getBackground().equals(Color.RED))
{
Bukkit.getScheduler().runTask(main, new Runnable() {
public void run() {
getplr(b.getText()).kickPlayer(jtf.getText());
b.setBackground(Color.RED);
}
});
}
}
});
jp.add(b);
System.out.println("Button added.");
}
f.setLayout(new BorderLayout());
f.add(jp, BorderLayout.CENTER);
f.setSize(500,500);
f.pack();
f.setVisible(true);
}

Swing panels inside panel not showing

I'm trying to create a JFrame with one main panel contains two panels: left sub-panel has add and remove buttons which will dynamically add and remove components; right panel contains regular component. My code works find when there is only one panel, fails when used inside sub-panel.
public class MultiPanel extends JFrame{
static MultiPanel myFrame;
static int countMe = 0;
JPanel mainPanel;
JPanel userPanel;
JPanel contentPanel;
private static void iniComponents() {
myFrame = new MultiPanel();
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.prepareUI();
myFrame.pack();
myFrame.setVisible(true);
}
private void prepareUI() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("My Title");
setPreferredSize(new java.awt.Dimension(1280, 720));
setSize(new java.awt.Dimension(1280, 720));
mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS));
userPanel = new JPanel();
// userPanel.setLayout(new BoxLayout(userPanel, BoxLayout.Y_AXIS));
mainPanel.add(userPanel);
JButton buttonAdd = new JButton("Add subPanel");
buttonAdd.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
userPanel.add(new subPanel());
myFrame.pack();
}
});
JButton buttonRemoveAll = new JButton("Remove All");
buttonRemoveAll.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
userPanel.removeAll();
myFrame.pack();
}
});
contentPanel = new JPanel();
JLabel jLabel1 = new JLabel("Content here");
contentPanel.add(jLabel1);
mainPanel.add(contentPanel);
GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(mainPanel)
);
layout.setVerticalGroup(
layout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(mainPanel)
);
// getContentPane().add(userPanel, BorderLayout.WEST);
// getContentPane().add(contentPanel, BorderLayout.EAST);
// getContentPane().add(buttonAdd, BorderLayout.PAGE_START);
// getContentPane().add(buttonRemoveAll, BorderLayout.PAGE_END);
}
private class subPanel extends JPanel {
subPanel me;
public subPanel() {
super();
me = this;
JLabel myLabel = new JLabel("This is subPanel(): " + countMe++);
add(myLabel);
JButton myButtonRemoveMe = new JButton("remove me");
myButtonRemoveMe.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
me.getParent().remove(me);
myFrame.pack();
}
});
add(myButtonRemoveMe);
}
}
public static void main(String args[]) {
SwingUtilities.invokeLater(() -> {
iniComponents();
});
}
}
I also wonder what is the proper way to write about the layout, aligning and organizing components seems to be painful for me.

ScrollPane not showing on JLabel

When I run this program, I don't see a scrollbar on the Label. What am I missing?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Util1
{
public static void main(String[] args)
{
new Util1();
}
public Util1()
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ExamplePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class ExamplePane extends JPanel
{
public ExamplePane()
{
final JPanel panel = new JPanel(new GridBagLayout());
final JLabel message = new JLabel("<html>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello</html>");
message.setPreferredSize(new Dimension(500, 50));
JScrollPane scroller = new JScrollPane( message, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroller.setViewportView(message);
panel.add(scroller);
add(panel);
}
}
}
To see a scrollbar wrap the "message" JLabel into JPanel and then add this JPanel to JScrollPane like bellow:
public ExamplePane() {
final JPanel panel = new JPanel(new GridBagLayout());
final JLabel message = new JLabel("<html>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello<br>Hello</html>");
message.setPreferredSize(new Dimension(500, 50));
final JPanel messagePanel = new JPanel();
messagePanel.add(message);
JScrollPane scroller = new JScrollPane(messagePanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroller.setPreferredSize(new Dimension(100, 50));
panel.add(scroller);
add(panel);
}

Why JPanel.focusGaind and Lost don't work?

Please take a look at the following code (I've missed the imports purposely)
public class MainFrame extends JFrame {
private JPanel contentPane;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainFrame frame = new MainFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MainFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
tabbedPane.setBounds(10, 11, 414, 240);
contentPane.add(tabbedPane);
JPanel panel = new JPanel();
panel.addFocusListener(new FocusListener() {
#Override
public void focusLost(FocusEvent arg0) {
System.out.println("lost");
// I want to do something here, if I reach here!
}
#Override
public void focusGained(FocusEvent arg0) {
System.out.println("gained");
// I want to do something here, if I reach here!
}
});
tabbedPane.addTab("New tab", null, panel, null);
JButton button = new JButton("New button");
panel.add(button);
JPanel panel_1 = new JPanel();
tabbedPane.addTab("New tab", null, panel_1, null);
JPanel panel_2 = new JPanel();
tabbedPane.addTab("New tab", null, panel_2, null);
}
}
I've created this class to test it and then add the onFocusListener in my main code, but it's not working the way I expect. Please tell what's wrong or is this the right EvenetListener at all?
JPanels are not focusable by default. If you ever wanted to use a FocusListener on them, you'd first have to change this property via setFocusable(true).
But even if you do this, a FocusListener is not what you want.
Instead I'd look to listen to the JTabbedPane's model for changes. It uses a SingleSelectionModel, and you can add a ChangeListener to this model, listen for changes, check the component that is currently being displayed and if your component, react.
You are using setBounds and null layouts, something that you will want to avoid doing if you are planning on creating and maintaining anything more than a toy Swing program.
Edit
For example:
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.*;
#SuppressWarnings("serial")
public class MainPanel extends JPanel {
private static final int PREF_W = 450;
private static final int PREF_H = 300;
private static final int GAP = 5;
private static final int TAB_COUNT = 5;
private JTabbedPane tabbedPane = new JTabbedPane();
public MainPanel() {
for (int i = 0; i < TAB_COUNT; i++) {
JPanel panel = new JPanel();
panel.add(new JButton("Button " + (i + 1)));
panel.setName("Panel " + (i + 1));
tabbedPane.add(panel.getName(), panel);
}
setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
tabbedPane.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent evt) {
Component component = tabbedPane.getSelectedComponent();
System.out.println("Component Selected: " + component.getName());
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
MainPanel mainPanel = new MainPanel();
JFrame frame = new JFrame("MainPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
JPanel is a lightweight container and it is not a Actionable component so it does not get focus events. It lets you add focus listener because of swing component hierarchy. In Order to get tab selected events you need to use JTabbedPane#addChangeListener.
Hope this helps.

Dynamically add components to a JDialog on button click

I want to know how to add components dynamically to a JDialog. I know there is a similar question on SO here, but as you can see, I have his solution as a part of my code.
So the idea is that on click of the button, I need to add a component on the dialog. The sample code is below:
import java.awt.Container;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Test extends JFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static void main(String args[]) {
Test test = new Test();
test.createDialog();
}
public void createDialog() {
DynamicDialog dialog = new DynamicDialog(this);
dialog.setSize(300, 300);
dialog.setVisible(true);
}
}
class DynamicDialog extends JDialog {
/**
*
*/
private static final long serialVersionUID = 1L;
public DynamicDialog(final JFrame owner) {
super(owner, "Dialog Title", Dialog.DEFAULT_MODALITY_TYPE);
final JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
final JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.add(Box.createRigidArea(new Dimension(3, 10)));
panel.add(createLabel("Click on add"));
panel.add(Box.createRigidArea(new Dimension(23, 10)));
panel.add(createLabel("To add another line of text"));
panel.add(Box.createHorizontalGlue());
mainPanel.add(panel);
mainPanel.add(Box.createRigidArea(new Dimension(3, 10)));
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
buttonPanel.add(Box.createHorizontalGlue());
JButton button = new JButton();
button.setText("Add another line");
buttonPanel.add(button);
mainPanel.add(buttonPanel);
mainPanel.add(Box.createRigidArea(new Dimension(3, 10)));
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
Container contentPane = owner.getContentPane();
JPanel _panel = new JPanel();
_panel.setLayout(new BoxLayout(_panel, BoxLayout.X_AXIS));
_panel.add(Box.createHorizontalGlue());
_panel.add(createLabel("Added!"));
contentPane.add(_panel);
contentPane.validate();
contentPane.repaint();
owner.pack();
}
});
pack();
setLocationRelativeTo(owner);
this.add(mainPanel);
}
JLabel createLabel(String name) {
JLabel label = new JLabel(name);
return label;
}
}
If you add it to the main panel it will work, you were adding it to the content pane of the frame which it seems it does not show up anywhere.
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
JPanel _panel = new JPanel();
_panel.setLayout(new BoxLayout(_panel, BoxLayout.X_AXIS));
_panel.add(Box.createHorizontalGlue());
_panel.add(createLabel("Added!"));
mainPanel.add(_panel);
mainPanel.validate();
mainPanel.repaint();
owner.pack();
}
})

Categories