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);
}
Related
I am making a GUI application, and I made a JPanel with JScrollPane. The problem is that when adding elements to it, first few elements taking all available space, which looks ugly. How can I prevent them from that?
Here is the code:
import javax.swing.*;
import java.awt.*;
public class VersionPanel extends JPanel {
private final JPanel panel;
public VersionPanel() {
this.setLayout(new BorderLayout());
this.panel = new JPanel(new GridLayout(0, 1));
JScrollPane scrollPane = new JScrollPane(this.panel);
scrollPane.setPreferredSize(new Dimension(400, 300));
this.add(scrollPane, BorderLayout.CENTER);
}
public void addVersionLabel(VersionLabel label) {
this.panel.add(label);
this.panel.revalidate();
int height = (int) this.panel.getPreferredSize().getHeight();
this.panel.scrollRectToVisible(new Rectangle(0, height, 10, 10));
}
}
Here is the code of VersionLabel:
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.*;
import java.awt.event.ActionListener;
public class VersionLabel extends JPanel {
private final ActionListener launch;
private final ActionListener delete;
private final ActionListener install;
public VersionLabel(String versionNumber, boolean installed, ActionListener launch, ActionListener delete, ActionListener install) {
this.launch = launch;
this.delete = delete;
this.install = install;
this.setLayout(new GridLayout(1, 2));
this.add(this.getLeftPanel(versionNumber, installed));
this.add(this.getRightPanel(installed));
this.setBorder(new BevelBorder(BevelBorder.RAISED, Color.RED, Color.RED)); //test border
this.setMaximumSize(this.getMinimumSize());
}
private JPanel getLeftPanel(String versionNumber, boolean installed) {
return new JPanel() {{
this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
this.add(new JLabel(versionNumber));
this.add(new JLabel(installed ? "Installed" : "Not Installed"));
}};
}
private JPanel getRightPanel(boolean installed) {
return new JPanel(new FlowLayout(FlowLayout.RIGHT)) {{
if(installed) {
this.add(new JButton("Launch") {{ this.addActionListener(launch); }});
this.add(new JButton("Delete") {{ this.addActionListener(delete); }});
} else {
this.add(new JButton("Install") {{ this.addActionListener(install); }});
}
}};
}
}
Thanks to #DontKnowMuchButGettingBetter! I added a new JPanel to my code:
public VersionPanel() {
this.setLayout(new BorderLayout());
this.panel = new JPanel(new GridLayout(0, 1));
JPanel bPanel = new JPanel(new BorderLayout());
bPanel.add(this.panel, BorderLayout.PAGE_START);
JScrollPane scrollPane = new JScrollPane(bPanel);
scrollPane.setPreferredSize(new Dimension(400, 300));
this.add(scrollPane, BorderLayout.CENTER);
}
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:
class CipherGUIFrame extends JFrame {
public CipherGUIFrame() {
super("Caesar Cipher GUI");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 600);
JTextArea area1 = new JTextArea();
JTextArea area2 = new JTextArea();
JSpinner myspinner=new JSpinner();
JPanel mainframe = new JPanel();
mainframe.setLayout(new BoxLayout(mainframe, BoxLayout.Y_AXIS));
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
JPanel p3 = new JPanel();
p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS));
p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
p1.setBorder(BorderFactory.createTitledBorder("Cleartext"));
p2.setBorder(BorderFactory.createTitledBorder("Spinner"));
p3.setLayout(new BoxLayout(p3, BoxLayout.Y_AXIS));
p3.setBorder(BorderFactory.createTitledBorder("Ciphertext"));
p1.add(area1);
p2.add(myspinner);
p3.add(area2);
mainframe.add(p1);
mainframe.add(p2);
mainframe.add(p3);
this.add(mainframe);
}
}
It seems that this code produces something which looks similar to this:
I am trying to tidy this up so it looks cleaner; is there a way to shrink the middle panel or to make the others bigger to make it look nicer?
Don't set the sizes of anything, but instead set the columns and rows of your JTextAreas. Don't use BoxLayout when you don't want its behaviors. Put your JTextAreas in JScrollPanes instead. And don't forget to pack() your JFrame.
import java.awt.BorderLayout;
import javax.swing.*;
public class Cipher2 extends JPanel {
public static final int ROWS = 12;
public static final int COLS = 30;
private JTextArea textArea1 = new JTextArea(ROWS, COLS);
private JTextArea textArea2 = new JTextArea(ROWS, COLS);
public Cipher2() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); // Box OK here
JScrollPane scroll1 = new JScrollPane(textArea1);
add(wrapComponentWithTitle(scroll1, "Fubar"), BorderLayout.PAGE_START);
add(wrapComponentWithTitle(new JSpinner(), "Spinner"), BorderLayout.CENTER);
scroll1 = new JScrollPane(textArea2);
add(wrapComponentWithTitle(scroll1, "Snafu"), BorderLayout.PAGE_END);
}
private JPanel wrapComponentWithTitle(JComponent component, String title) {
// BoxLayout NOT OK here. Use BorderLayout instead
JPanel wrapPanel = new JPanel(new BorderLayout());
wrapPanel.add(component);
wrapPanel.setBorder(BorderFactory.createTitledBorder(title));
return wrapPanel;
}
private static void createAndShowGui() {
Cipher2 mainPanel = new Cipher2();
JFrame frame = new JFrame("Foo");
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(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I figured out the answer: change Y_AXIS to X_AXIS.
<3
I am trying to add two buttons below the JTextArea using the Eclipse WindowBuilder, but I can't. I tried to change the layout, but I couldn't find a way to add buttons where I want and to re-size the JTextArea in an easy way.
public TestScrollPane03() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JTextArea textArea = new JTextArea(100, 50);
JScrollPane scrollPane = new JScrollPane(textArea);
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(scrollPane);
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
How would I go about adding buttons below my original textArea?
You need to have two panels, one for your textArea, and one for your input (in this case buttons). I think something like this is what you are looking for:
public class Test
{
public static void createFrame()
{
EventQueue.invokeLater(new Runnable()
{
#Override
public void run()
{
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(true);
JTextArea textArea = new JTextArea(15, 50);
textArea.setWrapStyleWord(true);
textArea.setEditable(false);
textArea.setFont(Font.getFont(Font.SANS_SERIF));
JScrollPane scroller = new JScrollPane(textArea);
scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
JPanel inputpanel = new JPanel();
inputpanel.setLayout(new FlowLayout());
JTextField input = new JTextField(20);
JButton button = new JButton("Enter");
DefaultCaret caret = (DefaultCaret) textArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
panel.add(scroller);
inputpanel.add(input);
inputpanel.add(button);
panel.add(inputpanel);
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
frame.setResizable(false);
input.requestFocus();
}
});
}
public static void main(String... args)
{
createFrame();
}
}
If you want your frame to look more like those of the OS you are running on, you can add .setLookAndFeel() before you make the frame visible:
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
What adding the UIManager looks like (notably a bit smaller):
i made this code to navigate trough panel1 and panel2
with buttons.
(button1 and button2) but when i run my code the frame stays empty.
Can somebody explain me what i'm doing wrong and how i can accomplish
toggling between panel1 and panel2 in this way? Starting with panel1 first
Code:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
public class togglepanel {
public static void main(String[] args) {
final JFrame frame = new JFrame();
final JPanel panel1 = new JPanel();
final JPanel panel2 = new JPanel();
JButton button1 = new JButton("previous frame!");
JButton button2 = new JButton("next frame");
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setVisible(true);
frame.setSize(600, 400);
frame.add(panel1);
frame.add(panel2);
panel1.add(button2);
panel1.setVisible(true);
panel2.add(button1);
panel2.setVisible(false);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
panel1.setVisible(true);
panel2.setVisible(false);
}
});
button2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
panel1.setVisible(false);
panel2.setVisible(true);
}
});
}
}
thanks in advance
Use a layout manager.
frame.setLayout(new FlowLayout());
Another useful way to do this, and I think better is to use a CardLayout and to add both JPanels to a container that uses this CardLayout. You can then easily swap views by calling the CardLayout methods.
e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TogglePanel {
public static void main(String[] args) {
final CardLayout cardlayout = new CardLayout();
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Container contentPane = frame.getContentPane();
contentPane.setLayout(cardlayout);
final JPanel panel1 = new JPanel();
final JPanel panel2 = new JPanel();
JButton button1 = new JButton("previous frame!");
JButton button2 = new JButton("next frame");
contentPane.setPreferredSize(new Dimension(600, 400));
contentPane.add(panel1, "Panel 1");
contentPane.add(panel2, "Panel 2");
frame.pack();
frame.setLocationRelativeTo(null);
frame.setResizable(true);
frame.setVisible(true);
panel1.add(button2);
panel2.add(button1);
ActionListener btnListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardlayout.next(contentPane);
}
};
button1.addActionListener(btnListener);
button2.addActionListener(btnListener);
}
}