Make JTextPane's Text Move Sideways Instead of a New Line - java

I am working with the JTextPane and am trying to make the text move sideways instead of a newline like the JTextField. I have tried searching and looking through the JTextPane's API but I haven't found anything useful. Could someone show me some type of method or process (that can be used in a main class) that could help me? Thanks you!
P.S.
I am aware of using the JScrollPane, but I would like to avoid that since I would like the JTextPane to look like a JTextField as much as possible.

JTextPane textPane = new JTextPane();
JPanel noWrapPanel = new JPanel( new BorderLayout() );
noWrapPanel.add( textPane );
JScrollPane scrollPane = new JScrollPane( noWrapPanel );
Solution Source
Plus:
JScrollPane.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_NEVER);
JScrollPane.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_NEVER);
EDIT:
Solution without JScrollPane
import java.awt.Component;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.plaf.ComponentUI;
import javax.swing.text.StyledDocument;
public class NonWrappingTextPane extends JTextPane {
public NonWrappingTextPane() {
super();
}
public NonWrappingTextPane(StyledDocument doc) {
super(doc);
}
// Override getScrollableTracksViewportWidth
// to preserve the full width of the text
#Override
public boolean getScrollableTracksViewportWidth() {
Component parent = getParent();
ComponentUI ui = this.getUI();
return parent != null ? (ui.getPreferredSize(this).width <= parent.getSize().width) : true;
}
// Test method
public static void main(String[] args) {
String content = "The plaque on the Apollo 11 Lunar Module\n"
+ "\"Eagle\" reads:\n\n"
+ "\"Here men from the planet Earth first\n"
+ "set foot upon the Moon, July, 1969 AD\n"
+ "We came in peace for all mankind.\"\n\n"
+ "It is signed by the astronauts and the\n"
+ "President of the United States.";
JFrame f = new JFrame("Non-wrapping Text Pane Example");
JPanel p = new JPanel();
NonWrappingTextPane nwtp = new NonWrappingTextPane();
nwtp.setText(content);
p.add(nwtp);
f.getContentPane().setLayout(new GridLayout(2, 1));
f.getContentPane().add(p);
f.setSize(300, 200);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

Related

Java FlowLayout

I am writing some Java code that allows the user to see a frame with JLabel, JTextField and JButton.
I want the JLabel to be called "Count" and I have a problem with FlowLayout.
I want the interface to look like this:
Instead, I have this:
This is my code:
package modul1_Interfate_Grafice;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Exercitiu04 implements ActionListener {
private JFrame frame;
private JLabel labelCount;
private JTextField tfCount;
private JButton buttonCount;
private int count = 0;
public void go() {
frame = new JFrame("Java Counter");
labelCount = new JLabel("Counter");
labelCount.setLayout(new FlowLayout());
frame.getContentPane().add(BorderLayout.CENTER, labelCount);
tfCount = new JTextField(count + " ", 10);
tfCount.setEditable(false);
labelCount.add(tfCount);
buttonCount = new JButton("Count");
labelCount.add(buttonCount);
buttonCount.addActionListener(this);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(350, 150);
frame.setLocation(400, 200);
}
#Override
public void actionPerformed(ActionEvent event) {
count++;
tfCount.setText(count + "");
}
public static void main(String[] args) {
Exercitiu04 a = new Exercitiu04();
a.go();
}
}
Solve it.
Instead of labelCount.setLayout(new FlowLayout());` i should have had
frame.setLayout(new FlowLayout());
From description of JLabel class,
JLabel is:
A display area for a short text string or an image, or both.
But here: labelCount.add(tfCount) and here labelCount.add(buttonCount) you're trying to put a textfield and a button into a label. In this case, positions of button and textfield are controlled by FlowLayout but position of the text in the label is not.
Instead of this, you should put all of your elements in common JPanel, like this:
...
frame = new JFrame("Java Counter");
frame.setLayout(new BorderLayout());
JPanel wrapper = new JPanel(); // JPanel has FlowLayout by default
labelCount = new JLabel("Counter");
labelCount.setLayout(new FlowLayout());
wrapper.add(labelCount);
tfCount = new JTextField(count + " ", 10);
tfCount.setEditable(false);
wrapper.add(tfCount);
buttonCount = new JButton("Count");
buttonCount.addActionListener(this);
wrapper.add(buttonCount);
frame.add(BorderLayout.CENTER, wrapper);
...
And, like MasterBlaster said, you should put swing methods in EDT.
There are only two things you should know about FlowLayout:
a) It is a default layout manager of the JPanel component
b) It is good for nothing.
This trivial layout cannot be achieved with FlowLayout.
When doing layouts in Swing, you should familiarize yourself
with some powerful layout managers. I recommend MigLayout and
GroupLayout.
package com.zetcode;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
/*
Simple UI with a MigLayout manager.
Author Jan Bodnar
Website zetcode.com
*/
public class MigLayoutCounterEx extends JFrame {
public MigLayoutCounterEx() {
initUI();
}
private void initUI() {
JLabel lbl = new JLabel("Counter");
JTextField field = new JTextField(10);
JButton btn = new JButton("Count");
createLayout(lbl, field, btn);
setTitle("Java Counter");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void createLayout(JComponent... arg) {
setLayout(new MigLayout());
add(arg[0]);
add(arg[1]);
add(arg[2]);
pack();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MigLayoutCounterEx ex = new MigLayoutCounterEx();
ex.setVisible(true);
});
}
}
The example is trivial. You just put the three components into the
cells.
Screenshot:
You shouldn't use setSize when dealing with FlowLayout. Instead use pack(). It makes the window just about big enough to fit all your components in. That should tidy things up for you

Aligning and Inlining components (or icons) in JTextPane

I'm working on an application in Java which, among other things, is supposed to display the details of a Magic: The Gathering card in a text field (since I'm using Swing, this is currently a JTextPane).
Those details contain text and small icons, with some of those icons inlined with the text (so the text flows around them), and some icons, by my design, right-aligned with some left-aligned text in the same line.
I took an image from another application which uses a very similar design to the one I'm working on (although not in Java):
This is how it basically should look like.
Now, for the love of everything, I can't get that to work in a JTextPane.
I started with trying to do this with CSS, but found out that the JEditorPane and subclasses don't support the "float" attribute, so I tried it with using the Pane's StyledDocument instead.
I didn't get the first part to work (the icon and right-align text at the top always ignored their alignment and were placed directly after the left-aligned text in the line) at first, until I found this question.
It was suggested to use the following line of code:
pane.setEditorKit(new HTMLEditorKit());
which somehow indeed fixed my first issue.
But now I'm stuck at the second part, getting those icons in the second part inline with the text. Here's what I currently got:
What I've found is that for some reason, when you switch the JTextPane to html mode with an editor kit with the line of code above, inserting components just goes completely crazy.
Both the icons on the top (which I have merged into a single image actually), and the ones in the text below (not merged) are both inside of JLabels, but it doesn't matter if I add them as images or inside of JLabels. The images or labels are definitely not bigger than what you see there, I have no idea at all where the extra whitespace is coming from.
I found this question, and the answer suggest that this is some kind of bug or just weird behavior with the html mode of the JEditorPane.
If I remove the above code line again, I end up with my original problem:
Depending on where exactly the icons are in the text, I get all kinds of different weird results. I put together some more example pictures below:
So, how could I possibly fix this? The JTextPane is working fine for me, except for this part, but I could possibly use some other solution, as long as the end result still looks the same. Remember that I might want to add some other components (like a Button) in there, so I'd like to stick to something native to Swing if possible at all.
The user will not be able to edit the TextPane's contents, but I'd like to add an option later to copy all of the content in one click (so I'd rather stay with a text area).
Below, I have put together a (not really that minimal) working example for you to play around with:
(EDIT: Updated code at the bottom now! The old code is still there under the following link.)
http://pastebin.com/RwAdPCzb
The icons that I'm using are below. You'd need to rename them and change the path in the code.
Some things to notice:
In the beginning I styled the text using the `Style` class, as described in the "How to use Editor Panes and Text Panes" tutorial on the Oracle website (TextSamplerDemo.java, for your reference). With this, I wasn't even able to do the right-align part at the top. Strangely, when I used the `SimpleAttributeSet` class for styling instead, even with the very same settings, it works.
I tried different alignment options for both the text and the labels which contain the icons. Regardless of what options I used, there was no visible difference at all.
UPDATE 1:
After Sharcoux' answer, I have edited my code to have 2 JLabels above the actual JTextPane which hold the two lines that were supposed to have different alignings (a left- and a right-aligned part).
The JTextPane doesn't use a HTMLEditorKit anymore now, and I use insertIcon() to insert the icons into the text.
This way, the icons are inserted (almost) correctly!
Image here:
However, there are two small things that I'm still not satisfied with:
First:
I need to put everything into a JScrollPane because the text in the TextPane is much longer in my actual application. Since I now have three components instead of just the TextPane, I needed to put everything into a JPanel and that into the ScrollPane.
However, if you do it like this, the JTextPane doesn't know that its with should not exceed the JScrollPane's anymore. It stopps wrapping text and just grows as big as the entire text.
I have opened a new question for this, since I feel that this is a basic issue of Swing and deserves its own question. If you want to help, here is the link:
JTextComponent inside JPanel inside JScrollPane
Second:
This is probably not possible, but I guess I'll ask anyway. The icons have the same baseline as the text when you add them this way. Is they any way to move them just a bit lower? 2-3 pixels, maybe? They would align much better with the text that way. Two pictures below.
This is how it looks now:
And this is how I would like it to look:
Maybe I can subclass and override some part of the JTextPane to move all icons that are rendered on it down a set pixel amount, or something like that?
For reference, here is also my new, updated code. I replaced the old one above with a pastebin.com link, if you still want to look at it.
UPDATE 2:
My first problem has already been eliminated! I updated the code below to reflect that, too.
My second question still stands!
Here's the new code:
import java.awt.EventQueue;
import java.awt.Graphics2D;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
import javax.swing.JTextPane;
import javax.swing.JViewport;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import javax.swing.ScrollPaneConstants;
public class MinimalExample extends JFrame {
private JPanel contentPane;
private JScrollPane scrollPane;
private JTextPane textPane;
// Setup some data for an example card:
String name = "Absorb Vis";
String set = "CON";
String manaCost = "{6}{B}";
String printedType = "Sorcery";
String artist = "Brandon Kitkouski";
String rulesText = "Target player loses 4 life and you gain 4 life.\n"
+ "Basic landcycling {1}{B} ({1}{B}, Discard this card: "
+ "Search your library for a basic land card, reveal it, and put "
+ "it into your hand. Then shuffle your library.)";
HashMap<String, BufferedImage> manaSymbolImages;
private ScrollablePanel textPanel;
//private JPanel textPanel;
private JPanel headlinesPanel;
private JPanel firstHeadlinePanel;
private JPanel secondHeadlinePanel;
private JLabel titleLabel;
private JLabel manaCostLabel;
private JLabel typeLabel;
private JLabel setLabel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MinimalExample frame = new MinimalExample();
frame.setVisible(true);
}
catch (Exception e) {
e.printStackTrace();
}
}
});
}
public MinimalExample() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 230, 400);
contentPane = new JPanel();
contentPane.setBackground(Color.WHITE);
contentPane.setBorder(null);
setContentPane(contentPane);
/* HTMLEditorKit eKit = new HTMLEditorKit();
* textPane.setEditorKit(eKit); HTMLDocument htmlDoc = (HTMLDocument)
* textPane.getDocument(); htmlDoc.setPreservesUnknownTags(false); */
contentPane.setLayout(new GridLayout(0, 1, 0, 0));
textPanel = new ScrollablePanel();
//textPanel = new JPanel();
textPanel.setBackground(Color.WHITE);
textPanel.setLayout(new BorderLayout(0, 0));
headlinesPanel = new JPanel();
headlinesPanel.setBorder(new EmptyBorder(2, 5, 3, 5));
headlinesPanel.setBackground(Color.WHITE);
textPanel.add(headlinesPanel, BorderLayout.NORTH);
headlinesPanel.setLayout(new GridLayout(0, 1, 0, 0));
firstHeadlinePanel = new JPanel();
firstHeadlinePanel.setBorder(new EmptyBorder(0, 0, 3, 0));
firstHeadlinePanel.setOpaque(false);
headlinesPanel.add(firstHeadlinePanel);
firstHeadlinePanel.setLayout(new BorderLayout(0, 0));
titleLabel = new JLabel("");
titleLabel.setFont(new Font("Tahoma", Font.BOLD, 12));
firstHeadlinePanel.add(titleLabel, BorderLayout.WEST);
manaCostLabel = new JLabel("");
firstHeadlinePanel.add(manaCostLabel, BorderLayout.EAST);
secondHeadlinePanel = new JPanel();
secondHeadlinePanel.setBorder(null);
secondHeadlinePanel.setOpaque(false);
headlinesPanel.add(secondHeadlinePanel);
secondHeadlinePanel.setLayout(new BorderLayout(0, 0));
typeLabel = new JLabel("");
typeLabel.setFont(new Font("Tahoma", Font.PLAIN, 12));
secondHeadlinePanel.add(typeLabel, BorderLayout.WEST);
setLabel = new JLabel("");
setLabel.setFont(new Font("Tahoma", Font.BOLD, 12));
secondHeadlinePanel.add(setLabel, BorderLayout.EAST);
scrollPane = new JScrollPane();
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBackground(Color.WHITE);
contentPane.add(scrollPane);
textPane = new JTextPane();
textPane.setBorder(new EmptyBorder(0, 3, 0, 3));
textPane.setAlignmentY(0.3f);
textPane.setEditable(false);
textPanel.add(textPane, BorderLayout.CENTER);
scrollPane.setViewportView(textPanel);
loadManaCostIcons();
setPaneText();
}
// This part inserts the text into the document of the text pane.
public void setPaneText() {
titleLabel.setText(name);
manaCostLabel.setIcon(combineSymbols(manaCost));
typeLabel.setText(printedType);
setLabel.setText(set);
StyledDocument textPaneDoc = textPane.getStyledDocument();
SimpleAttributeSet defaultAtts = new SimpleAttributeSet();
StyleConstants.setFontFamily(defaultAtts, "SansSerif");
StyleConstants.setFontSize(defaultAtts, 12);
SimpleAttributeSet rulesAtts = new SimpleAttributeSet(defaultAtts);
SimpleAttributeSet artistAtts = new SimpleAttributeSet(defaultAtts);
StyleConstants.setFontSize(artistAtts, 10);
addTextWithSymbols(rulesText, rulesAtts);
try {
textPaneDoc.insertString(textPaneDoc.getLength(), artist, artistAtts);
}
catch (BadLocationException e) {
e.printStackTrace();
}
textPane.revalidate();
textPane.repaint();
}
/* This adds the rest of the text to the pane. The codes for the symbols get
* replaced by the actual symbols and the text gets inserted piece by piece. */
public void addTextWithSymbols(String text, SimpleAttributeSet style) {
StyledDocument textPaneDoc = textPane.getStyledDocument();
Pattern symbolPattern = Pattern.compile("\\{(.*?)\\}");
try {
Matcher symbolMatcher = symbolPattern.matcher(text);
int previousMatch = 0;
while (symbolMatcher.find()) {
int start = symbolMatcher.start();
int end = symbolMatcher.end();
String subStringText = text.substring(previousMatch, start);
String currentMatch = text.substring(start, end);
if (subStringText.isEmpty() == false) {
textPaneDoc.insertString(textPaneDoc.getLength(), subStringText, style);
}
ImageIcon currentIcon = new ImageIcon(manaSymbolImages.get(currentMatch));
SimpleAttributeSet iconAtts = new SimpleAttributeSet();
JLabel iconLabel = new JLabel(currentIcon);
StyleConstants.setComponent(iconAtts, iconLabel);
textPane.insertIcon(currentIcon);
previousMatch = end;
}
String subStringText = text.substring(previousMatch);
if (subStringText.isEmpty() == false) {
textPaneDoc.insertString(textPaneDoc.getLength(), subStringText + "\n", style);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/* Everything below is more or less irrelevant. However, you might need to
* adjust the image image file paths. */
public void loadManaCostIcons() {
manaSymbolImages = new HashMap<String, BufferedImage>();
try {
// Most likely, those paths won't work for you!
File bFile = new File("resource/B.png");
File c1File = new File("resource/1.png");
File c6File = new File("resource/6.png");
manaSymbolImages.put("{B}", ImageIO.read(bFile));
manaSymbolImages.put("{1}", ImageIO.read(c1File));
manaSymbolImages.put("{6}", ImageIO.read(c6File));
}
catch (IOException e) {
e.printStackTrace();
}
}
public ImageIcon combineSymbols(String symbols) {
String[] manaSymbols = symbols.split("(?<=})");
int combinedWidth = 0;
int maxHeight = 0;
for (int i = 0; i < manaSymbols.length; i++) {
BufferedImage currentSymbolImage = manaSymbolImages.get(manaSymbols[i]);
combinedWidth += currentSymbolImage.getWidth();
if (maxHeight < currentSymbolImage.getWidth()) {
maxHeight = currentSymbolImage.getWidth();
}
}
BufferedImage combinedManaCostImage = new BufferedImage(combinedWidth, maxHeight,
BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = combinedManaCostImage.createGraphics();
int currentPosition = 0;
for (int i = 0; i < manaSymbols.length; i++) {
BufferedImage tempCurrentImage = manaSymbolImages.get(manaSymbols[i].trim());
graphics.drawImage(tempCurrentImage, null, currentPosition, 0);
currentPosition += tempCurrentImage.getWidth();
}
graphics.dispose();
return (new ImageIcon(combinedManaCostImage));
}
/* Original source of this is here:
* https://stackoverflow.com/questions/15783014/jtextarea-on-jpanel-inside-jscrollpane-does-not-resize-properly
* And one update to it is here:
* */
private static class ScrollablePanel extends JPanel implements Scrollable {
#Override
public Dimension getPreferredScrollableViewportSize() {
return super.getPreferredSize();
}
#Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation,
int direction) {
return 16;
}
#Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation,
int direction) {
return 16;
}
#Override
public boolean getScrollableTracksViewportWidth() {
return true;
}
#Override
public boolean getScrollableTracksViewportHeight() {
boolean track = true;
Container parent = getParent();
if (parent instanceof JViewport) {
JViewport viewport = (JViewport) parent;
if (viewport.getHeight() < getPreferredSize().height) {
track = false;
}
}
return track;
}
}
}
I think that the issue is the way you insert your images, and most probably, from your combineSymbol method.
Here is the way to insert stuff in the JTextPane :
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame mainFrame = new JFrame("test");
mainFrame.setSize(300, 100);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = mainFrame.getContentPane();
pane.setLayout(new BorderLayout());
JTP jtp = new JTP();
pane.add(jtp);
mainFrame.setVisible(true);
}
});
}
static class JTP extends JTextPane {
JTP() {
HTMLEditorKit eKit = new HTMLEditorKit();
setEditorKit(eKit);
HTMLDocument htmlDoc = (HTMLDocument) getDocument();//the HTMLEditorKit automatically created an HTMLDocument
htmlDoc.setPreservesUnknownTags(false);//I advice you to put this line if you plan to insert some foreign HTML
//inserting plain text (just change null for an attributeSet for styled text)
try {
htmlDoc.insertString(0, "test", null);
} catch (BadLocationException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
//inserting images
insertIcon(new ImageIcon("image.png"));
insertIcon(new ImageIcon("image.png"));
//inserting components (With component, you should specify the yAlignment by yourself)
JLabel label = new JLabel(new ImageIcon("image.png"));
label.setAlignmentY(JLabel.TOP);
insertComponent(label);
}
}
}
But to make things easier, I strongly advice you to use a title line outside the JTextPane. Text editors aren't really made for text having different alignment on the same line. Here is what I would suggest :
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame mainFrame = new JFrame("test");
mainFrame.setSize(300, 100);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = mainFrame.getContentPane();
pane.setLayout(new BorderLayout());
pane.setBackground(Color.WHITE);
pane.add(new JTP());
pane.add(new Title(), BorderLayout.NORTH);
mainFrame.setVisible(true);
}
});
}
static class JTP extends JTextPane {
JTP() {
setEditable(false);
setOpaque(false);
HTMLEditorKit eKit = new HTMLEditorKit();
setEditorKit(eKit);
HTMLDocument htmlDoc = (HTMLDocument) getDocument();//the HTMLEditorKit automatically created an HTMLDocument
htmlDoc.setPreservesUnknownTags(false);//I advice you to put this line if you plan to insert some foreign HTML
//inserting plain text (just change null for an attributeSet for styled text)
try {
htmlDoc.insertString(0, "capacity : ", null);
} catch (BadLocationException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
//inserting images
insertIcon(new ImageIcon("image.png"));
insertIcon(new ImageIcon("image.png"));
//inserting components (With component, you should specify the yAlignment by yourself)
JLabel label = new JLabel(new ImageIcon("image.png"));
label.setAlignmentY(JLabel.TOP);
insertComponent(label);
}
}
static class Title extends JPanel {
Title() {
setLayout(new BorderLayout());
setOpaque(false);
add(new JLabel("<html><b>Card title</b></html>"), BorderLayout.CENTER);
add(new JLabel(new ImageIcon("image.png")), BorderLayout.EAST);
}
}
}
You can try to define your own TabStops to align icons.
If you know size of icon and width of JTextPane just add your content as
"Person Name -tab- icon" and set custom TabSet for the paragraph. The TabSet has just one TabStop. The TabStop position = jTextPaneWidth - iconWidth

JTextField permanent Position/Location?

So I am a having a problem regarding my JTextField.
What I'm trying to do is to put the JTextField box below the picture(map of a certain town).
Yeah, I used .setBounds and it was already below the image, but what I want to happen is that if I do .pack();, it must be still visible. Unfortunately, it wasn't.
I tried using the .setBorder(BorderFactory.createEmptyBorder(5,50,0,50)); and I saw that the box is below the picture but it is no longer available for putting a text.
And to conclude, I want the JTextField below the picture and still must be visible whenever I pack it.
Please Help. Thank you.
I am still on the stage of discovering new things about GUI.
Sorry for the noob question.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.JTextField;
class ProgDraftMain {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
ProgDraft gui = new ProgDraft();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setResizable(false);
gui.pack();
//gui.setSize(1000 , 1000);
gui.setVisible(true);
}
});
}
}
class ProgDraft extends JFrame {
private ImageIcon image1;
private JLabel label1;
private JTextField textField1;
ProgDraft() {
/***Panel**/
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.LEADING));
/***Title***/
JLabel title = new JLabel("Perimeter Check", JLabel.CENTER);
Font font = new Font("Gigi", Font.BOLD, 50);
title.setFont(font);
/***Image***/
ImageIcon pics = new ImageIcon(getClass().getResource("antipolo.png"));
JLabel logo = new JLabel(pics);
logo.setBorder(BorderFactory.createEmptyBorder(10, 70, 0, 50));
logo.setToolTipText("Ito raw kunware yung barangay.");
panel.add(logo);
/***Info ANtipolo***/
String text = "Ito kunware ang ANtipolo" + "<br>" +
"Marami ditong landslide areas" + "<br>" + "<br>" +
"Take care and stay safe!" + "<br>" +
"I love my dogs" + "<br>" + "<br>" +"<br>" +
"Please help!";
JLabel dog = new JLabel("<html><div style=\"text-align: center;\">" + text + "</html>");
dog.setBorder(BorderFactory.createEmptyBorder(5,50,0,50));
panel.add(dog);
/***JTextFieldski**/
JTextField textField = new JTextField(6);
textField.setBorder(BorderFactory.createEmptyBorder(5,50,0,50));
textField.setBounds(210,470,100,25);
panel.add(textField);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(textField, BorderLayout.SOUTH);
getContentPane().add(dog, BorderLayout.CENTER);
getContentPane().add(panel, BorderLayout.SOUTH);
getContentPane().add(title, BorderLayout.NORTH);
}
}
I think you took my advice yesterday about using EmptyBorder a little too far. You are trying to use it for pixel perfect position. That's not what they're meant for. Don't worry about pixel perfect positioning. Like I said yesterday, learn the layout managers and make use of them. Also you can wrap components in panels with different layout managers and nest the panels. You don't have to try and get everything perfect on one panel. Different layout managers have different features and qualities.
For instance What you are trying to do is add two different components to the BorderLayout.SOUTH. The thing about BorderLayout is each position can only have one components. The last one added wins. So what can we do? How about wrapping the two in a panel, then adding that panel to the SOUTH :-) Easy right?
Also in regards to the EmptyBorders, Make use the the JLabel api. You can setHorizontalAlignment to JLabel.CENTER. The default is JLabel.LEADING, so all the text is to the left. If you set it to the center, then it will be centered.
Also just FYI, setBounds will not work unless you are using null layouts, which I advise against. You don't use it.
Here is the refactor (using NO Empty Borders, letting the layout managers do the job we pay them to do)
import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.JTextField;
class ProgDraftMain {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ProgDraft gui = new ProgDraft();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setResizable(false);
gui.pack();
//gui.setSize(1000 , 1000);
gui.setVisible(true);
}
});
}
}
class ProgDraft extends JFrame {
private ImageIcon image1;
private JLabel label1;
private JTextField textField1;
ProgDraft() {
/**
* Main Panel
*/
JPanel mainPanel = new JPanel(new BorderLayout());
/**
* *Title**
*/
JLabel title = new JLabel("Perimeter Check", JLabel.CENTER);
Font font = new Font("Gigi", Font.BOLD, 50);
title.setFont(font);
mainPanel.add(title, BorderLayout.PAGE_START); // add title to top
/**
* *Info ANtipolo**
*/
String text = "Ito kunware ang ANtipolo" + "<br>"
+ "Marami ditong landslide areas" + "<br>" + "<br>"
+ "Take care and stay safe!" + "<br>"
+ "I love my dogs" + "<br>" + "<br>" + "<br>"
+ "Please help!";
JLabel dog = new JLabel("<html><div style=\"text-align: center;\">" + text + "</html>");
dog.setHorizontalAlignment(JLabel.CENTER);
mainPanel.add(dog); // add dog to center
/**
* *Image** ==========>>>>>> Make sure to change the image name back.
*/
ImageIcon pics = new ImageIcon(getClass().getResource("stackoverflow.png"));
JLabel logo = new JLabel(pics);
logo.setHorizontalAlignment(JLabel.CENTER);
//logo.setBorder(BorderFactory.createEmptyBorder(10, 70, 0, 50));
logo.setToolTipText("Ito raw kunware yung barangay.");
/**
* Wrapper for text field and icon
*/
JPanel iconFieldPanel = new JPanel(new BorderLayout());
JTextField textField = new JTextField(10);
iconFieldPanel.add(logo);
iconFieldPanel.add(textField, BorderLayout.PAGE_END);
JPanel iconFieldWrapper = new JPanel();
iconFieldWrapper.add(iconFieldPanel);
mainPanel.add(iconFieldWrapper, BorderLayout.PAGE_END); // add icon and field to bottom
getContentPane().add(mainPanel);
}
}
And pleeease do take some time to go over the link I provided for using layout managers. Study one at a time and get the hang of each. It's an art, so it'll take time, just like anything else.

Can't get my Jscrollpane working in my Jtextarea

I've looked around quite a lot on google and followed several examples however I can't seem to get my JScrollPane working on a textarea in a JPanel.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import javax.swing.event.*;
class main
{
public static void main(String Args[])
{
frame f1 = new frame();
}
}
class frame extends JFrame
{
JButton B = new JButton("B");
JButton button = new JButton("A");
JTextArea E = new JTextArea("some lines", 10, 20);
JScrollPane scrollBar = new JScrollPane(E);
JPanel grid = new JPanel ();
frame()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500,800);
setTitle("Mobile Phone App");
setLocationRelativeTo(null);
E.setLineWrap(true);
E.setEditable(false);
grid.add(button);
button.addActionListener(new action());
grid.add(B);
B.addActionListener(new action());
//grid.add(E);
grid.getContentPane().add(scrollBar);
add(grid);
setVisible(true);
}
class action implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
String V = E.getText();
if(e.getSource() == button)
{
E.setText(V + "A is pressed");
}
if(e.getSource() == B)
{
E.setText(V + "B is pressed");
}
}
}
}
Would be great if someone can see where I am going wrong. I added JscrollPane in which I added the text area "e" in it.
E.setColumns(10);
E.setRows(5);
E.setPreferredSize(new Dimension(10,5)); // delete this
Don't hardcode a preferred size. The preferred size is overriding your attempt to set the rows/columns. So get rid of that line.
Note, you can also specify the row/columns when you create the text area:
JTextArea textArea = new JTextArea(5, 10);
to provide a hint to the intial size of the text area. Now the text area can change in size as text is added or removed and the scrollbar will appear when needed.
Also follow standard java naming conventions. Variable names should NOT start with an upper case character.
Right I got it!
Basically I had to add it in differently...the way I was approaching it was wrong!
grid.add(scrollBar, BorderLayout.CENTER);

JTextArea won't show up unless I call append() on it

The following problem boggled my mind, so I came here for some help.
After experimenting I ended up with this block of code:
JTextArea chatPanel = null;
JScrollPane scrollPanel = null;
if(chatPanel == null)
{
chatPanel = new JTextArea("derp");
chatPanel.setEditable(false);
chatPanel.setForeground(new Color(10,191,26));
chatPanel.setOpaque(false);
scrollPanel = new JScrollPane(chatPanel);
scrollPanel.setOpaque(false);
scrollPanel.getViewport().setOpaque(false);
scrollPanel.setBorder(BorderFactory.createEmptyBorder());
}
//## marked area ##
scrollPanel.setBounds(9,596,435,138);
pane.add(scrollPanel);
The result? Nothing shows up. The text area with "derp" in it I expected is not there, just an empty scroll panel. Now, if I go to the ## marked area ## and replace it with this:
chatPanel.append("Hello.");
the chatPanel shows up fine in the scrollPanel, with its text being "derpHello.". Any ideas as per what's going on?
For the record, pane is a simple container with a null layout that otherwise displays eveyrthing fine. Declaration, just for the record:
Container pane = getContentPane()
pane.setLayout(null);
I have no problem with the following code, I can see the "derp" in green just fine:
import java.awt.Color;
import java.awt.Container;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class TestTextArea {
private void initUI() {
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextArea chatPanel = null;
JScrollPane scrollPanel = null;
Container pane = frame.getContentPane();
pane.setLayout(null);
if (chatPanel == null) {
chatPanel = new JTextArea("derp");
chatPanel.setEditable(false);
chatPanel.setForeground(new Color(10, 191, 26));
chatPanel.setOpaque(false);
scrollPanel = new JScrollPane(chatPanel);
scrollPanel.setOpaque(false);
scrollPanel.getViewport().setOpaque(false);
scrollPanel.setBorder(BorderFactory.createEmptyBorder());
}
// ## marked area ##
scrollPanel.setBounds(9, 596, 435, 138);
pane.add(scrollPanel);
frame.validate();
frame.setSize(600, 800);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTextArea().initUI();
}
});
}
}
Now, I would really advise you to use an appropriate LayoutManager instead of that null layout. That would allow you to use pack() and revalidate() and have a much simpler and more maintainable code.
There must be something else that your code does not illustrate for now. Try to put an SSCCE.
There is nothing in your JTextArea to display as you initialize it with the empty String. When you append something to it, there is effectively text inside.
Note that your JScrollPane will never try to resize your component inside (why else would it allow you to scroll?). Therefore, you will have to set a dimension on your JTextArea.
EDIT (after your code correction): I can see "derp" just fine with following code.
public class TextTest extends JFrame {
public TextTest () {
JPanel pane = new JPanel();
JTextArea chatPanel = null;
JScrollPane scrollPanel = null;
if(chatPanel == null)
{
chatPanel = new JTextArea("derp");
chatPanel.setEditable(false);
chatPanel.setForeground(new Color(10,191,26));
chatPanel.setOpaque(false);
scrollPanel = new JScrollPane(chatPanel);
scrollPanel.setOpaque(false);
scrollPanel.getViewport().setOpaque(false);
scrollPanel.setBorder(BorderFactory.createEmptyBorder());
}
//## marked area ##
scrollPanel.setBounds(9,596,435,138);
pane.add(scrollPanel);
setContentPane(pane);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new TextTest();
}
}

Categories

Resources